Repository: conan-io/conan

Issue:
[question] do not save username and password in exported scm object

We are used the scm object as bellow:
```
scm = {
        'type': 'git',
        'url': 'auto',
        'revision': 'auto',
        'username': tools.get_env("GIT_USERNAME", None),
        'password': tools.get_env("GIT_PASSWORD", None)
}
```

In CI we set the env var GIT_USERNAME and GIT_PASSWORD, however we noticed that the actual username and password got replaced and exported as part of the recipe.
This is not convenient at all as everyone now have access to the CI git credentials. 

Any suggestion on how to deal with this ? 
Ideally, username and password should be only read from env var if defined.

Thanks,
Walid
 




- [ ] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).

Discussion:
jgsogo: Can you provide some early feedback/review about the implementation, @danimtb? I feel like this is all that we need... do you miss anything, any test?  Thanks! 🙌 

Patch:
diff --git a/conans/client/cmd/export.py b/conans/client/cmd/export.py
index e6f89b90d..8aee04fce 100644
--- a/conans/client/cmd/export.py
+++ b/conans/client/cmd/export.py
@@ -3,6 +3,7 @@ import os
 import shutil
 
 import six
+import yaml
 
 from conans.client.file_copier import FileCopier
 from conans.client.output import Color, ScopedOutput
