Repository: conan-io/conan

Issue:
Environment variable to set [general]default_profile 
To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [ ] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

This idea was initially proposed at https://github.com/conan-io/conan/issues/1221#issuecomment-403961457

It would be nice if there was an environment variable (perhaps `CONAN_DEFAULT_PROFILE`?) which, if set, would override `[general]default_profile` from `conan.conf `. In an IDE workflow, a project file might be set up to obtain its own dependencies by calling `conan install` (e.g. https://github.com/conan-io/cmake-conan), but it feels wrong to hard-code a desired profile into the call to conan install. Most project systems like this support multiple configurations (e.g. Qt Creator has [kits](http://doc.qt.io/qtcreator/creator-configuring-projects.html), MSVC supports setting up multiple configurations. conan_cmake_settings(...) makes an effort to reverse-engineer the settings from the compiler detection variables, but it's not particularly complete, and in any case a sophisticated profile might have content (e.g. build_requires for toolchains) arguably could never get in this fashion. 

IDE features to define a build template like this usually have a mechanism to add environment variables to the build invocation, and a way to set the default profile through the environment seems consistent with the existing ability to override specific settings from it using [CONAN_ENV_XXXX_YYYY](https://docs.conan.io/en/latest/reference/env_vars.html#conan-env-xxxx-yyyy).




Discussion:

Patch:
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
index 741fb2fb8..3efb42b2e 100644
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -290,8 +290,10 @@ class ConanClientConfigParser(ConfigParser, object):
         ret = os.environ.get("CONAN_DEFAULT_PROFILE_PATH", None)
         if ret:
             if not os.path.isabs(ret):
-                raise ConanException("Environment variable 'CONAN_DEFAULT_PROFILE_PATH' must point "
-                                     "to an absolute path.")
+                from conans.client.client_cache import PROFILES_FOLDER
+                profiles_folder = os.path.join(os.path.dirname(self.filename), PROFILES_FOLDER)
+                ret = os.path.abspath(os.path.join(profiles_folder, ret))
+
             if not os.path.exists(ret):
                 raise ConanException("Environment variable 'CONAN_DEFAULT_PROFILE_PATH' must point to "
                                      "an existing profile file.")
diff --git a/conans/client/output.py b/conans/client/output.py
index 8176cfe53..da8864d3a 100644
--- a/conans/client/output.py
+++ b/conans/client/output.py
@@ -100,9 +100,6 @@ class ConanOutput(object):
         self._stream.flush()
         self._color = tmp_color
 
-    def flush(self):
-        self._stream.flush()
-
 
 class ScopedOutput(ConanOutput):
     def __init__(self, scope, output):
diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py
index bee679558..51c0f896c 100644
--- a/conans/client/remote_manager.py
+++ b/conans/client/remote_manager.py
@@ -29,7 +29,6 @@ from conans.client.source import merge_directories
 from conans.util.env_reader import get_env
 from conans.search.search import filter_packages
 from conans.client.cmd.uploader import UPLOAD_POLICY_SKIP
-from conans.util import progress_bar
 
 
 class RemoteManager(object):
@@ -200,7 +199,7 @@ class RemoteManager(object):
         duration = time.time() - t1
         log_recipe_download(conan_reference, duration, remote.name, zipped_files)
 
-        unzip_and_get_files(zipped_files, dest_folder, EXPORT_TGZ_NAME, output=self._output)
+        unzip_and_get_files(zipped_files, dest_folder, EXPORT_TGZ_NAME)
         # Make sure that the source dir is deleted
         rm_conandir(self._client_cache.source(conan_reference))
         touch_folder(dest_folder)
@@ -221,8 +220,7 @@ class RemoteManager(object):
         duration = time.time() - t1
         log_recipe_sources_download(conan_reference, duration, remote.name, zipped_files)
 
-        unzip_and_get_files(zipped_files, export_sources_folder, EXPORT_SOURCES_TGZ_NAME,
-                            output=self._output)
+        unzip_and_get_files(zipped_files, export_sources_folder, EXPORT_SOURCES_TGZ_NAME)
         c_src_path = os.path.join(export_sources_folder, EXPORT_SOURCES_DIR_OLD)
         if os.path.exists(c_src_path):
             merge_directories(c_src_path, export_sources_folder)
@@ -243,7 +241,7 @@ class RemoteManager(object):
             zipped_files = self._call_remote(remote, "get_package", package_reference, dest_folder)
             duration = time.time() - t1
             log_package_download(package_reference, duration, remote, zipped_files)
-            unzip_and_get_files(zipped_files, dest_folder, PACKAGE_TGZ_NAME, output=self._output)
+            unzip_and_get_files(zipped_files, dest_folder, PACKAGE_TGZ_NAME)
             # Issue #214 https://github.com/conan-io/conan/issues/214
             touch_folder(dest_folder)
             if get_env("CONAN_READ_ONLY_CACHE", False):
@@ -413,22 +411,21 @@ def compress_files(files, symlinks, name, dest_dir, output=None):
     return tgz_path
 
 
-def unzip_and_get_files(files, destination_dir, tgz_name, output):
+def unzip_and_get_files(files, destination_dir, tgz_name):
     """Moves all files from package_files, {relative_name: tmp_abs_path}
     to destination_dir, unzipping the "tgz_name" if found"""
 
     tgz_file = files.pop(tgz_name, None)
     check_compressed_files(tgz_name, files)
     if tgz_file:
-        uncompress_file(tgz_file, destination_dir, output=output)
+        uncompress_file(tgz_file, destination_dir)
         os.remove(tgz_file)
 
 
-def uncompress_file(src_path, dest_folder, output):
+def uncompress_file(src_path, dest_folder):
     t1 = time.time()
     try:
-        with progress_bar.open_binary(src_path, desc="Decompressing %s" % os.path.basename(src_path),
-                                      output=output) as file_handler:
+        with open(src_path, 'rb') as file_handler:
             tar_extract(file_handler, dest_folder)
     except Exception as e:
         error_msg = "Error while downloading/extracting files to %s\n%s\n" % (dest_folder, str(e))
diff --git a/conans/requirements.txt b/conans/requirements.txt
index 24a491e63..a7e8b1779 100644
--- a/conans/requirements.txt
+++ b/conans/requirements.txt
@@ -12,4 +12,3 @@ future==0.16.0
 pygments>=2.0, <3.0
 astroid>=1.6.5
 deprecation>=2.0, <2.1
-tqdm==4.20.0
diff --git a/conans/util/progress_bar.py b/conans/util/progress_bar.py
deleted file mode 100644
index 470528faf..000000000
--- a/conans/util/progress_bar.py
+++ /dev/null
@@ -1,72 +0,0 @@
-
-import os
-from tqdm import tqdm
-from contextlib import contextmanager
-
-TIMEOUT_BEAT_SECONDS = 30
-TIMEOUT_BEAT_CHARACTER = '.'
-
-
-class _FileReaderWithProgressBar(object):
-
-    tqdm_defaults = {'unit': 'B',
-                     'unit_scale': True,
-                     'unit_divisor': 1024,
-                     'ascii': False,  # Fancy output (forces unicode progress bar)
-                     }
-
-    def __init__(self, fileobj, output, desc=None):
-        pb_kwargs = self.tqdm_defaults.copy()
-        self._ori_output = output
-
-        # If there is no terminal, just print a beat every TIMEOUT_BEAT seconds.
-        if not output.is_terminal:
-            output = _NoTerminalOutput(output)
-            pb_kwargs['mininterval'] = TIMEOUT_BEAT_SECONDS
-
-        self._output = output
-        self._fileobj = fileobj
-        self.seek(0, os.SEEK_END)
-        self._pb = tqdm(total=self.tell(), desc=desc, file=output, **pb_kwargs)
-        self.seek(0)
-
-    def seek(self, *args, **kwargs):
-        return self._fileobj.seek(*args, **kwargs)
-
-    def tell(self):
-        return self._fileobj.tell()
-
-    def read(self, size):
-        prev = self.tell()
-        ret = self._fileobj.read(size)
-        self._pb.update(self.tell() - prev)
-        return ret
-
-    def pb_close(self):
-        self._pb.close()
-
-    def pb_write(self, message):
-        """ Allow to write messages to output without interfering with the progress bar """
-        tqdm.write(message, file=self._ori_output)
-
-
-class _NoTerminalOutput(object):
-    """ Helper class: Replace every message sent to it with a fixed one """
-    def __init__(self, output):
-        self._output = output
-
-    def write(self, *args, **kwargs):
-        self._output.write(TIMEOUT_BEAT_CHARACTER)
-
-    def flush(self):
-        self._output.flush()
-
-
-@contextmanager
-def open_binary(path, output, **kwargs):
-    with open(path, mode='rb') as f:
-        file_wrapped = _FileReaderWithProgressBar(f, output=output, **kwargs)
-        yield file_wrapped
-        file_wrapped.pb_close()
-        if not output.is_terminal:
-            output.write("\n")


Test patch:
diff --git a/conans/test/functional/default_profile_test.py b/conans/test/functional/default_profile_test.py
index d868aaa92..3bb9fda84 100644
--- a/conans/test/functional/default_profile_test.py
+++ b/conans/test/functional/default_profile_test.py
@@ -7,6 +7,7 @@ from conans.test.utils.test_files import temp_folder
 from conans.test.utils.tools import TestClient
 from conans.util.files import save
 from conans import tools
+from conans.client.client_cache import PROFILES_FOLDER
 
 
 class DefaultProfileTest(unittest.TestCase):
@@ -161,10 +162,15 @@ class MyConanfile(ConanFile):
             self.assertIn(">>> " + env_variable, client.out)
 
         # Use relative path defined in environment variable
-        with tools.environment_append({'CONAN_DEFAULT_PROFILE_PATH': '../whatever'}):
-            client.run("create . name/version@user/channel", ignore_error=True)
-            self.assertIn("Environment variable 'CONAN_DEFAULT_PROFILE_PATH' must point to "
-                          "an absolute path", client.out)
+        env_variable = "env_variable=relative_profile"
+        rel_path = os.path.join('..', 'env_rel_profile')
+        self.assertFalse(os.path.isabs(rel_path))
+        default_profile_path = os.path.join(client.client_cache.conan_folder,
+                                            PROFILES_FOLDER, rel_path)
+        save(default_profile_path, "[env]\n" + env_variable)
+        with tools.environment_append({'CONAN_DEFAULT_PROFILE_PATH': rel_path}):
+            client.run("create . name/version@user/channel")
+            self.assertIn(">>> " + env_variable, client.out)
 
         # Use non existing path
         profile_path = os.path.join(tmp, "this", "is", "a", "path")