@@ -59,6 +60,7 @@ def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,
     """
     loader, cache, hook_manager, output = app.loader, app.cache, app.hook_manager, app.out
     revisions_enabled = app.config.revisions_enabled
+    scm_to_conandata = app.config.scm_to_conandata
     conanfile = loader.load_export(conanfile_path, name, version, user, channel)
 
     # FIXME: Conan 2.0, deprecate CONAN_USER AND CONAN_CHANNEL and remove this try excepts
@@ -123,8 +125,8 @@ def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,
         # Calculate the "auto" values and replace in conanfile.py
         scm_data, local_src_folder = _capture_scm_auto_fields(conanfile,
                                                               os.path.dirname(conanfile_path),
-                                                              package_layout.export(), output,
-                                                              ignore_dirty)
+                                                              package_layout, output,
+                                                              ignore_dirty, scm_to_conandata)
         # Clear previous scm_folder
         modified_recipe = False
         scm_sources_folder = package_layout.scm_sources()
@@ -201,9 +203,9 @@ def _check_settings_for_warnings(conanfile, output):
     if not conanfile.settings:
         return
     try:
-        if not 'os_build' in conanfile.settings:
+        if 'os_build' not in conanfile.settings:
             return
-        if not 'os' in conanfile.settings:
+        if 'os' not in conanfile.settings:
             return
 
         output.writeln("*"*60, front=Color.BRIGHT_RED)
@@ -218,7 +220,7 @@ def _check_settings_for_warnings(conanfile, output):
         pass
 
 
-def _capture_scm_auto_fields(conanfile, conanfile_dir, destination_folder, output, ignore_dirty):
+def _capture_scm_auto_fields(conanfile, conanfile_dir, package_layout, output, ignore_dirty, scm_to_conandata):
     """Deduce the values for the scm auto fields or functions assigned to 'url' or 'revision'
        and replace the conanfile.py contents.
        Returns a tuple with (scm_data, path_to_scm_local_directory)"""
@@ -232,7 +234,7 @@ def _capture_scm_auto_fields(conanfile, conanfile_dir, destination_folder, outpu
 
     if not captured:
         # We replace not only "auto" values, also evaluated functions (e.g from a python_require)
-        _replace_scm_data_in_conanfile(os.path.join(destination_folder, "conanfile.py"), scm_data)
+        _replace_scm_data_in_recipe(package_layout, scm_data, scm_to_conandata)
         return scm_data, None
 
     if not scm.is_pristine() and not ignore_dirty:
@@ -260,11 +262,29 @@ def _capture_scm_auto_fields(conanfile, conanfile_dir, destination_folder, outpu
         output.success("Revision deduced by 'auto': %s" % scm_data.revision)
 
     local_src_path = scm.get_local_path_to_url(scm_data.url)
-    _replace_scm_data_in_conanfile(os.path.join(destination_folder, "conanfile.py"), scm_data)
+    _replace_scm_data_in_recipe(package_layout, scm_data, scm_to_conandata)
 
     return scm_data, local_src_path
 
 
+def _replace_scm_data_in_recipe(package_layout, scm_data, scm_to_conandata):
+    if scm_to_conandata:
+        conandata_path = os.path.join(package_layout.export(), DATA_YML)
+        conandata_yml = {}
+        if os.path.exists(conandata_path):
+            conandata_yml = yaml.safe_load(load(conandata_path))
+            if '.conan' in conandata_yml:
+                raise ConanException("Field '.conan' inside '{}' file is reserved to Conan usage.".format(DATA_YML))
+        scm_data_copied = scm_data.as_dict()
+        scm_data_copied.pop('username', None)
+        scm_data_copied.pop('password', None)
+        conandata_yml['.conan'] = {'scm': scm_data_copied}
+
+        save(conandata_path, yaml.safe_dump(conandata_yml, default_flow_style=False))
+    else:
+        _replace_scm_data_in_conanfile(package_layout.conanfile(), scm_data)
+
+
 def _replace_scm_data_in_conanfile(conanfile_path, scm_data):
     # Parsing and replacing the SCM field
     content = load(conanfile_path)
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
index a97bc7ae9..685663f11 100644
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -155,6 +155,7 @@ default_package_id_mode = semver_direct_mode # environment CONAN_DEFAULT_PACKAGE
 # temp_test_folder = True             # environment CONAN_TEMP_TEST_FOLDER
 
 # cacert_path                         # environment CONAN_CACERT_PATH
+# scm_to_conandata                    # environment CONAN_SCM_TO_CONANDATA
 
 [storage]
 # This is the default path, but you can write your own. It must be an absolute path or a
@@ -392,6 +393,16 @@ class ConanClientConfigParser(ConfigParser, object):
         except ConanException:
             return False
 
+    @property
+    def scm_to_conandata(self):
+        try:
+            scm_to_conandata = get_env("CONAN_SCM_TO_CONANDATA")
+            if scm_to_conandata is None:
+                scm_to_conandata = self.get_item("general.scm_to_conandata")
+            return scm_to_conandata.lower() in ("1", "true")
+        except ConanException:
+            return False
+
     @property
     def default_package_id_mode(self):
         try:
diff --git a/conans/client/conf/detect.py b/conans/client/conf/detect.py
index 1b3310d6e..de0b8601f 100644
--- a/conans/client/conf/detect.py
+++ b/conans/client/conf/detect.py
@@ -10,7 +10,8 @@ from conans.model.version import Version
 
 
 def _execute(command):
-    proc = Popen(command, shell=True, bufsize=1, stdout=PIPE, stderr=STDOUT)
+    proc = Popen(command, shell=True, bufsize=1, universal_newlines=True, stdout=PIPE,
+                 stderr=STDOUT)
 
     output_buffer = []
     while True:
diff --git a/conans/client/file_copier.py b/conans/client/file_copier.py
index fa150e4cb..116dbc3b3 100644
--- a/conans/client/file_copier.py
+++ b/conans/client/file_copier.py
@@ -3,6 +3,7 @@ import os
 import shutil
 from collections import defaultdict
 
+from conans.errors import ConanException
 from conans.util.files import mkdir, walk
 
 
@@ -175,7 +176,12 @@ class FileCopier(object):
             link = os.readlink(src_link)
             # Absoluted path symlinks are a problem, convert it to relative
             if os.path.isabs(link):
-                link = os.path.relpath(link, os.path.dirname(src_link))
+                try:
+                    link = os.path.relpath(link, os.path.dirname(src_link))
+                except ValueError as e:
+                    # https://github.com/conan-io/conan/issues/6197 fails if Windows and other Drive
+                    raise ConanException("Symlink '%s' pointing to '%s' couldn't be made relative:"
+                                         " %s" % (src_link, link, str(e)))
 
             dst_link = os.path.join(dst, linked_folder)
             try:
diff --git a/conans/client/generators/cmake_common.py b/conans/client/generators/cmake_common.py
index fb76e8bdb..1159ce8b7 100644
--- a/conans/client/generators/cmake_common.py
+++ b/conans/client/generators/cmake_common.py
@@ -289,14 +289,15 @@ class CMakeCommonMacros:
 
     conan_set_std = textwrap.dedent("""
         macro(conan_set_std)
+            conan_message(STATUS "Conan: Adjusting language standard")
             # Do not warn "Manually-specified variables were not used by the project"
             set(ignorevar "${CONAN_STD_CXX_FLAG}${CONAN_CMAKE_CXX_STANDARD}${CONAN_CMAKE_CXX_EXTENSIONS}")
             if (CMAKE_VERSION VERSION_LESS "3.1" OR
                 (CMAKE_VERSION VERSION_LESS "3.12" AND ("${CONAN_CMAKE_CXX_STANDARD}" STREQUAL "20" OR "${CONAN_CMAKE_CXX_STANDARD}" STREQUAL "gnu20")))
-            if(CONAN_STD_CXX_FLAG)
-                conan_message(STATUS "Conan setting CXX_FLAGS flags: ${CONAN_STD_CXX_FLAG}")
-                set(CMAKE_CXX_FLAGS "${CONAN_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
-            endif()
+                if(CONAN_STD_CXX_FLAG)
+                    conan_message(STATUS "Conan setting CXX_FLAGS flags: ${CONAN_STD_CXX_FLAG}")
+                    set(CMAKE_CXX_FLAGS "${CONAN_STD_CXX_FLAG} ${CMAKE_CXX_FLAGS}")
+                endif()
             else()
                 if(CONAN_CMAKE_CXX_STANDARD)
                     conan_message(STATUS "Conan setting CPP STANDARD: ${CONAN_CMAKE_CXX_STANDARD} WITH EXTENSIONS ${CONAN_CMAKE_CXX_EXTENSIONS}")
@@ -309,6 +310,7 @@ class CMakeCommonMacros:
 
     conan_set_rpath = textwrap.dedent("""
         macro(conan_set_rpath)
+            conan_message(STATUS "Conan: Adjusting default RPATHs Conan policies")
             if(APPLE)
                 # https://cmake.org/Wiki/CMake_RPATH_handling
                 # CONAN GUIDE: All generated libraries should have the id and dependencies to other
@@ -822,12 +824,10 @@ macro(conan_basic_setup)
 
     if(NOT ARGUMENTS_SKIP_RPATH AND NOT ARGUMENTS_KEEP_RPATHS)
         # Parameter has renamed, but we keep the compatibility with old SKIP_RPATH
-        conan_message(STATUS "Conan: Adjusting default RPATHs Conan policies")
         conan_set_rpath()
     endif()
 
     if(NOT ARGUMENTS_SKIP_STD)
-        conan_message(STATUS "Conan: Adjusting language standard")
         conan_set_std()
     endif()
 
diff --git a/conans/client/loader.py b/conans/client/loader.py
index 2bf0c25a2..b219bd215 100644
--- a/conans/client/loader.py
+++ b/conans/client/loader.py
@@ -59,10 +59,15 @@ class ConanFileLoader(object):
             if self._pyreq_loader:
                 self._pyreq_loader.load_py_requires(conanfile, lock_python_requires, self)
 
-            conanfile.conan_data = self._load_data(conanfile_path)
-
-            self._cached_conanfile_classes[conanfile_path] = (conanfile, lock_python_requires,
-                                                              module)
+            # Load and populate dynamic fields from the data file
+            conan_data = self._load_data(conanfile_path)
+            conanfile.conan_data = conan_data
+            if conan_data and '.conan' in conan_data:
+                scm_data = conan_data['.conan'].get('scm')
+                if scm_data:
+                    conanfile.scm.update(scm_data)
+
+            self._cached_conanfile_classes[conanfile_path] = (conanfile, lock_python_requires, module)
             return conanfile(self._output, self._runner, display, user, channel), module
         except ConanException as e:
             raise ConanException("Error loading conanfile at '{}': {}".format(conanfile_path, e))
diff --git a/conans/model/scm.py b/conans/model/scm.py
index 172cf8a3a..23c8125da 100644
--- a/conans/model/scm.py
+++ b/conans/model/scm.py
@@ -61,7 +61,7 @@ class SCMData(object):
             return self.revision
         raise ConanException("Not implemented recipe revision for %s" % self.type)
 
-    def __repr__(self):
+    def as_dict(self):
         d = {"url": self.url, "revision": self.revision, "username": self.username,
              "password": self.password, "type": self.type,
              "subfolder": self.subfolder, "submodule": self.submodule}
@@ -70,6 +70,10 @@ class SCMData(object):
         if self.verify_ssl != self.VERIFY_SSL_DEFAULT:
             d.update({"verify_ssl": self.verify_ssl})
         d = {k: v for k, v in d.items() if v is not None}
+        return d
+
+    def __repr__(self):
+        d = self.as_dict()
 
         def _kv_to_string(key, value):
             if isinstance(value, bool):


Test patch:
diff --git a/conans/test/functional/conanfile/conan_data_test.py b/conans/test/functional/conanfile/conan_data_test.py
index 993faf120..6c4036b67 100644
--- a/conans/test/functional/conanfile/conan_data_test.py
+++ b/conans/test/functional/conanfile/conan_data_test.py
@@ -1,4 +1,5 @@
 import os
+import textwrap
 import unittest
 
 from bottle import static_file
@@ -7,6 +8,7 @@ from nose.plugins.attrib import attr
 from conans.model.ref import ConanFileReference
 from conans.test.utils.test_files import tgz_with_contents
 from conans.test.utils.tools import TestClient, StoppableThreadBottle
+from conans.util.files import md5sum, sha1sum, sha256sum, load
 
 
 class ConanDataTest(unittest.TestCase):
@@ -83,43 +85,52 @@ sources:
     @attr("slow")
     @attr('local_bottle')
     def conan_data_as_source_test(self):
-
-        tgz_path = tgz_with_contents({"foo.txt": "bar"})
+        tgz_path = tgz_with_contents({"foo.txt": "foo"})
+        md5_value = "2ef49b5a102db1abb775eaf1922d5662"
+        sha1_value = "18dbea2d9a97bb9e9948604a41976bba5b5940bf"
+        sha256_value = "9619013c1f7b83cca4bf3f336f8b4525a23d5463e0768599fe5339e02dd0a338"
+        self.assertEqual(md5_value, md5sum(tgz_path))
+        self.assertEqual(sha1_value, sha1sum(tgz_path))
+        self.assertEqual(sha256_value, sha256sum(tgz_path))
 
         # Instance stoppable thread server and add endpoints
         thread = StoppableThreadBottle()
 
         @thread.server.get("/myfile.tar.gz")
         def get_file():
-            return static_file(os.path.basename(tgz_path), root=os.path.dirname(tgz_path))
+            return static_file(os.path.basename(tgz_path), root=os.path.dirname(tgz_path),
+                               mimetype="")
 
         thread.run_server()
 
         client = TestClient()
-        conanfile = """
-from conans import ConanFile, tools
-
-class Lib(ConanFile):
- 
-    def source(self):
-        tools.get(**self.conan_data["sources"]["all"])
-        self.output.info("OK!")
-"""
+        conanfile = textwrap.dedent("""
+            from conans import ConanFile, tools
+
+            class Lib(ConanFile):
+                def source(self):
+                    data = self.conan_data["sources"]["all"]
+                    tools.get(**data)
+                    self.output.info("OK!")
+            """)
+        conandata = textwrap.dedent("""
+            sources:
+              all:
+                url: "http://localhost:{}/myfile.tar.gz"
+                md5: "{}"
+                sha1: "{}"
+                sha256: "{}"
+            """)
         client.save({"conanfile.py": conanfile,
-                     "conandata.yml": """
-sources:
-  all:
-    url: "http://localhost:{}/myfile.tar.gz"
-    md5: "530e88952844f62f4b322ca13191062e"
-    sha1: "fae807733fcc7d1f22354755d468b748ab972a4d"
-    sha256: "8ac04f26347c82b2305dd3beb9c24d81e275f5c30cd4840f94cf31dfa8eaf381"                   
-""".format(thread.port)})
+                     "conandata.yml": conandata.format(thread.port, md5_value, sha1_value,
+                                                       sha256_value)})
         ref = ConanFileReference.loads("Lib/0.1@user/testing")
         client.run("create . {}".format(ref))
         self.assertIn("OK!", client.out)
 
         source_folder = client.cache.package_layout(ref).source()
-        self.assertTrue(os.path.exists(os.path.join(source_folder, "foo.txt")))
+        downloaded_file = os.path.join(source_folder, "foo.txt")
+        self.assertEqual("foo", load(downloaded_file))
 
     def invalid_yml_test(self):
         client = TestClient()
@@ -133,4 +144,5 @@ class Lib(ConanFile):
         ref = ConanFileReference.loads("Lib/0.1@user/testing")
         client.run("create . {}".format(ref), assert_error=True)
         self.assertIn("ERROR: Error loading conanfile at", client.out)
-        self.assertIn(": Invalid yml format at conandata.yml: while scanning a block scalar", client.out)
+        self.assertIn(": Invalid yml format at conandata.yml: while scanning a block scalar",
+                      client.out)
diff --git a/conans/test/functional/scm/test_scm_to_conandata.py b/conans/test/functional/scm/test_scm_to_conandata.py
new file mode 100644
index 000000000..750743963
--- /dev/null
+++ b/conans/test/functional/scm/test_scm_to_conandata.py
@@ -0,0 +1,161 @@
+import os
+import tempfile
+import textwrap
+import unittest
+
+import yaml
+
+from conans.client.graph.python_requires import ConanPythonRequire
+from conans.client.loader import ConanFileLoader
+from conans.client.tools.env import environment_append
+from conans.model.ref import ConanFileReference
+from conans.paths import DATA_YML
+from conans.test.utils.tools import TestBufferConanOutput, TestClient
+from conans.test.utils.tools import create_local_git_repo
+from conans.util.files import load
+from conans.util.files import save_files
+
+
+class SCMDataToConanDataTestCase(unittest.TestCase):
+    ref = ConanFileReference.loads("name/version@")
+
+    def test_plain_recipe(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conans import ConanFile
+            
+            class Recipe(ConanFile):
+                scm = {"type": "git", "url": "myurl", "revision": "myrev",
+                       "username": "myuser", "password": os.environ.get("SECRET", None),}
+        """)
+        t = TestClient()
+        t.save({'conanfile.py': conanfile})
+        t.run("config set general.scm_to_conandata=1")
+        t.run("export . name/version@")
+
+        # Check exported files
+        package_layout = t.cache.package_layout(self.ref)
+        exported_conanfile = load(package_layout.conanfile())
+        self.assertEqual(exported_conanfile, conanfile)
+        exported_conandata = load(os.path.join(package_layout.export(), DATA_YML))
+        conan_data = yaml.safe_load(exported_conandata)
+        self.assertDictEqual(conan_data['.conan']['scm'], {"type": "git", "url": "myurl", "revision": "myrev"})
+
+        # Check the recipe gets the proper values
+        t.run("inspect name/version@ -a scm")
+        self.assertIn("password: None", t.out)
+        self.assertIn("username: myuser", t.out)
+        with environment_append({"SECRET": "42"}):
+            t.run("inspect name/version@ -a scm")
+            self.assertIn("password: 42", t.out)
+            self.assertIn("username: myuser", t.out)
+
+    def test_save_special_chars(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conans import ConanFile
+
+            class Recipe(ConanFile):
+                scm = {"type": "git", "url": 'weir"d', "revision": 123,
+                       "subfolder": "weir\\"d", "submodule": "don't"}
+        """)
+        t = TestClient()
+        t.save({'conanfile.py': conanfile})
+        t.run("config set general.scm_to_conandata=1")
+        t.run("export . name/version@")
+
+        # Check exported files
+        package_layout = t.cache.package_layout(self.ref)
+        exported_conanfile = load(package_layout.conanfile())
+        self.assertEqual(exported_conanfile, conanfile)
+        exported_conandata = load(os.path.join(package_layout.export(), DATA_YML))
+        conan_data = yaml.safe_load(exported_conandata)
+        self.assertDictEqual(conan_data['.conan']['scm'], {"type": "git", "url": 'weir"d', "revision": 123,
+                                                           "subfolder": "weir\"d", "submodule": "don't"})
+
+        # Check the recipe gets the proper values
+        t.run("inspect name/version@ -a scm")
+        self.assertIn("revision: 123", t.out)
+        self.assertIn('subfolder: weir"d', t.out)
+        self.assertIn("submodule: don't", t.out)
+        self.assertIn("revision: 123", t.out)
+        self.assertIn('url: weir"d', t.out)
+
+    def test_auto_is_replaced(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conans import ConanFile
+
+            class Recipe(ConanFile):
+                scm = {"type": "git", "url": "auto", "revision": "auto"}
+        """)
+        t = TestClient()
+        t.save({'conanfile.py': conanfile})
+        _, commit = create_local_git_repo(folder=t.current_folder)
+        t.run_command('git remote add origin https://myrepo.com.git')
+        t.run("config set general.scm_to_conandata=1")
+        t.run("export . name/version@")
+
+        # Check exported files
+        package_layout = t.cache.package_layout(self.ref)
+        exported_conanfile = load(package_layout.conanfile())
+        self.assertEqual(exported_conanfile, conanfile)
+        exported_conandata = load(os.path.join(package_layout.export(), DATA_YML))
+        conan_data = yaml.safe_load(exported_conandata)
+        self.assertDictEqual(conan_data['.conan']['scm'], {"type": "git", "url": 'https://myrepo.com.git',
+                                                           "revision": commit})
+
+        # Check the recipe gets the proper values
+        t.run("inspect name/version@ -a scm")
+        self.assertIn("revision: {}".format(commit), t.out)
+        self.assertIn("type: git", t.out)
+        self.assertIn("url: https://myrepo.com.git", t.out)
+
+    def test_existing_field(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conans import ConanFile
+
+            class Recipe(ConanFile):
+                scm = {"type": "git", "url": "myurl", "revision": "myrev",
+                       "username": "myuser", "password": os.environ.get("SECRET", None),}
+        """)
+        t = TestClient()
+        t.save({'conanfile.py': conanfile,
+                DATA_YML: yaml.safe_dump({'.conan': {'scm_data': {}}}, default_flow_style=False)})
+
+        # Without activating the behavior, it works
+        t.run("export . name/version@")
+
+        # It fails with it activated
+        t.run("config set general.scm_to_conandata=1")
+        t.run("export . name/version@", assert_error=True)
+        self.assertIn("ERROR: Field '.conan' inside 'conandata.yml' file is reserved to Conan usage.", t.out)
+
+
+class ParseSCMFromConanDataTestCase(unittest.TestCase):
+    loader = ConanFileLoader(runner=None, output=TestBufferConanOutput(),
+                             python_requires=ConanPythonRequire(None, None))
+
+    def test_parse_data(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conans import ConanFile
+
+            class Recipe(ConanFile):
+                scm = {"type": "git", "url": "auto", "revision": "auto"}
+        """)
+        conan_data = {
+            'something_else': {},
+            '.conan': {'scm': {
+                'type': 'git',
+                'url': 'http://myrepo.com',
+                'shallow': False,
+                'revision': 'abcdefghijk'
+            }}}
+        test_folder = tempfile.mkdtemp()
+        save_files(test_folder, {'conanfile.py': conanfile,
+                                 DATA_YML: yaml.safe_dump(conan_data, default_flow_style=False)})
+
+        conanfile, _ = self.loader.load_basic_module(conanfile_path=os.path.join(test_folder, 'conanfile.py'))
+        self.assertDictEqual(conanfile.scm, conan_data['.conan']['scm'])
diff --git a/conans/test/unittests/client/cmd/export/test_capture_export_scm_data.py b/conans/test/unittests/client/cmd/export/test_capture_export_scm_data.py
index c40a329d3..178549281 100644
--- a/conans/test/unittests/client/cmd/export/test_capture_export_scm_data.py
+++ b/conans/test/unittests/client/cmd/export/test_capture_export_scm_data.py
@@ -12,9 +12,10 @@ from conans.model.ref import ConanFileReference
 from conans.test.utils.test_files import temp_folder
 from conans.test.utils.tools import create_local_git_repo, TestBufferConanOutput
 from conans.util.files import save
+from conans.paths.package_layouts.package_cache_layout import PackageCacheLayout
 
 
-@mock.patch("conans.client.cmd.export._replace_scm_data_in_conanfile", return_value=None)
+@mock.patch("conans.client.cmd.export._replace_scm_data_in_recipe", return_value=None)
 class CaptureExportSCMDataTest(unittest.TestCase):
 
     def setUp(self):
@@ -45,9 +46,10 @@ class CaptureExportSCMDataTest(unittest.TestCase):
         scm_data, _ = _capture_scm_auto_fields(
             conanfile=conanfile,
             conanfile_dir=self.conanfile_dir,
-            destination_folder="",
+            package_layout=None,
             output=output,
-            ignore_dirty=True)
+            ignore_dirty=True,
+            scm_to_conandata=False)
 
         self.assertEqual(scm_data.url, url)
         self.assertEqual(scm_data.revision, self.rev)
@@ -71,9 +73,10 @@ class CaptureExportSCMDataTest(unittest.TestCase):
         scm_data, _ = _capture_scm_auto_fields(
             conanfile=conanfile,
             conanfile_dir=self.conanfile_dir,
-            destination_folder="",
+            package_layout=None,
             output=output,
-            ignore_dirty=False)
+            ignore_dirty=False,
+            scm_to_conandata=False)
 
         self.assertEqual(scm_data.url, url)
         if is_pristine:
@@ -100,9 +103,10 @@ class CaptureExportSCMDataTest(unittest.TestCase):
         scm_data, _ = _capture_scm_auto_fields(
                     conanfile=conanfile,
                     conanfile_dir=self.conanfile_dir,
-                    destination_folder="",
+                    package_layout=None,
                     output=output,
-                    ignore_dirty=True)
+                    ignore_dirty=True,
+                    scm_to_conandata=False)
 
         self.assertEqual(scm_data.url, url)
         self.assertEqual(scm_data.revision, self.rev)
diff --git a/conans/test/unittests/client/generators/cmake_test.py b/conans/test/unittests/client/generators/cmake_test.py
index 6cf3d5160..dc40bab9a 100644
--- a/conans/test/unittests/client/generators/cmake_test.py
+++ b/conans/test/unittests/client/generators/cmake_test.py
@@ -230,12 +230,10 @@ class CMakeGeneratorTest(unittest.TestCase):
 
     if(NOT ARGUMENTS_SKIP_RPATH AND NOT ARGUMENTS_KEEP_RPATHS)
         # Parameter has renamed, but we keep the compatibility with old SKIP_RPATH
-        conan_message(STATUS "Conan: Adjusting default RPATHs Conan policies")
         conan_set_rpath()
     endif()
 
     if(NOT ARGUMENTS_SKIP_STD)
-        conan_message(STATUS "Conan: Adjusting language standard")
         conan_set_std()
     endif()
 
diff --git a/conans/test/utils/test_files.py b/conans/test/utils/test_files.py
index 176476e9d..b549374aa 100644
--- a/conans/test/utils/test_files.py
+++ b/conans/test/utils/test_files.py
@@ -1,18 +1,19 @@
 import os
 import platform
 import shutil
+import tarfile
 import tempfile
 
 import time
 from six import BytesIO
 
-from conans.client.tools.files import untargz, chdir
+from conans.client.tools.files import untargz
 from conans.client.tools.win import get_cased_path
 from conans.errors import ConanException
 from conans.paths import PACKAGE_TGZ_NAME
 from conans.test import CONAN_TEST_FOLDER
 from conans.test.utils.cpp_test_files import cpp_hello_conan_files, cpp_hello_source_files
-from conans.util.files import mkdir_tmp
+from conans.util.files import gzopen_without_timestamps
 
 
 def wait_until_removed(folder):
@@ -100,14 +101,18 @@ def hello_conan_files(ref, number=0, deps=None, language=0, lang='cpp'):
 
 
 def tgz_with_contents(files):
-    with chdir(mkdir_tmp()):
-        import tarfile
-        file_path = os.path.abspath("myfile.tar.gz")
-        tar_file = tarfile.open(file_path, "w:gz")
+    folder = temp_folder()
+    file_path = os.path.join(folder, "myfile.tar.gz")
+
+    with open(file_path, "wb") as tgz_handle:
+        tgz = gzopen_without_timestamps("myfile.tar.gz", mode="w", fileobj=tgz_handle)
+
         for name, content in files.items():
             info = tarfile.TarInfo(name=name)
             data = content.encode('utf-8')
             info.size = len(data)
-            tar_file.addfile(tarinfo=info, fileobj=BytesIO(data))
-            tar_file.close()
-        return file_path
+            tgz.addfile(tarinfo=info, fileobj=BytesIO(data))
+
+        tgz.close()
+
+    return file_path