Repository: conan-io/conan
Pull request #16132 (2024-04-23 09:55:31)

possibility to require itself, previous version visible=False
Changelog: Feature: Allow a recipe to ``requires(..., visible=False)`` a previous version of itself without raising a loop error
Docs: https://github.com/conan-io/docs/pull/XXXX





Patch:
diff --git a/conan/api/model.py b/conan/api/model.py
index 9e23cdfe1..025e20dd1 100644
--- a/conan/api/model.py
+++ b/conan/api/model.py
@@ -1,5 +1,6 @@
 import fnmatch
 import json
+import os
 
 from conans.client.graph.graph import RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_PLATFORM, \
     RECIPE_VIRTUAL, BINARY_SKIP, BINARY_MISSING, BINARY_INVALID
@@ -90,6 +91,8 @@ class MultiPackagesList:
 
     @staticmethod
     def load_graph(graphfile, graph_recipes=None, graph_binaries=None):
+        if not os.path.isfile(graphfile):
+            raise ConanException(f"Graph file not found: {graphfile}")
         graph = json.loads(load(graphfile))
         return MultiPackagesList._define_graph(graph, graph_recipes, graph_binaries)
 
diff --git a/conan/api/subapi/cache.py b/conan/api/subapi/cache.py
index 4fcfeebc7..77d8c6df8 100644
--- a/conan/api/subapi/cache.py
+++ b/conan/api/subapi/cache.py
@@ -6,10 +6,10 @@ from io import BytesIO
 
 from conan.api.model import PackagesList
 from conan.api.output import ConanOutput
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
 from conan.internal.conan_app import ConanApp
 from conan.internal.integrity_check import IntegrityChecker
-from conans.client.cache.cache import ClientCache
 from conans.client.downloaders.download_cache import DownloadCache
 from conans.errors import ConanException
 from conans.model.package_ref import PkgReference
@@ -118,9 +118,9 @@ class CacheAPI:
                     rmdir(pref_layout.download_package())
 
     def save(self, package_list, tgz_path):
-        cache_folder = self.conan_api.cache_folder
         global_conf = self.conan_api.config.global_conf
-        cache = ClientCache(cache_folder, global_conf)
+        cache = PkgCache(self.conan_api.cache_folder, global_conf)
+        cache_folder = cache.store  # Note, this is not the home, but the actual package cache
         out = ConanOutput()
         mkdir(os.path.dirname(tgz_path))
         name = os.path.basename(tgz_path)
@@ -160,23 +160,26 @@ class CacheAPI:
     def restore(self, path):
         if not os.path.isfile(path):
             raise ConanException(f"Restore archive doesn't exist in {path}")
+
+        cache = PkgCache(self.conan_api.cache_folder, self.conan_api.config.global_conf)
+        cache_folder = cache.store  # Note, this is not the home, but the actual package cache
+
         with open(path, mode='rb') as file_handler:
             the_tar = tarfile.open(fileobj=file_handler)
             fileobj = the_tar.extractfile("pkglist.json")
             pkglist = fileobj.read()
-            the_tar.extractall(path=self.conan_api.cache_folder)
+            the_tar.extractall(path=cache_folder)
             the_tar.close()
 
         # After unzipping the files, we need to update the DB that references these files
         out = ConanOutput()
         package_list = PackagesList.deserialize(json.loads(pkglist))
-        cache = ClientCache(self.conan_api.cache_folder, self.conan_api.config.global_conf)
         for ref, ref_bundle in package_list.refs().items():
             ref.timestamp = revision_timestamp_now()
             ref_bundle["timestamp"] = ref.timestamp
             recipe_layout = cache.get_or_create_ref_layout(ref)  # DB folder entry
             recipe_folder = ref_bundle["recipe_folder"]
-            rel_path = os.path.relpath(recipe_layout.base_folder, cache.cache_folder)
+            rel_path = os.path.relpath(recipe_layout.base_folder, cache_folder)
             rel_path = rel_path.replace("\\", "/")
             # In the case of recipes, they are always "in place", so just checking it
             assert rel_path == recipe_folder, f"{rel_path}!={recipe_folder}"
@@ -189,25 +192,25 @@ class CacheAPI:
                 out.info(f"Restore: {pref} in {unzipped_pkg_folder}")
                 # If the DB folder entry is different to the disk unzipped one, we need to move it
                 # This happens for built (not downloaded) packages in the source "conan cache save"
-                db_pkg_folder = os.path.relpath(pkg_layout.package(), cache.cache_folder)
+                db_pkg_folder = os.path.relpath(pkg_layout.package(), cache_folder)
                 db_pkg_folder = db_pkg_folder.replace("\\", "/")
                 if db_pkg_folder != unzipped_pkg_folder:
                     # If a previous package exists, like a previous restore, then remove it
                     if os.path.exists(pkg_layout.package()):
                         shutil.rmtree(pkg_layout.package())
-                    shutil.move(os.path.join(cache.cache_folder, unzipped_pkg_folder),
+                    shutil.move(os.path.join(cache_folder, unzipped_pkg_folder),
                                 pkg_layout.package())
                     pref_bundle["package_folder"] = db_pkg_folder
                 unzipped_metadata_folder = pref_bundle.get("metadata_folder")
                 if unzipped_metadata_folder:
                     out.info(f"Restore: {pref} metadata in {unzipped_metadata_folder}")
-                    db_metadata_folder = os.path.relpath(pkg_layout.metadata(), cache.cache_folder)
+                    db_metadata_folder = os.path.relpath(pkg_layout.metadata(), cache_folder)
                     db_metadata_folder = db_metadata_folder.replace("\\", "/")
                     if db_metadata_folder != unzipped_metadata_folder:
                         # We need to put the package in the final location in the cache
                         if os.path.exists(pkg_layout.metadata()):
                             shutil.rmtree(pkg_layout.metadata())
-                        shutil.move(os.path.join(cache.cache_folder, unzipped_metadata_folder),
+                        shutil.move(os.path.join(cache_folder, unzipped_metadata_folder),
                                     pkg_layout.metadata())
                         pref_bundle["metadata_folder"] = db_metadata_folder
 
diff --git a/conan/api/subapi/local.py b/conan/api/subapi/local.py
index 88ae8a8fe..27ed46e00 100644
--- a/conan/api/subapi/local.py
+++ b/conan/api/subapi/local.py
@@ -111,9 +111,10 @@ class LocalAPI:
             with chdir(conanfile.build_folder):
                 conanfile.test()
 
-    def inspect(self, conanfile_path, remotes, lockfile):
+    def inspect(self, conanfile_path, remotes, lockfile, name=None, version=None, user=None,
+                channel=None):
         app = ConanApp(self._conan_api)
-        conanfile = app.loader.load_named(conanfile_path, name=None, version=None,
-                                          user=None, channel=None, remotes=remotes, graph_lock=lockfile)
+        conanfile = app.loader.load_named(conanfile_path, name=name, version=version, user=user,
+                                          channel=channel, remotes=remotes, graph_lock=lockfile)
         return conanfile
 
diff --git a/conan/api/subapi/profiles.py b/conan/api/subapi/profiles.py
index f6d927048..6184a60cc 100644
--- a/conan/api/subapi/profiles.py
+++ b/conan/api/subapi/profiles.py
@@ -1,5 +1,6 @@
 import os
 
+from conan.api.output import ConanOutput
 from conan.internal.cache.home_paths import HomePaths
 
 from conans.client.loader import load_python_file
@@ -97,6 +98,11 @@ class ProfilesAPI:
         profile.conf.validate()
         # Apply the new_config to the profiles the global one, so recipes get it too
         profile.conf.rebase_conf_definition(global_conf)
+        for k, v in sorted(profile.options._package_options.items()):
+            ConanOutput().warning("Unscoped option definition is ambiguous.\n"
+                                  f"Use '&:{k}={v}' to refer to the current package.\n"
+                                  f"Use '*:{k}={v}' or other pattern if the intent was to apply to "
+                                  f"dependencies", warn_tag="legacy")
         return profile
 
     def get_path(self, profile, cwd=None, exists=True):
diff --git a/conan/api/subapi/remotes.py b/conan/api/subapi/remotes.py
index da6520695..1a54e61be 100644
--- a/conan/api/subapi/remotes.py
+++ b/conan/api/subapi/remotes.py
@@ -9,6 +9,7 @@ from conan.internal.cache.home_paths import HomePaths
 from conan.internal.conan_app import ConanApp
 from conans.client.rest_client_local_recipe_index import add_local_recipes_index_remote, \
     remove_local_recipes_index_remote
+from conans.client.store.localdb import LocalDB
 from conans.errors import ConanException
 from conans.util.files import save, load
 
@@ -141,10 +142,10 @@ class RemotesAPI:
         removed = _filter(remotes, pattern, only_enabled=False)
         remotes = [r for r in remotes if r not in removed]
         _save(self._remotes_file, remotes)
-        app = ConanApp(self.conan_api)
+        localdb = LocalDB(self.conan_api.cache_folder)
         for remote in removed:
             remove_local_recipes_index_remote(self.conan_api, remote)
-            app.cache.localdb.clean(remote_url=remote.url)
+            localdb.clean(remote_url=remote.url)
         return removed
 
     def update(self, remote_name: str, url=None, secure=None, disabled=None, index=None,
@@ -200,9 +201,9 @@ class RemotesAPI:
 
     def user_info(self, remote: Remote):
         # TODO: Review
-        app = ConanApp(self.conan_api)
+        localdb = LocalDB(self.conan_api.cache_folder)
         user_info = {}
-        user, token, _ = app.cache.localdb.get_login(remote.url)
+        user, token, _ = localdb.get_login(remote.url)
         user_info["name"] = remote.name
         user_info["user_name"] = user
         user_info["authenticated"] = True if token else False
@@ -225,29 +226,29 @@ class RemotesAPI:
 
         :param remote: The ``Remote`` object to logout
         """
-        app = ConanApp(self.conan_api)
+        localdb = LocalDB(self.conan_api.cache_folder)
         # The localdb only stores url + username + token, not remote name, so use URL as key
-        app.cache.localdb.clean(remote_url=remote.url)
+        localdb.clean(remote_url=remote.url)
 
     def user_set(self, remote: Remote, username):
         # TODO: Review
-        app = ConanApp(self.conan_api)
+        localdb = LocalDB(self.conan_api.cache_folder)
         if username == "":
             username = None
-        app.cache.localdb.store(username, token=None, refresh_token=None, remote_url=remote.url)
+        localdb.store(username, token=None, refresh_token=None, remote_url=remote.url)
 
     def user_auth(self, remote: Remote, with_user=False):
         # TODO: Review
         app = ConanApp(self.conan_api)
         if with_user:
-            user, token, _ = app.cache.localdb.get_login(remote.url)
+            user, token, _ = app.localdb.get_login(remote.url)
             if not user:
                 var_name = f"CONAN_LOGIN_USERNAME_{remote.name.replace('-', '_').upper()}"
                 user = os.getenv(var_name, None) or os.getenv("CONAN_LOGIN_USERNAME", None)
             if not user:
                 return
         app.remote_manager.check_credentials(remote)
-        user, token, _ = app.cache.localdb.get_login(remote.url)
+        user, token, _ = app.localdb.get_login(remote.url)
         return user
 
 
diff --git a/conan/api/subapi/upload.py b/conan/api/subapi/upload.py
index f39c3f3f6..f8ad2dc3e 100644
--- a/conan/api/subapi/upload.py
+++ b/conan/api/subapi/upload.py
@@ -47,7 +47,7 @@ class UploadAPI:
         preparator.prepare(package_list, enabled_remotes)
         if metadata != ['']:
             gather_metadata(package_list, app.cache, metadata)
-        signer = PkgSignaturesPlugin(app.cache)
+        signer = PkgSignaturesPlugin(app.cache, app.cache_folder)
         # This might add files entries to package_list with signatures
         signer.sign(package_list)
 
diff --git a/conan/cli/commands/download.py b/conan/cli/commands/download.py
index f8087103b..dbaa4f73e 100644
--- a/conan/cli/commands/download.py
+++ b/conan/cli/commands/download.py
@@ -21,7 +21,7 @@ def download(conan_api: ConanAPI, parser, *args):
 
     parser.add_argument('pattern', nargs="?",
                         help="A pattern in the form 'pkg/version#revision:package_id#revision', "
-                             "e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. "
+                             "e.g: \"zlib/1.2.13:*\" means all binaries for zlib/1.2.13. "
                              "If revision is not specified, it is assumed latest one.")
     parser.add_argument("--only-recipe", action='store_true', default=False,
                         help='Download only the recipe/s, not the binary packages.')
diff --git a/conan/cli/commands/export_pkg.py b/conan/cli/commands/export_pkg.py
index c9a6e9438..a47cdfe46 100644
--- a/conan/cli/commands/export_pkg.py
+++ b/conan/cli/commands/export_pkg.py
@@ -46,7 +46,8 @@ def export_pkg(conan_api, parser, *args):
     profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)
     remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []
 
-    conanfile = conan_api.local.inspect(path, remotes, lockfile)
+    conanfile = conan_api.local.inspect(path, remotes, lockfile, name=args.name,
+                                        version=args.version, user=args.user, channel=args.channel)
     # The package_type is not fully processed at export
     if conanfile.package_type == "python-require":
         raise ConanException("export-pkg can only be used for binaries, not for 'python-require'")
diff --git a/conan/cli/commands/graph.py b/conan/cli/commands/graph.py
index bf591c461..c5fb5f168 100644
--- a/conan/cli/commands/graph.py
+++ b/conan/cli/commands/graph.py
@@ -248,7 +248,7 @@ def graph_explain(conan_api, parser,  subparser, *args):
                            help='Whether the provided reference is a build-require')
     subparser.add_argument('--missing', nargs="?",
                            help="A pattern in the form 'pkg/version#revision:package_id#revision', "
-                                "e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. "
+                                "e.g: \"zlib/1.2.13:*\" means all binaries for zlib/1.2.13. "
                                 "If revision is not specified, it is assumed latest one.")
 
     args = parser.parse_args(*args)
diff --git a/conan/cli/commands/list.py b/conan/cli/commands/list.py
index 1fd4a8811..a905c2acd 100644
--- a/conan/cli/commands/list.py
+++ b/conan/cli/commands/list.py
@@ -207,7 +207,7 @@ def list(conan_api: ConanAPI, parser, *args):
     """
     parser.add_argument('pattern', nargs="?",
                         help="A pattern in the form 'pkg/version#revision:package_id#revision', "
-                             "e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. "
+                             "e.g: \"zlib/1.2.13:*\" means all binaries for zlib/1.2.13. "
                              "If revision is not specified, it is assumed latest one.")
     parser.add_argument('-p', '--package-query', default=None, action=OnceArgument,
                         help="List only the packages matching a specific query, e.g, os=Windows AND "
diff --git a/conan/cli/commands/remove.py b/conan/cli/commands/remove.py
index 984463b4f..74ac93d99 100644
--- a/conan/cli/commands/remove.py
+++ b/conan/cli/commands/remove.py
@@ -41,7 +41,7 @@ def remove(conan_api: ConanAPI, parser, *args):
     """
     parser.add_argument('pattern', nargs="?",
                         help="A pattern in the form 'pkg/version#revision:package_id#revision', "
-                             "e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. "
+                             "e.g: \"zlib/1.2.13:*\" means all binaries for zlib/1.2.13. "
                              "If revision is not specified, it is assumed latest one.")
     parser.add_argument('-c', '--confirm', default=False, action='store_true',
                         help='Remove without requesting a confirmation')
diff --git a/conan/cli/commands/upload.py b/conan/cli/commands/upload.py
index 3d1171e04..282a70df9 100644
--- a/conan/cli/commands/upload.py
+++ b/conan/cli/commands/upload.py
@@ -50,7 +50,7 @@ def upload(conan_api: ConanAPI, parser, *args):
     """
     parser.add_argument('pattern', nargs="?",
                         help="A pattern in the form 'pkg/version#revision:package_id#revision', "
-                             "e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. "
+                             "e.g: \"zlib/1.2.13:*\" means all binaries for zlib/1.2.13. "
                              "If revision is not specified, it is assumed latest one.")
     parser.add_argument('-p', '--package-query', default=None, action=OnceArgument,
                         help="Only upload packages matching a specific query. e.g: os=Windows AND "
diff --git a/conan/internal/api/detect_api.py b/conan/internal/api/detect_api.py
index 5f2eabebd..e90894b29 100644
--- a/conan/internal/api/detect_api.py
+++ b/conan/internal/api/detect_api.py
@@ -384,9 +384,14 @@ def detect_default_compiler():
         return None, None, None
 
     if platform.system() == "Windows":
-        compiler, version, compiler_exe = detect_msvc_compiler()
-        if compiler:
-            return compiler, version, compiler_exe
+        ide_version = _detect_vs_ide_version()
+        version = {"17": "193", "16": "192", "15": "191"}.get(str(ide_version))  # Map to compiler
+        if ide_version == "17":
+            update = detect_msvc_update(version)  # FIXME weird passing here the 193 compiler version
+            if update and int(update) >= 10:
+                version = "194"
+        if version:
+            return 'msvc', Version(version), None
 
     if platform.system() == "SunOS":
         sun_cc, sun_cc_version, compiler_exe = detect_suncc_compiler()
@@ -409,7 +414,7 @@ def detect_default_compiler():
 
 
 def default_msvc_ide_version(version):
-    version = {"193": "17", "192": "16", "191": "15"}.get(str(version))
+    version = {"194": "17", "193": "17", "192": "16", "191": "15"}.get(str(version))
     if version:
         return Version(version)
 
diff --git a/conan/internal/cache/cache.py b/conan/internal/cache/cache.py
index 8e0b58159..edb2bb94a 100644
--- a/conan/internal/cache/cache.py
+++ b/conan/internal/cache/cache.py
@@ -2,24 +2,51 @@ import hashlib
 import os
 import shutil
 import uuid
+from typing import List
 
 from conan.internal.cache.conan_reference_layout import RecipeLayout, PackageLayout
 # TODO: Random folders are no longer accessible, how to get rid of them asap?
-# TODO: Add timestamp for LRU
 # TODO: We need the workflow to remove existing references.
 from conan.internal.cache.db.cache_database import CacheDatabase
-from conans.errors import ConanReferenceAlreadyExistsInDB, ConanReferenceDoesNotExistInDB
+from conans.errors import ConanReferenceAlreadyExistsInDB, ConanReferenceDoesNotExistInDB, \
+    ConanException
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
 from conans.util.dates import revision_timestamp_now
-from conans.util.files import rmdir, renamedir
+from conans.util.files import rmdir, renamedir, mkdir
 
 
-class DataCache:
+class PkgCache:
+    """ Class to represent the recipes and packages storage in disk
+    """
 
-    def __init__(self, base_folder, db_filename):
-        self._base_folder = os.path.abspath(base_folder)
-        self._db = CacheDatabase(filename=db_filename)
+    def __init__(self, cache_folder, global_conf):
+        # paths
+        self._store_folder = global_conf.get("core.cache:storage_path") or \
+                             os.path.join(cache_folder, "p")
+
+        try:
+            mkdir(self._store_folder)
+            db_filename = os.path.join(self._store_folder, 'cache.sqlite3')
+            self._base_folder = os.path.abspath(self._store_folder)
+            self._db = CacheDatabase(filename=db_filename)
+        except Exception as e:
+            raise ConanException(f"Couldn't initialize storage in {self._store_folder}: {e}")
+
+    @property
+    def store(self):
+        return self._base_folder
+
+    @property
+    def temp_folder(self):
+        """ temporary folder where Conan puts exports and packages before the final revision
+        is computed"""
+        # TODO: Improve the path definitions, this is very hardcoded
+        return os.path.join(self._base_folder, "t")
+
+    @property
+    def builds_folder(self):
+        return os.path.join(self._base_folder, "b")
 
     def _create_path(self, relative_path, remove_contents=True):
         path = self._full_path(relative_path)
@@ -33,10 +60,6 @@ class DataCache:
         path = os.path.realpath(os.path.join(self._base_folder, relative_path))
         return path
 
-    @property
-    def base_folder(self):
-        return self._base_folder
-
     @staticmethod
     def _short_hash_path(h):
         """:param h: Unicode text to reduce"""
@@ -49,34 +72,24 @@ class DataCache:
         return sha_bytes[0:13]
 
     @staticmethod
-    def _get_tmp_path(ref: RecipeReference):
-        # The reference will not have revision, but it will be always constant
-        h = ref.name[:5] + DataCache._short_hash_path(ref.repr_notime())
-        return os.path.join("t", h)
-
-    @staticmethod
-    def _get_tmp_path_pref(pref):
-        # The reference will not have revision, but it will be always constant
-        assert pref.revision is None
-        assert pref.timestamp is None
-        random_id = str(uuid.uuid4())
-        h = pref.ref.name[:5] + DataCache._short_hash_path(pref.repr_notime() + random_id)
-        return os.path.join("b", h)
-
-    @staticmethod
-    def _get_path(ref: RecipeReference):
-        return ref.name[:5] + DataCache._short_hash_path(ref.repr_notime())
+    def _get_path(ref):
+        return ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())
 
     @staticmethod
     def _get_path_pref(pref):
-        return pref.ref.name[:5] + DataCache._short_hash_path(pref.repr_notime())
+        return pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime())
 
     def create_export_recipe_layout(self, ref: RecipeReference):
-        # This is a temporary layout while exporting a new recipe, because the revision is not
-        # computed yet, until it is. The entry is not added to DB, just a temp folder is created
+        """  This is a temporary layout while exporting a new recipe, because the revision is not
+        computed until later. The entry is not added to DB, just a temp folder is created
+
+        This temporary export folder will be moved to permanent when revision is computed by the
+        assign_rrev() method
+        """
         assert ref.revision is None, "Recipe revision should be None"
         assert ref.timestamp is None
-        reference_path = self._get_tmp_path(ref)
+        h = ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())
+        reference_path = os.path.join("t", h)
         self._create_path(reference_path)
         return RecipeLayout(ref, os.path.join(self._base_folder, reference_path))
 
@@ -86,11 +99,14 @@ class DataCache:
         assert pref.package_id, "Package id must be known to get or create the package layout"
         assert pref.revision is None, "Package revision should be None"
         assert pref.timestamp is None
-        package_path = self._get_tmp_path_pref(pref)
+
+        random_id = str(uuid.uuid4())
+        h = pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime() + random_id)
+        package_path = os.path.join("b", h)
         self._create_path(package_path)
         return PackageLayout(pref, os.path.join(self._base_folder, package_path))
 
-    def get_recipe_layout(self, ref: RecipeReference):
+    def recipe_layout(self, ref: RecipeReference):
         """ the revision must exists, the folder must exist
         """
         if ref.revision is None:  # Latest one
@@ -101,10 +117,17 @@ class DataCache:
         ref = ref_data.get("ref")  # new revision with timestamp
         return RecipeLayout(ref, os.path.join(self._base_folder, ref_path))
 
+    def get_latest_recipe_reference(self, ref: RecipeReference):
+        assert ref.revision is None
+        ref_data = self._db.get_latest_recipe(ref)
+        return ref_data.get("ref")
+
     def get_recipe_revisions_references(self, ref: RecipeReference):
+        # For listing multiple revisions only
+        assert ref.revision is None
         return self._db.get_recipe_revisions_references(ref)
 
-    def get_package_layout(self, pref: PkgReference):
+    def pkg_layout(self, pref: PkgReference):
         """ the revision must exists, the folder must exist
         """
         assert pref.ref.revision, "Recipe revision must be known to get the package layout"
@@ -119,7 +142,7 @@ class DataCache:
         """ called by RemoteManager.get_recipe()
         """
         try:
-            return self.get_recipe_layout(ref)
+            return self.recipe_layout(ref)
         except ConanReferenceDoesNotExistInDB:
             assert ref.revision, "Recipe revision must be known to create the package layout"
             reference_path = self._get_path(ref)
@@ -131,7 +154,7 @@ class DataCache:
         """ called by RemoteManager.get_package() and  BinaryInstaller
         """
         try:
-            return self.get_package_layout(pref)
+            return self.pkg_layout(pref)
         except ConanReferenceDoesNotExistInDB:
             assert pref.ref.revision, "Recipe revision must be known to create the package layout"
             assert pref.package_id, "Package id must be known to create the package layout"
@@ -142,20 +165,25 @@ class DataCache:
             return PackageLayout(pref, os.path.join(self._base_folder, package_path))
 
     def update_recipe_timestamp(self, ref: RecipeReference):
+        """ when the recipe already exists in cache, but we get a new timestamp from a server
+        that would affect its order in our cache """
         assert ref.revision
         assert ref.timestamp
         self._db.update_recipe_timestamp(ref)
 
-    def list_references(self):
+    def all_refs(self):
         return self._db.list_references()
 
     def exists_prev(self, pref):
+        # Used just by download to skip downloads if prev already exists in cache
         return self._db.exists_prev(pref)
 
     def get_latest_package_reference(self, pref):
         return self._db.get_latest_package_reference(pref)
 
-    def get_package_references(self, ref: RecipeReference, only_latest_prev=True):
+    def get_package_references(self, ref: RecipeReference,
+                               only_latest_prev=True) -> List[PkgReference]:
+        """Get the latest package references"""
         return self._db.get_package_references(ref, only_latest_prev)
 
     def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):
@@ -164,12 +192,12 @@ class DataCache:
     def get_matching_build_id(self, ref, build_id):
         return self._db.get_matching_build_id(ref, build_id)
 
-    def remove_recipe(self, layout: RecipeLayout):
+    def remove_recipe_layout(self, layout: RecipeLayout):
         layout.remove()
         # FIXME: This is clearing package binaries from DB, but not from disk/layout
         self._db.remove_recipe(layout.reference)
 
-    def remove_package(self, layout: PackageLayout):
+    def remove_package_layout(self, layout: PackageLayout):
         layout.remove()
         self._db.remove_package(layout.reference)
 
@@ -189,7 +217,7 @@ class DataCache:
         except ConanReferenceAlreadyExistsInDB:
             # TODO: Optimize this into 1 single UPSERT operation
             # There was a previous package folder for this same package reference (and prev)
-            pkg_layout = self.get_package_layout(pref)
+            pkg_layout = self.pkg_layout(pref)
             # We remove the old one and move the new one to the path of the previous one
             # this can be necessary in case of new metadata or build-folder because of "build_id()"
             pkg_layout.remove()
diff --git a/conan/internal/conan_app.py b/conan/internal/conan_app.py
index 3ce4eed48..0f92e3eb2 100644
--- a/conan/internal/conan_app.py
+++ b/conan/internal/conan_app.py
@@ -1,8 +1,8 @@
 import os
 
 from conan.api.output import ConanOutput
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.graph.proxy import ConanProxy
 from conans.client.graph.python_requires import PyRequireLoader
 from conans.client.graph.range_resolver import RangeResolver
@@ -12,6 +12,7 @@ from conans.client.remote_manager import RemoteManager
 from conans.client.rest.auth_manager import ConanApiAuthManager
 from conans.client.rest.conan_requester import ConanRequester
 from conans.client.rest.rest_client import RestApiClientFactory
+from conans.client.store.localdb import LocalDB
 
 
 class CmdWrapper:
@@ -29,11 +30,12 @@ class CmdWrapper:
 
 
 class ConanFileHelpers:
-    def __init__(self, requester, cmd_wrapper, global_conf, cache):
+    def __init__(self, requester, cmd_wrapper, global_conf, cache, home_folder):
         self.requester = requester
         self.cmd_wrapper = cmd_wrapper
         self.global_conf = global_conf
         self.cache = cache
+        self.home_folder = home_folder
 
 
 class ConanApp:
@@ -42,7 +44,7 @@ class ConanApp:
         cache_folder = conan_api.home_folder
         self._configure(global_conf)
         self.cache_folder = cache_folder
-        self.cache = ClientCache(self.cache_folder, global_conf)
+        self.cache = PkgCache(self.cache_folder, global_conf)
 
         home_paths = HomePaths(self.cache_folder)
         self.hook_manager = HookManager(home_paths.hooks_path)
@@ -52,16 +54,19 @@ class ConanApp:
         # To handle remote connections
         rest_client_factory = RestApiClientFactory(self.requester, global_conf)
         # Wraps RestApiClient to add authentication support (same interface)
-        auth_manager = ConanApiAuthManager(rest_client_factory, self.cache, global_conf)
+        self.localdb = LocalDB(cache_folder)
+        auth_manager = ConanApiAuthManager(rest_client_factory, cache_folder, self.localdb,
+                                           global_conf)
         # Handle remote connections
-        self.remote_manager = RemoteManager(self.cache, auth_manager)
+        self.remote_manager = RemoteManager(self.cache, auth_manager, cache_folder)
 
         self.proxy = ConanProxy(self, conan_api.local.editable_packages)
         self.range_resolver = RangeResolver(self, global_conf, conan_api.local.editable_packages)
 
         self.pyreq_loader = PyRequireLoader(self, global_conf)
         cmd_wrap = CmdWrapper(home_paths.wrapper_path)
-        conanfile_helpers = ConanFileHelpers(self.requester, cmd_wrap, global_conf, self.cache)
+        conanfile_helpers = ConanFileHelpers(self.requester, cmd_wrap, global_conf, self.cache,
+                                             self.cache_folder)
         self.loader = ConanFileLoader(self.pyreq_loader, conanfile_helpers)
 
     @staticmethod
diff --git a/conan/internal/runner/docker.py b/conan/internal/runner/docker.py
index ebc6374e3..77aabaf0a 100644
--- a/conan/internal/runner/docker.py
+++ b/conan/internal/runner/docker.py
@@ -90,7 +90,7 @@ class DockerRunner:
             profile_list = set(self.args.profile_build + self.args.profile_host)
         else:
             profile_list = self.args.profile_host or self.args.profile_build
-        
+
         # Update the profile paths
         for i, raw_arg in enumerate(raw_args):
             for i, raw_profile in enumerate(profile_list):
@@ -111,7 +111,7 @@ class DockerRunner:
         if not (self.dockerfile or self.image):
             raise ConanException("'dockerfile' or docker image name is needed")
         self.image = self.image or 'conan-runner-default'
-        self.name = self.configfile.image or f'conan-runner-{host_profile.runner.get("suffix", "docker")}'
+        self.name = self.configfile.run.name or f'conan-runner-{host_profile.runner.get("suffix", "docker")}'
         self.remove = str(host_profile.runner.get('remove', 'false')).lower() == 'true'
         self.cache = str(host_profile.runner.get('cache', 'clean'))
         self.container = None
diff --git a/conan/tools/cmake/cmakedeps/templates/config.py b/conan/tools/cmake/cmakedeps/templates/config.py
index ea0184457..6a161d293 100644
--- a/conan/tools/cmake/cmakedeps/templates/config.py
+++ b/conan/tools/cmake/cmakedeps/templates/config.py
@@ -22,13 +22,20 @@ class ConfigTemplate(CMakeDepsFileTemplate):
             else:
                 return "{}Config.cmake".format(self.file_name)
 
+    @property
+    def additional_variables_prefixes(self):
+        prefix_list = (
+            self.cmakedeps.get_property("cmake_additional_variables_prefixes", self.conanfile) or [])
+        return list(set([self.file_name] + prefix_list))
+
     @property
     def context(self):
         targets_include = "" if not self.generating_module else "module-"
         targets_include += "{}Targets.cmake".format(self.file_name)
         return {"is_module": self.generating_module,
                 "version": self.conanfile.ref.version,
-                "file_name": self.file_name,
+                "file_name":  self.file_name,
+                "additional_variables_prefixes": self.additional_variables_prefixes,
                 "pkg_name": self.pkg_name,
                 "config_suffix": self.config_suffix,
                 "check_components_exist": self.cmakedeps.check_components_exist,
@@ -67,11 +74,14 @@ class ConfigTemplate(CMakeDepsFileTemplate):
             endif()
         endforeach()
 
-        set({{ file_name }}_VERSION_STRING "{{ version }}")
-        set({{ file_name }}_INCLUDE_DIRS {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
-        set({{ file_name }}_INCLUDE_DIR {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
-        set({{ file_name }}_LIBRARIES {{ pkg_var(pkg_name, 'LIBRARIES', config_suffix) }} )
-        set({{ file_name }}_DEFINITIONS {{ pkg_var(pkg_name, 'DEFINITIONS', config_suffix) }} )
+        {% for prefix in additional_variables_prefixes %}
+        set({{ prefix }}_VERSION_STRING "{{ version }}")
+        set({{ prefix }}_INCLUDE_DIRS {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
+        set({{ prefix }}_INCLUDE_DIR {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
+        set({{ prefix }}_LIBRARIES {{ pkg_var(pkg_name, 'LIBRARIES', config_suffix) }} )
+        set({{ prefix }}_DEFINITIONS {{ pkg_var(pkg_name, 'DEFINITIONS', config_suffix) }} )
+
+        {% endfor %}
 
         # Only the first installed configuration is included to avoid the collision
         foreach(_BUILD_MODULE {{ pkg_var(pkg_name, 'BUILD_MODULES_PATHS', config_suffix) }} )
diff --git a/conan/tools/cmake/presets.py b/conan/tools/cmake/presets.py
index d50bfdea2..b7e616150 100644
--- a/conan/tools/cmake/presets.py
+++ b/conan/tools/cmake/presets.py
@@ -16,11 +16,12 @@ from conans.util.files import save, load
 
 def write_cmake_presets(conanfile, toolchain_file, generator, cache_variables,
                         user_presets_path=None, preset_prefix=None, buildenv=None, runenv=None,
-                        cmake_executable=None):
+                        cmake_executable=None, absolute_paths=None):
     preset_path, preset_data = _CMakePresets.generate(conanfile, toolchain_file, generator,
                                                       cache_variables, preset_prefix, buildenv, runenv,
-                                                      cmake_executable)
-    _IncludingPresets.generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data)
+                                                      cmake_executable, absolute_paths)
+    _IncludingPresets.generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data,
+                               absolute_paths)
 
 
 class _CMakePresets:
@@ -28,12 +29,13 @@ class _CMakePresets:
     """
     @staticmethod
     def generate(conanfile, toolchain_file, generator, cache_variables, preset_prefix, buildenv, runenv,
-                 cmake_executable):
+                 cmake_executable, absolute_paths):
         toolchain_file = os.path.abspath(os.path.join(conanfile.generators_folder, toolchain_file))
-        try:  # Make it relative to the build dir if possible
-            toolchain_file = os.path.relpath(toolchain_file, conanfile.build_folder)
-        except ValueError:
-            pass
+        if not absolute_paths:
+            try:  # Make it relative to the build dir if possible
+                toolchain_file = os.path.relpath(toolchain_file, conanfile.build_folder)
+            except ValueError:
+                pass
         cache_variables = cache_variables or {}
         if platform.system() == "Windows" and generator == "MinGW Makefiles":
             if "CMAKE_SH" not in cache_variables:
@@ -249,7 +251,8 @@ class _IncludingPresets:
     """
 
     @staticmethod
-    def generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data):
+    def generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data,
+                 absolute_paths):
         if not user_presets_path:
             return
 
@@ -288,10 +291,11 @@ class _IncludingPresets:
         if inherited_user:
             _IncludingPresets._clean_user_inherits(data, preset_data)
 
-        try:  # Make it relative to the CMakeUserPresets.json if possible
-            preset_path = os.path.relpath(preset_path, output_dir)
-        except ValueError:
-            pass
+        if not absolute_paths:
+            try:  # Make it relative to the CMakeUserPresets.json if possible
+                preset_path = os.path.relpath(preset_path, output_dir)
+            except ValueError:
+                pass
         data = _IncludingPresets._append_user_preset_path(data, preset_path, output_dir)
 
         data = json.dumps(data, indent=4)
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index adb338e5b..02d6c4723 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -480,6 +480,9 @@ class FindFiles(Block):
         {% if cmake_include_path %}
         list(PREPEND CMAKE_INCLUDE_PATH {{ cmake_include_path }})
         {% endif %}
+        {% if host_runtime_dirs %}
+        set(CONAN_RUNTIME_LIB_DIRS {{ host_runtime_dirs }} )
+        {% endif %}
 
         {% if cross_building %}
         if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PACKAGE OR CMAKE_FIND_ROOT_PATH_MODE_PACKAGE STREQUAL "ONLY")
@@ -502,6 +505,40 @@ class FindFiles(Block):
         {% endif %}
     """)
 
+    def _runtime_dirs_value(self, dirs):
+        if is_multi_configuration(self._toolchain.generator):
+            return ' '.join(f'"$<$<CONFIG:{c}>:{i}>"' for c, v in dirs.items() for i in v)
+        else:
+            return ' '.join(f'"{item}"' for _, items in dirs.items() for item in items)
+
+    def _get_host_runtime_dirs(self, host_req):
+        settings = self._conanfile.settings
+        host_runtime_dirs = {}
+        is_win = self._conanfile.settings.get_safe("os") == "Windows"
+
+        # Get the previous configuration
+        if is_multi_configuration(self._toolchain.generator) and os.path.exists(CONAN_TOOLCHAIN_FILENAME):
+            existing_toolchain = load(CONAN_TOOLCHAIN_FILENAME)
+            pattern_lib_dirs = r"set\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\)"
+            variable_match = re.search(pattern_lib_dirs, existing_toolchain)
+            if variable_match:
+                capture = variable_match.group(1)
+                matches = re.findall(r'"\$<\$<CONFIG:([A-Za-z]*)>:([^>]*)>"', capture)
+                host_runtime_dirs = {}
+                for k, v in matches:
+                    host_runtime_dirs.setdefault(k, []).append(v)
+        
+        # Calculate the dirs for the current build_type
+        runtime_dirs = []
+        for req in host_req:
+            cppinfo = req.cpp_info.aggregated_components()
+            runtime_dirs.extend(cppinfo.bindirs if is_win else cppinfo.libdirs)
+        
+        build_type = settings.get_safe("build_type")
+        host_runtime_dirs[build_type] = [s.replace("\\", "/") for s in runtime_dirs]
+
+        return host_runtime_dirs
+
     @staticmethod
     def _join_paths(paths):
         return " ".join(['"{}"'.format(p.replace('\\', '/')
@@ -524,6 +561,7 @@ class FindFiles(Block):
         host_req = self._conanfile.dependencies.filter({"build": False}).values()
         build_paths = []
         host_lib_paths = []
+        host_runtime_dirs = self._get_host_runtime_dirs(host_req)
         host_framework_paths = []
         host_include_paths = []
         for req in host_req:
@@ -552,6 +590,7 @@ class FindFiles(Block):
             "cmake_include_path": self._join_paths(host_include_paths),
             "is_apple": is_apple_,
             "cross_building": cross_building(self._conanfile),
+            "host_runtime_dirs": self._runtime_dirs_value(host_runtime_dirs)
         }
 
 
@@ -969,11 +1008,10 @@ class OutputDirsBlock(Block):
 
     @property
     def template(self):
-        if not self._conanfile.package_folder:
-            return ""
-
         return textwrap.dedent("""
+           {% if package_folder %}
            set(CMAKE_INSTALL_PREFIX "{{package_folder}}")
+           {% endif %}
            {% if default_bin %}
            set(CMAKE_INSTALL_BINDIR "{{default_bin}}")
            set(CMAKE_INSTALL_SBINDIR "{{default_bin}}")
@@ -998,9 +1036,8 @@ class OutputDirsBlock(Block):
         return elements[0] if elements else None
 
     def context(self):
-        if not self._conanfile.package_folder:
-            return {}
-        return {"package_folder": self._conanfile.package_folder.replace("\\", "/"),
+        pf = self._conanfile.package_folder
+        return {"package_folder": pf.replace("\\", "/") if pf else None,
                 "default_bin": self._get_cpp_info_value("bindirs"),
                 "default_lib": self._get_cpp_info_value("libdirs"),
                 "default_include": self._get_cpp_info_value("includedirs"),
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 22e8c3801..549e2c0b3 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -179,6 +179,7 @@ class CMakeToolchain(object):
         self.presets_prefix = "conan"
         self.presets_build_environment = None
         self.presets_run_environment = None
+        self.absolute_paths = False  # By default use relative paths to toolchain and presets
 
     def _context(self):
         """ Returns dict, the context for the template
@@ -268,7 +269,7 @@ class CMakeToolchain(object):
 
         write_cmake_presets(self._conanfile, toolchain_file, self.generator, cache_variables,
                             self.user_presets_path, self.presets_prefix, buildenv, runenv,
-                            cmake_executable)
+                            cmake_executable, self.absolute_paths)
 
     def _get_generator(self, recipe_generator):
         # Returns the name of the generator to be used by CMake
diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py
index 8c929e979..1632e3b95 100644
--- a/conan/tools/microsoft/visual.py
+++ b/conan/tools/microsoft/visual.py
@@ -59,7 +59,8 @@ def msvc_version_to_vs_ide_version(version):
                 '190': '14',
                 '191': '15',
                 '192': '16',
-                '193': '17'}
+                '193': '17',
+                '194': '17'}  # Note both 193 and 194 belong to VS 17 2022
     return _visuals[str(version)]
 
 
@@ -75,7 +76,8 @@ def msvc_version_to_toolset_version(version):
                 '190': 'v140',
                 '191': 'v141',
                 '192': 'v142',
-                "193": 'v143'}
+                "193": 'v143',
+                "194": 'v143'}
     return toolsets.get(str(version))
 
 
@@ -140,6 +142,7 @@ class VCVars:
                 compiler_update = conanfile.settings.get_safe("compiler.update", "")
                 # The equivalent of compiler 19.26 is toolset 14.26
                 vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update)
+
         vcvarsarch = _vcvars_arch(conanfile)
 
         winsdk_version = conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str)
diff --git a/conans/client/cache/cache.py b/conans/client/cache/cache.py
deleted file mode 100644
index 8c494cf02..000000000
--- a/conans/client/cache/cache.py
+++ /dev/null
@@ -1,133 +0,0 @@
-import os
-from typing import List
-
-from conan.internal.cache.cache import DataCache, RecipeLayout, PackageLayout
-from conans.client.store.localdb import LocalDB
-from conans.errors import ConanException
-from conans.model.package_ref import PkgReference
-from conans.model.recipe_ref import RecipeReference
-from conans.util.files import mkdir
-
-LOCALDB = ".conan.db"
-
-
-# TODO: Rename this to ClientHome
-class ClientCache(object):
-    """ Class to represent/store/compute all the paths involved in the execution
-    of conans commands. Accesses to real disk and reads/write things. (OLD client ConanPaths)
-    """
-
-    def __init__(self, cache_folder, global_conf):
-        self.cache_folder = cache_folder
-        # paths
-        self._store_folder = global_conf.get("core.cache:storage_path") or \
-                             os.path.join(self.cache_folder, "p")
-
-        try:
-            mkdir(self._store_folder)
-            db_filename = os.path.join(self._store_folder, 'cache.sqlite3')
-            self._data_cache = DataCache(self._store_folder, db_filename)
-        except Exception as e:
-            raise ConanException(f"Couldn't initialize storage in {self._store_folder}: {e}")
-
-    @property
-    def temp_folder(self):
-        """ temporary folder where Conan puts exports and packages before the final revision
-        is computed"""
-        # TODO: Improve the path definitions, this is very hardcoded
-        return os.path.join(self._store_folder, "t")
-
-    @property
-    def builds_folder(self):
-        return os.path.join(self._store_folder, "b")
-
-    def create_export_recipe_layout(self, ref: RecipeReference):
-        return self._data_cache.create_export_recipe_layout(ref)
-
-    def assign_rrev(self, layout: RecipeLayout):
-        return self._data_cache.assign_rrev(layout)
-
-    def create_build_pkg_layout(self, ref):
-        return self._data_cache.create_build_pkg_layout(ref)
-
-    def assign_prev(self, layout: PackageLayout):
-        return self._data_cache.assign_prev(layout)
-
-    # Recipe methods
-    def recipe_layout(self, ref: RecipeReference):
-        return self._data_cache.get_recipe_layout(ref)
-
-    def get_latest_recipe_reference(self, ref):
-        # TODO: We keep this for testing only, to be removed
-        assert ref.revision is None
-        return self._data_cache.get_recipe_layout(ref).reference
-
-    def get_recipe_revisions_references(self, ref):
-        # For listing multiple revisions only
-        assert ref.revision is None
-        return self._data_cache.get_recipe_revisions_references(ref)
-
-    def pkg_layout(self, ref: PkgReference):
-        return self._data_cache.get_package_layout(ref)
-
-    def get_or_create_ref_layout(self, ref: RecipeReference):
-        return self._data_cache.get_or_create_ref_layout(ref)
-
-    def get_or_create_pkg_layout(self, ref: PkgReference):
-        return self._data_cache.get_or_create_pkg_layout(ref)
-
-    def remove_recipe_layout(self, layout):
-        self._data_cache.remove_recipe(layout)
-
-    def remove_package_layout(self, layout):
-        self._data_cache.remove_package(layout)
-
-    def remove_build_id(self, pref):
-        self._data_cache.remove_build_id(pref)
-
-    def update_recipe_timestamp(self, ref):
-        """ when the recipe already exists in cache, but we get a new timestamp from a server
-        that would affect its order in our cache """
-        return self._data_cache.update_recipe_timestamp(ref)
-
-    def all_refs(self):
-        return self._data_cache.list_references()
-
-    def exists_prev(self, pref):
-        # Used just by download to skip downloads if prev already exists in cache
-        return self._data_cache.exists_prev(pref)
-
-    def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):
-        return self._data_cache.get_package_revisions_references(pref, only_latest_prev)
-
-    def get_package_references(self, ref: RecipeReference,
-                               only_latest_prev=True) -> List[PkgReference]:
-        """Get the latest package references"""
-        return self._data_cache.get_package_references(ref, only_latest_prev)
-
-    def get_matching_build_id(self, ref, build_id):
-        return self._data_cache.get_matching_build_id(ref, build_id)
-
-    def get_latest_package_reference(self, pref):
-        return self._data_cache.get_latest_package_reference(pref)
-
-    def get_recipe_lru(self, ref):
-        return self._data_cache.get_recipe_lru(ref)
-
-    def update_recipe_lru(self, ref):
-        self._data_cache.update_recipe_lru(ref)
-
-    def get_package_lru(self, pref):
-        return self._data_cache.get_package_lru(pref)
-
-    def update_package_lru(self, pref):
-        self._data_cache.update_package_lru(pref)
-
-    @property
-    def store(self):
-        return self._store_folder
-
-    @property
-    def localdb(self):
-        localdb_filename = os.path.join(self.cache_folder, LOCALDB)
-        return LocalDB(localdb_filename)
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
index 15836051d..bf64917c7 100644
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -94,14 +94,14 @@ compiler:
                     "10", "10.1", "10.2", "10.3", "10.4", "10.5",
                     "11", "11.1", "11.2", "11.3", "11.4",
                     "12", "12.1", "12.2", "12.3",
-                    "13", "13.1", "13.2", 
+                    "13", "13.1", "13.2", "13.3",
                     "14", "14.1"]
         libcxx: [libstdc++, libstdc++11]
         threads: [null, posix, win32]  # Windows MinGW
         exception: [null, dwarf2, sjlj, seh]  # Windows MinGW
         cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
     msvc:
-        version: [170, 180, 190, 191, 192, 193]
+        version: [170, 180, 190, 191, 192, 193, 194]
         update: [null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
         runtime: [static, dynamic]
         runtime_type: [Debug, Release]
diff --git a/conans/client/conf/config_installer.py b/conans/client/conf/config_installer.py
index 82f39daa0..4cb240fa6 100644
--- a/conans/client/conf/config_installer.py
+++ b/conans/client/conf/config_installer.py
@@ -8,7 +8,7 @@ from contextlib import contextmanager
 from conan.api.output import ConanOutput
 from conans.client.downloaders.file_downloader import FileDownloader
 from conans.errors import ConanException
-from conans.util.files import mkdir, rmdir, remove, unzip, chdir, load
+from conans.util.files import mkdir, rmdir, remove, unzip, chdir
 from conans.util.runners import detect_runner
 
 
@@ -44,8 +44,8 @@ def _hide_password(resource):
 
 
 @contextmanager
-def tmp_config_install_folder(cache):
-    tmp_folder = os.path.join(cache.cache_folder, "tmp_config_install")
+def tmp_config_install_folder(cache_folder):
+    tmp_folder = os.path.join(cache_folder, "tmp_config_install")
     # necessary for Mac OSX, where the temp folders in /var/ are symlinks to /private/var/
     tmp_folder = os.path.abspath(tmp_folder)
     rmdir(tmp_folder)
@@ -56,24 +56,24 @@ def tmp_config_install_folder(cache):
         rmdir(tmp_folder)
 
 
-def _process_git_repo(config, cache):
+def _process_git_repo(config, cache_folder):
     output = ConanOutput()
     output.info("Trying to clone repo: %s" % config.uri)
-    with tmp_config_install_folder(cache) as tmp_folder:
+    with tmp_config_install_folder(cache_folder) as tmp_folder:
         with chdir(tmp_folder):
             args = config.args or ""
             ret, out = detect_runner('git clone "{}" . {}'.format(config.uri, args))
             if ret != 0:
                 raise ConanException("Can't clone repo: {}".format(out))
             output.info("Repo cloned!")
-        _process_folder(config, tmp_folder, cache)
+        _process_folder(config, tmp_folder, cache_folder)
 
 
-def _process_zip_file(config, zippath, cache, tmp_folder, first_remove=False):
+def _process_zip_file(config, zippath, cache_folder, tmp_folder, first_remove=False):
     unzip(zippath, tmp_folder)
     if first_remove:
         os.unlink(zippath)
-    _process_folder(config, tmp_folder, cache)
+    _process_folder(config, tmp_folder, cache_folder)
 
 
 def _filecopy(src, filename, dst):
@@ -91,20 +91,20 @@ def _filecopy(src, filename, dst):
     shutil.copyfile(src, dst)
 
 
-def _process_file(directory, filename, config, cache, folder):
+def _process_file(directory, filename, config, cache_folder, folder):
     output = ConanOutput()
     if filename == "settings.yml":
         output.info("Installing settings.yml")
-        _filecopy(directory, filename, cache.cache_folder)
+        _filecopy(directory, filename, cache_folder)
     elif filename == "remotes.json":
         output.info("Defining remotes from remotes.json")
-        _filecopy(directory, filename, cache.cache_folder)
+        _filecopy(directory, filename, cache_folder)
     else:
         relpath = os.path.relpath(directory, folder)
         if config.target_folder:
-            target_folder = os.path.join(cache.cache_folder, config.target_folder, relpath)
+            target_folder = os.path.join(cache_folder, config.target_folder, relpath)
         else:
-            target_folder = os.path.join(cache.cache_folder, relpath)
+            target_folder = os.path.join(cache_folder, relpath)
 
         if os.path.isfile(target_folder):  # Existed as a file and now should be a folder
             remove(target_folder)
@@ -114,7 +114,7 @@ def _process_file(directory, filename, config, cache, folder):
         _filecopy(directory, filename, target_folder)
 
 
-def _process_folder(config, folder, cache, ignore=None):
+def _process_folder(config, folder, cache_folder, ignore=None):
     if not os.path.isdir(folder):
         raise ConanException("No such directory: '%s'" % str(folder))
     if config.source_folder:
@@ -127,12 +127,12 @@ def _process_folder(config, folder, cache, ignore=None):
         for f in files:
             rel_path = os.path.relpath(os.path.join(root, f), folder)
             if not conanignore.matches(rel_path):
-                _process_file(root, f, config, cache, folder)
+                _process_file(root, f, config, cache_folder, folder)
 
 
-def _process_download(config, cache, requester):
+def _process_download(config, cache_folder, requester):
     output = ConanOutput()
-    with tmp_config_install_folder(cache) as tmp_folder:
+    with tmp_config_install_folder(cache_folder) as tmp_folder:
         output.info("Trying to download  %s" % _hide_password(config.uri))
         path = urlsplit(config.uri).path
         filename = os.path.basename(path)
@@ -141,7 +141,7 @@ def _process_download(config, cache, requester):
             downloader = FileDownloader(requester=requester)
             downloader.download(url=config.uri, file_path=zippath, verify_ssl=config.verify_ssl,
                                 retry=1)
-            _process_zip_file(config, zippath, cache, tmp_folder, first_remove=True)
+            _process_zip_file(config, zippath, cache_folder, tmp_folder, first_remove=True)
         except Exception as e:
             raise ConanException("Error while installing config from %s\n%s" % (config.uri, str(e)))
 
@@ -181,22 +181,23 @@ def _is_compressed_file(filename):
 
 def configuration_install(app, uri, verify_ssl, config_type=None,
                           args=None, source_folder=None, target_folder=None, ignore=None):
-    cache, requester = app.cache, app.requester
+    requester = app.requester
+    cache_folder = app.cache_folder
     config = _ConfigOrigin(uri, config_type, verify_ssl, args, source_folder, target_folder)
     try:
         if config.type == "git":
-            _process_git_repo(config, cache)
+            _process_git_repo(config, cache_folder)
         elif config.type == "dir":
-            _process_folder(config, config.uri, cache, ignore)
+            _process_folder(config, config.uri, cache_folder, ignore)
         elif config.type == "file":
             if _is_compressed_file(config.uri):
-                with tmp_config_install_folder(cache) as tmp_folder:
-                    _process_zip_file(config, config.uri, cache, tmp_folder)
+                with tmp_config_install_folder(cache_folder) as tmp_folder:
+                    _process_zip_file(config, config.uri, cache_folder, tmp_folder)
             else:
                 dirname, filename = os.path.split(config.uri)
-                _process_file(dirname, filename, config, cache, dirname)
+                _process_file(dirname, filename, config, cache_folder, dirname)
         elif config.type == "url":
-            _process_download(config, cache, requester=requester)
+            _process_download(config, cache_folder, requester=requester)
         else:
             raise ConanException("Unable to process config install: %s" % config.uri)
     except Exception as e:
diff --git a/conans/client/conf/detect_vs.py b/conans/client/conf/detect_vs.py
index f0c48c749..4db783a87 100644
--- a/conans/client/conf/detect_vs.py
+++ b/conans/client/conf/detect_vs.py
@@ -12,7 +12,7 @@ def vs_installation_path(version):
 
 
 def vs_detect_update(version):
-    version = {"193": "17", "192": "16", "191": "15"}.get(str(version))
+    version = {"194": "17", "193": "17", "192": "16", "191": "15"}.get(str(version))
     full_version = _vs_installation_path(version)[1]
     components = full_version.split(".")
     if len(components) > 1:
diff --git a/conans/client/downloaders/caching_file_downloader.py b/conans/client/downloaders/caching_file_downloader.py
index 4b7914f60..24155ad11 100644
--- a/conans/client/downloaders/caching_file_downloader.py
+++ b/conans/client/downloaders/caching_file_downloader.py
@@ -21,7 +21,7 @@ class SourcesCachingDownloader:
         helpers = getattr(conanfile, "_conan_helpers")
         self._global_conf = helpers.global_conf
         self._file_downloader = FileDownloader(helpers.requester, scope=conanfile.display_name)
-        self._cache = helpers.cache
+        self._home_folder = helpers.home_folder
         self._output = conanfile.output
         self._conanfile = conanfile
 
@@ -49,7 +49,7 @@ class SourcesCachingDownloader:
         something is found.
         """
         # We are going to use the download_urls definition for backups
-        download_cache_folder = download_cache_folder or HomePaths(self._cache.cache_folder).default_sources_backup_folder
+        download_cache_folder = download_cache_folder or HomePaths(self._home_folder).default_sources_backup_folder
         # regular local shared download cache, not using Conan backup sources servers
         backups_urls = backups_urls or ["origin"]
         if download_cache_folder and not os.path.isabs(download_cache_folder):
diff --git a/conans/client/downloaders/file_downloader.py b/conans/client/downloaders/file_downloader.py
index 318088a36..676af7a07 100644
--- a/conans/client/downloaders/file_downloader.py
+++ b/conans/client/downloaders/file_downloader.py
@@ -49,6 +49,7 @@ class FileDownloader:
                         time.sleep(retry_wait)
 
             self.check_checksum(file_path, md5, sha1, sha256)
+            self._output.debug(f"Downloaded {file_path} from {url}")
         except Exception:
             if os.path.exists(file_path):
                 os.remove(file_path)
diff --git a/conans/client/graph/compatibility.py b/conans/client/graph/compatibility.py
index c72c4377c..967ddc90e 100644
--- a/conans/client/graph/compatibility.py
+++ b/conans/client/graph/compatibility.py
@@ -30,26 +30,43 @@ from conan.errors import ConanException
 def cppstd_compat(conanfile):
     # It will try to find packages with all the cppstd versions
     extension_properties = getattr(conanfile, "extension_properties", {})
-    if extension_properties.get("compatibility_cppstd") is False:
-        return []
     compiler = conanfile.settings.get_safe("compiler")
     compiler_version = conanfile.settings.get_safe("compiler.version")
     cppstd = conanfile.settings.get_safe("compiler.cppstd")
-    if not compiler or not compiler_version or not cppstd:
+    if not compiler or not compiler_version:
         return []
     base = dict(conanfile.settings.values_list)
-    cppstd_possible_values = supported_cppstd(conanfile)
-    if cppstd_possible_values is None:
-        conanfile.output.warning(f'No cppstd compatibility defined for compiler "{compiler}"')
-        return []
-    ret = []
-    for _cppstd in cppstd_possible_values:
-        if _cppstd is None or _cppstd == cppstd:
+    factors = []  # List of list, each sublist is a potential combination
+    if cppstd is not None and extension_properties.get("compatibility_cppstd") is not False:
+        cppstd_possible_values = supported_cppstd(conanfile)
+        if cppstd_possible_values is None:
+            conanfile.output.warning(f'No cppstd compatibility defined for compiler "{compiler}"')
+        else:
+            factors.append([{"compiler.cppstd": v} for v in cppstd_possible_values if v != cppstd])
+
+    if compiler == "msvc":
+        msvc_fallback = {"194": "193"}.get(compiler_version)
+        if msvc_fallback:
+            factors.append([{"compiler.version": msvc_fallback}])
+
+    combinations = []
+    for factor in factors:
+        if not combinations:
+            combinations = factor
             continue
+        new_combinations = []
+        for comb in combinations:
+            for f in factor:
+                comb = comb.copy()
+                comb.update(f)
+                new_combinations.append(comb)
+        combinations = new_combinations
+
+    ret = []
+    for comb in combinations:
         configuration = base.copy()
-        configuration["compiler.cppstd"] = _cppstd
+        configuration.update(comb)
         ret.append({"settings": [(k, v) for k, v in configuration.items()]})
-
     return ret
 """
 
diff --git a/conans/client/graph/graph.py b/conans/client/graph/graph.py
index f6f1ba5cb..453cbf851 100644
--- a/conans/client/graph/graph.py
+++ b/conans/client/graph/graph.py
@@ -97,6 +97,11 @@ class Node(object):
                 # print("  +++++Runtime conflict!", require, "with", node.ref)
                 return True
             require.aggregate(existing.require)
+            # An override can be overriden by a downstream force/override
+            if existing.require.override and existing.require.ref != require.ref:
+                # If it is an override, but other value, it has been overriden too
+                existing.require.overriden_ref = existing.require.ref
+                existing.require.override_ref = require.ref
 
         assert not require.version_range  # No ranges slip into transitive_deps definitions
         # TODO: Might need to move to an update() for performance
@@ -118,6 +123,7 @@ class Node(object):
         if down_require is None:
             return
 
+        down_require.defining_require = require.defining_require
         return d.src.propagate_downstream(down_require, node)
 
     def check_downstream_exists(self, require):
@@ -128,6 +134,9 @@ class Node(object):
             if require.build and (self.context == CONTEXT_HOST or  # switch context
                                   require.ref.version != self.ref.version):  # or different version
                 pass
+            elif require.visible is False and require.ref.version != self.ref.version:
+                # Experimental, to support repackaging of openssl previous versions FIPS plugins
+                pass  # An invisible require doesn't conflict with itself
             else:
                 return None, self, self  # First is the require, as it is a loop => None
 
@@ -161,6 +170,7 @@ class Node(object):
             # print("    No need to check downstream more")
             return result
 
+        down_require.defining_require = require.defining_require
         source_node = dependant.src
         return source_node.check_downstream_exists(down_require) or result
 
@@ -275,9 +285,9 @@ class Overrides:
         overrides = {}
         for n in nodes:
             for r in n.conanfile.requires.values():
-                if r.override:
+                if r.override and not r.overriden_ref:  # overrides are not real graph edges
                     continue
-                if r.overriden_ref and not r.force:
+                if r.overriden_ref:
                     overrides.setdefault(r.overriden_ref, set()).add(r.override_ref)
                 else:
                     overrides.setdefault(r.ref, set()).add(None)
diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py
index 6663bca70..333893d2a 100644
--- a/conans/client/graph/graph_binaries.py
+++ b/conans/client/graph/graph_binaries.py
@@ -25,11 +25,12 @@ class GraphBinariesAnalyzer(object):
 
     def __init__(self, conan_app, global_conf):
         self._cache = conan_app.cache
+        self._home_folder = conan_app.cache_folder
         self._global_conf = global_conf
         self._remote_manager = conan_app.remote_manager
         # These are the nodes with pref (not including PREV) that have been evaluated
         self._evaluated = {}  # {pref: [nodes]}
-        compat_folder = HomePaths(self._cache.cache_folder).compatibility_plugin_path
+        compat_folder = HomePaths(conan_app.cache_folder).compatibility_plugin_path
         self._compatibility = BinaryCompatibility(compat_folder)
 
     @staticmethod
@@ -150,7 +151,7 @@ class GraphBinariesAnalyzer(object):
             if node.binary in (BINARY_CACHE, BINARY_UPDATE, BINARY_DOWNLOAD):
                 _compatible_found(package_id, compatible_package)
                 return
-        if not update:
+        if not should_update_reference(conanfile.ref, update):
             conanfile.output.info(f"Compatible configurations not found in cache, checking servers")
             for package_id, compatible_package in compatibles.items():
                 conanfile.output.info(f"'{package_id}': "
@@ -335,7 +336,7 @@ class GraphBinariesAnalyzer(object):
         config_mode = self._global_conf.get("core.package_id:config_mode", default=None)
         if config_mode is None:
             return
-        config_version_file = HomePaths(self._cache.cache_folder).config_version_path
+        config_version_file = HomePaths(self._home_folder).config_version_path
         try:
             config_refs = json.loads(load(config_version_file))["config_version"]
             result = OrderedDict()
@@ -350,7 +351,7 @@ class GraphBinariesAnalyzer(object):
         except Exception as e:
             raise ConanException(f"core.package_id:config_mode defined, but error while loading "
                                  f"'{os.path.basename(config_version_file)}'"
-                                 f" file in cache: {self._cache.cache_folder}: {e}")
+                                 f" file in cache: {self._home_folder}: {e}")
         return RequirementsInfo(result)
 
     def _evaluate_package_id(self, node, config_version):
diff --git a/conans/client/graph/graph_builder.py b/conans/client/graph/graph_builder.py
index 937d32f76..64c9a4bad 100644
--- a/conans/client/graph/graph_builder.py
+++ b/conans/client/graph/graph_builder.py
@@ -81,9 +81,13 @@ class DepsGraphBuilder(object):
 
             prev_ref = prev_node.ref if prev_node else prev_require.ref
             if prev_require.force or prev_require.override:  # override
-                require.overriden_ref = require.ref  # Store that the require has been overriden
-                require.override_ref = prev_ref
-                require.ref = prev_ref
+                if prev_require.defining_require is not require:
+                    require.overriden_ref = require.overriden_ref or require.ref.copy()  # Old one
+                    # require.override_ref can be !=None if lockfile-overrides defined
+                    require.override_ref = (require.override_ref or prev_require.override_ref
+                                            or prev_require.ref.copy())  # New one
+                    require.defining_require = prev_require.defining_require  # The overrider
+                require.ref = prev_ref  # New one, maybe resolved with revision
             else:
                 self._conflicting_version(require, node, prev_require, prev_node,
                                           prev_ref, base_previous, self._resolve_prereleases)
@@ -195,6 +199,8 @@ class DepsGraphBuilder(object):
                 if not resolved:
                     self._resolve_alias(node, require, alias, graph)
             self._resolve_replace_requires(node, require, profile_build, profile_host, graph)
+            if graph_lock:
+                graph_lock.resolve_overrides(require)
             node.transitive_deps[require] = TransitiveRequirement(require, node=None)
 
     def _resolve_alias(self, node, require, alias, graph):
diff --git a/conans/client/graph/install_graph.py b/conans/client/graph/install_graph.py
index 2471e1f62..14775ab01 100644
--- a/conans/client/graph/install_graph.py
+++ b/conans/client/graph/install_graph.py
@@ -160,7 +160,7 @@ class _InstallRecipeReference:
             if dep.dst.binary != BINARY_SKIP:
                 if dep.dst.ref == node.ref:  # If the node is itself, then it is internal dep
                     install_pkg_ref.depends.append(dep.dst.pref.package_id)
-                else:
+                elif dep.dst.ref not in self.depends:
                     self.depends.append(dep.dst.ref)
 
     def _install_order(self):
@@ -510,7 +510,7 @@ class InstallGraph:
 
         raise ConanException(textwrap.dedent(f'''\
            Missing prebuilt package for '{missing_pkgs}'. You can try:
-               - List all available packages using 'conan list {ref}:* -r=remote'
+               - List all available packages using 'conan list "{ref}:*" -r=remote'
                - Explain missing binaries: replace 'conan install ...' with 'conan graph explain ...'
                - {build_msg}
 
diff --git a/conans/client/graph/range_resolver.py b/conans/client/graph/range_resolver.py
index 16336607c..535cc5ce2 100644
--- a/conans/client/graph/range_resolver.py
+++ b/conans/client/graph/range_resolver.py
@@ -17,7 +17,12 @@ class RangeResolver:
         self._resolve_prereleases = global_conf.get('core.version_ranges:resolve_prereleases')
 
     def resolve(self, require, base_conanref, remotes, update):
-        version_range = require.version_range
+        try:
+            version_range = require.version_range
+        except Exception as e:
+            base = base_conanref or "conanfile"
+            raise ConanException(f"\n    Recipe '{base}' requires '{require.ref}' "
+                                 f"version-range definition error:\n    {e}")
         if version_range is None:
             return
         assert isinstance(version_range, VersionRange)
diff --git a/conans/client/pkg_sign.py b/conans/client/pkg_sign.py
index b1addaaa1..40207d362 100644
--- a/conans/client/pkg_sign.py
+++ b/conans/client/pkg_sign.py
@@ -7,9 +7,9 @@ from conans.util.files import mkdir
 
 
 class PkgSignaturesPlugin:
-    def __init__(self, cache):
+    def __init__(self, cache, home_folder):
         self._cache = cache
-        signer = HomePaths(cache.cache_folder).sign_plugin_path
+        signer = HomePaths(home_folder).sign_plugin_path
         if os.path.isfile(signer):
             mod, _ = load_python_file(signer)
             # TODO: At the moment it requires both methods sign and verify, but that might be relaxed
diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py
index 4feb4a094..9827b83d7 100644
--- a/conans/client/remote_manager.py
+++ b/conans/client/remote_manager.py
@@ -22,14 +22,15 @@ from conans.util.files import mkdir, tar_extract
 
 class RemoteManager:
     """ Will handle the remotes to get recipes, packages etc """
-    def __init__(self, cache, auth_manager):
+    def __init__(self, cache, auth_manager, home_folder):
         self._cache = cache
         self._auth_manager = auth_manager
-        self._signer = PkgSignaturesPlugin(cache)
+        self._signer = PkgSignaturesPlugin(cache, home_folder)
+        self._home_folder = home_folder
 
     def _local_folder_remote(self, remote):
         if remote.remote_type == LOCAL_RECIPES_INDEX:
-            return RestApiClientLocalRecipesIndex(remote, self._cache)
+            return RestApiClientLocalRecipesIndex(remote, self._home_folder)
 
     def check_credentials(self, remote):
         self._call_remote(remote, "check_credentials")
diff --git a/conans/client/rest/auth_manager.py b/conans/client/rest/auth_manager.py
index 603cc5177..cf1ab8dde 100644
--- a/conans/client/rest/auth_manager.py
+++ b/conans/client/rest/auth_manager.py
@@ -23,11 +23,11 @@ LOGIN_RETRIES = 3
 
 class ConanApiAuthManager(object):
 
-    def __init__(self, rest_client_factory, cache, global_conf):
+    def __init__(self, rest_client_factory, cache_folder, localdb, global_conf):
         self._rest_client_factory = rest_client_factory
-        self._localdb = cache.localdb
+        self._localdb = localdb
         self._global_conf = global_conf
-        self._cache_folder = cache.cache_folder
+        self._cache_folder = cache_folder
 
     def call_rest_api_method(self, remote, method_name, *args, **kwargs):
         """Handles AuthenticationException and request user to input a user and a password"""
diff --git a/conans/client/rest_client_local_recipe_index.py b/conans/client/rest_client_local_recipe_index.py
index 5aa92690f..36d3b516e 100644
--- a/conans/client/rest_client_local_recipe_index.py
+++ b/conans/client/rest_client_local_recipe_index.py
@@ -54,9 +54,9 @@ class RestApiClientLocalRecipesIndex:
     a local folder assuming the conan-center-index repo layout
     """
 
-    def __init__(self, remote, cache):
+    def __init__(self, remote, home_folder):
         self._remote = remote
-        local_recipes_index_path = HomePaths(cache.cache_folder).local_recipes_index_path
+        local_recipes_index_path = HomePaths(home_folder).local_recipes_index_path
         local_recipes_index_path = os.path.join(local_recipes_index_path, remote.name)
         local_recipes_index_path = os.path.join(local_recipes_index_path, ".conan")
         repo_folder = self._remote.url
diff --git a/conans/client/source.py b/conans/client/source.py
index ab812a45c..6c7617242 100644
--- a/conans/client/source.py
+++ b/conans/client/source.py
@@ -82,6 +82,6 @@ def run_source_method(conanfile, hook_manager):
         if hasattr(conanfile, "source"):
             conanfile.output.highlight("Calling source() in {}".format(conanfile.source_folder))
             with conanfile_exception_formatter(conanfile, "source"):
-                with conanfile_remove_attr(conanfile, ['settings', "options"], "source"):
+                with conanfile_remove_attr(conanfile, ['info', 'settings', "options"], "source"):
                     conanfile.source()
         hook_manager.execute("post_source", conanfile=conanfile)
diff --git a/conans/client/store/localdb.py b/conans/client/store/localdb.py
index 8525256b6..9b95d8701 100644
--- a/conans/client/store/localdb.py
+++ b/conans/client/store/localdb.py
@@ -7,21 +7,22 @@ from conans.errors import ConanException
 from conans.util import encrypt
 
 REMOTES_USER_TABLE = "users_remotes"
+LOCALDB = ".conan.db"
 
 _localdb_encryption_key = os.environ.pop('CONAN_LOGIN_ENCRYPTION_KEY', None)
 
 
 class LocalDB:
 
-    def __init__(self, dbfile):
-        self.dbfile = dbfile
+    def __init__(self, dbfolder):
+        self.dbfile = os.path.join(dbfolder, LOCALDB)
         self.encryption_key = _localdb_encryption_key
 
         # Create the database file if it doesn't exist
-        if not os.path.exists(dbfile):
-            par = os.path.dirname(dbfile)
+        if not os.path.exists(self.dbfile):
+            par = os.path.dirname(self.dbfile)
             os.makedirs(par, exist_ok=True)
-            open(dbfile, 'w').close()
+            open(self.dbfile, 'w').close()
 
             with self._connect() as connection:
                 try:
@@ -30,7 +31,7 @@ class LocalDB:
                                    "(remote_url TEXT UNIQUE, user TEXT, "
                                    "token TEXT, refresh_token TEXT)" % REMOTES_USER_TABLE)
                 except Exception as e:
-                    message = f"Could not initialize local sqlite database {dbfile}"
+                    message = f"Could not initialize local sqlite database {self.dbfile}"
                     raise ConanException(message, e)
 
     def _encode(self, value):
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
index 03118d236..96e819ff1 100644
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -238,6 +238,8 @@ class ConanFile:
 
     @property
     def source_path(self) -> Path:
+        self.output.warning(f"Use of 'source_path' is deprecated, please use 'source_folder' instead",
+                            warn_tag="deprecated")
         assert self.source_folder is not None, "`source_folder` is `None`"
         return Path(self.source_folder)
 
@@ -258,6 +260,8 @@ class ConanFile:
 
     @property
     def export_sources_path(self) -> Path:
+        self.output.warning(f"Use of 'export_sources_path' is deprecated, please use "
+                            f"'export_sources_folder' instead", warn_tag="deprecated")
         assert self.export_sources_folder is not None, "`export_sources_folder` is `None`"
         return Path(self.export_sources_folder)
 
@@ -267,6 +271,9 @@ class ConanFile:
 
     @property
     def export_path(self) -> Path:
+        self.output.warning(f"Use of 'export_path' is deprecated, please use 'export_folder' instead",
+                            warn_tag="deprecated")
+
         assert self.export_folder is not None, "`export_folder` is `None`"
         return Path(self.export_folder)
 
@@ -291,6 +298,8 @@ class ConanFile:
 
     @property
     def build_path(self) -> Path:
+        self.output.warning(f"Use of 'build_path' is deprecated, please use 'build_folder' instead",
+                            warn_tag="deprecated")
         assert self.build_folder is not None, "`build_folder` is `None`"
         return Path(self.build_folder)
 
@@ -310,11 +319,16 @@ class ConanFile:
 
     @property
     def package_path(self) -> Path:
+        self.output.warning(f"Use of 'package_path' is deprecated, please use 'package_folder' instead",
+                            warn_tag="deprecated")
+
         assert self.package_folder is not None, "`package_folder` is `None`"
         return Path(self.package_folder)
 
     @property
     def generators_path(self) -> Path:
+        self.output.warning(f"Use of 'generators_path' is deprecated, please use "
+                            f"'generators_folder' instead", warn_tag="deprecated")
         assert self.generators_folder is not None, "`generators_folder` is `None`"
         return Path(self.generators_folder)
 
diff --git a/conans/model/conf.py b/conans/model/conf.py
index 5098608e9..ef758d342 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -116,7 +116,7 @@ BUILT_IN_CONFS = {
     "tools.build:compiler_executables": "Defines a Python dict-like with the compilers path to be used. Allowed keys {'c', 'cpp', 'cuda', 'objc', 'objcxx', 'rc', 'fortran', 'asm', 'hip', 'ispc', 'ld', 'ar'}",
     "tools.build:cxxflags": "List of extra CXX flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
     "tools.build:cflags": "List of extra C flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
-    "tools.build:defines": "List of extra definition flags used by different toolchains like CMakeToolchain and AutotoolsToolchain",
+    "tools.build:defines": "List of extra definition flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
     "tools.build:sharedlinkflags": "List of extra flags used by CMakeToolchain for CMAKE_SHARED_LINKER_FLAGS_INIT variable",
     "tools.build:exelinkflags": "List of extra flags used by CMakeToolchain for CMAKE_EXE_LINKER_FLAGS_INIT variable",
     "tools.build:linker_scripts": "List of linker script files to pass to the linker used by different toolchains like CMakeToolchain, AutotoolsToolchain, and MesonToolchain",
diff --git a/conans/model/graph_lock.py b/conans/model/graph_lock.py
index 2ac43ac58..29e87de77 100644
--- a/conans/model/graph_lock.py
+++ b/conans/model/graph_lock.py
@@ -261,7 +261,6 @@ class Lockfile(object):
             locked_refs = self._conf_requires.refs()
         else:
             locked_refs = self._requires.refs()
-        self._resolve_overrides(require)
         try:
             self._resolve(require, locked_refs, resolve_prereleases)
         except ConanException:
@@ -273,13 +272,19 @@ class Lockfile(object):
                 ConanOutput().error(msg, error_type="exception")
             raise
 
-    def _resolve_overrides(self, require):
-        existing = self._overrides.get(require.ref)
-        if existing is not None and len(existing) == 1:
-            require.overriden_ref = require.ref  # Store that the require has been overriden
-            ref = next(iter(existing))
-            require.ref = ref
-            require.override_ref = ref
+    def resolve_overrides(self, require):
+        """ The lockfile contains the overrides to be able to inject them when the lockfile is
+        applied to upstream dependencies, that have the overrides downstream
+        """
+        if not self._overrides:
+            return
+
+        overriden = self._overrides.get(require.ref)
+        if overriden and len(overriden) == 1:
+            override_ref = next(iter(overriden))
+            require.overriden_ref = require.overriden_ref or require.ref.copy()
+            require.override_ref = override_ref
+            require.ref = override_ref
 
     def resolve_prev(self, node):
         if node.context == CONTEXT_BUILD:
diff --git a/conans/model/recipe_ref.py b/conans/model/recipe_ref.py
index ebbe5c189..01168f09f 100644
--- a/conans/model/recipe_ref.py
+++ b/conans/model/recipe_ref.py
@@ -26,6 +26,11 @@ class RecipeReference:
         self.revision = revision
         self.timestamp = timestamp
 
+    def copy(self):
+        # Used for creating copy in lockfile-overrides mechanism
+        return RecipeReference(self.name, self.version, self.user, self.channel, self.revision,
+                               self.timestamp)
+
     def __repr__(self):
         """ long repr like pkg/0.1@user/channel#rrev%timestamp """
         result = self.repr_notime()
diff --git a/conans/model/requires.py b/conans/model/requires.py
index 428bb5968..23987d0dc 100644
--- a/conans/model/requires.py
+++ b/conans/model/requires.py
@@ -29,6 +29,9 @@ class Requirement:
         self._direct = direct
         self.options = options
         # Meta and auxiliary information
+        # The "defining_require" is the require that defines the current value. If this require is
+        # overriden/forced, this attribute will point to the overriding/forcing requirement.
+        self.defining_require = self  # if not overriden, it points to itself
         self.overriden_ref = None  # to store if the requirement has been overriden (store old ref)
         self.override_ref = None  # to store if the requirement has been overriden (store new ref)
         self.is_test = test  # to store that it was a test, even if used as regular requires too
@@ -518,16 +521,6 @@ class Requirements:
             raise ConanException("Duplicated requirement: {}".format(ref))
         self._requires[req] = req
 
-    def override(self, ref):
-        req = Requirement(ref)
-        old_requirement = self._requires.get(req)
-        if old_requirement is not None:
-            req.force = True
-            self._requires[req] = req
-        else:
-            req.override = True
-            self._requires[req] = req
-
     def test_require(self, ref, run=None, options=None, force=None):
         """
              Represent a testing framework like gtest


Test patch:
diff --git a/conans/test/functional/command/config_install_test.py b/conans/test/functional/command/config_install_test.py
index 7ee9c34bd..43114c6b5 100644
--- a/conans/test/functional/command/config_install_test.py
+++ b/conans/test/functional/command/config_install_test.py
@@ -587,7 +587,7 @@ class ConfigInstallSchedTest(unittest.TestCase):
         assert os.path.basename(client.cache_folder) == DEFAULT_CONAN_HOME
         client.run('config install "%s/.git" --type git' % self.folder)
         conf = load(client.cache.new_config_path)
-        dirs = os.listdir(client.cache.cache_folder)
+        dirs = os.listdir(client.cache_folder)
         assert ".git" not in dirs
 
 
diff --git a/conans/test/functional/layout/test_editable_cmake.py b/conans/test/functional/layout/test_editable_cmake.py
index 16568c844..7fd00b57f 100644
--- a/conans/test/functional/layout/test_editable_cmake.py
+++ b/conans/test/functional/layout/test_editable_cmake.py
@@ -13,8 +13,7 @@ from conans.test.utils.tools import TestClient
 def editable_cmake(generator, build_folder=None):
     c = TestClient()
     if generator is not None:
-        c.save({"global.conf": "tools.cmake.cmaketoolchain:generator={}".format(generator)},
-               path=os.path.join(c.cache.cache_folder))
+        c.save_home({"global.conf": "tools.cmake.cmaketoolchain:generator={}".format(generator)})
     c.save(pkg_cmake("dep", "0.1"), path=os.path.join(c.current_folder, "dep"))
     c.save(pkg_cmake_app("pkg", "0.1", requires=["dep/0.1"]),
            path=os.path.join(c.current_folder, "pkg"))
@@ -102,8 +101,7 @@ def editable_cmake_exe(generator):
     # --install folder
     c = TestClient()
     if generator is not None:
-        c.save({"global.conf": "tools.cmake.cmaketoolchain:generator={}".format(generator)},
-               path=os.path.join(c.cache.cache_folder))
+        c.save_home({"global.conf": "tools.cmake.cmaketoolchain:generator={}".format(generator)})
     c.save(pkg_cmake("dep", "0.1", exe=True), path=os.path.join(c.current_folder, "dep"))
 
     def build_dep():
diff --git a/conans/test/functional/only_source_test.py b/conans/test/functional/only_source_test.py
index c51b146c3..2a1a7cc04 100644
--- a/conans/test/functional/only_source_test.py
+++ b/conans/test/functional/only_source_test.py
@@ -30,7 +30,7 @@ class OnlySourceTest(unittest.TestCase):
                       "--build=hello1/1.1@lasote/stable'",
                       client.out)
         # Only 1 reference!
-        assert "List all available packages using 'conan list hello0/0.0@lasote/stable:* -r=remote'" in client.out
+        assert "List all available packages using 'conan list \"hello0/0.0@lasote/stable:*\" -r=remote'" in client.out
 
         # We generate the package for hello0/0.0
         client.run("install --requires=hello0/0.0@lasote/stable --build hello0*")
diff --git a/conans/test/integration/cache/backup_sources_test.py b/conans/test/integration/cache/backup_sources_test.py
index e5671ab87..db70e24c7 100644
--- a/conans/test/integration/cache/backup_sources_test.py
+++ b/conans/test/integration/cache/backup_sources_test.py
@@ -1,6 +1,5 @@
 import json
 import os
-import shutil
 import textwrap
 from unittest import mock
 
@@ -25,9 +24,9 @@ class TestDownloadCacheBackupSources:
                         custom_download):
             client = TestClient(default_server_user=True, light=True)
             tmp_folder = temp_folder()
-            client.save({"global.conf": f"core.sources:download_cache={tmp_folder}\n"
-                                        "core.sources:download_urls=['origin', 'http://myback']"},
-                        path=client.cache.cache_folder)
+            client.save_home(
+                {"global.conf": f"core.sources:download_cache={tmp_folder}\n"
+                                "core.sources:download_urls=['origin', 'http://myback']"})
             sha256 = "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
             conanfile = textwrap.dedent(f"""
                 from conan import ConanFile
@@ -137,22 +136,21 @@ class TestDownloadCacheBackupSources:
 
         # Ensure that a None url is only warned about but no exception is thrown,
         # this is possible in CI systems that substitute an env var and fail to give it a value
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=[None, 'origin', '{self.file_server.fake_url}/backups/']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backups/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backups/"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .", assert_error=True)
         assert "Trying to download sources from None backup remote" in self.client.out
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['origin', '{self.file_server.fake_url}/backups/']\n"
                             f"core.sources:upload_url={self.file_server.fake_url}/backups/\n"
-                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', "
+                            f"'{self.file_server.fake_url}/mycompanystorage2/']"})
         self.client.run("create .")
 
         self.client.run("upload * -c -r=default")
@@ -184,22 +182,20 @@ class TestDownloadCacheBackupSources:
         rmdir(self.download_cache_folder)
         mkdir(self.download_cache_folder)
         # Everything the same, but try to download from backup first
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backups/', 'origin']\n"
                             f"core.sources:upload_url={self.file_server.fake_url}/backups/\n"
-                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']"})
         self.client.run("source .")
         assert f"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup" in self.client.out
         assert f"File {self.file_server.fake_url}/mycompanystorage/mycompanyfile.txt not found in {self.file_server.fake_url}/backups/" in self.client.out
 
         # Ensure defaults backup folder works if it's not set in global.conf
         # (The rest is needed to exercise the rest of the code)
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_urls=['{self.file_server.fake_url}/backups/', 'origin']\n"
-                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']"})
         self.client.run("source .")
         assert f"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup" in self.client.out
         assert f"File {self.file_server.fake_url}/mycompanystorage/mycompanyfile.txt not found in {self.file_server.fake_url}/backups/" in self.client.out
@@ -221,11 +217,10 @@ class TestDownloadCacheBackupSources:
                                      sha256="{sha256}")
                     """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['origin', '{self.file_server.fake_url}/backup/']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .")
@@ -255,14 +250,15 @@ class TestDownloadCacheBackupSources:
                                      sha256="{sha256}")
                     """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup', 'origin']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup"})
 
         self.client.save({"conanfile.py": conanfile})
-        self.client.run("create .")
+        self.client.run("create . -vv")
+        assert f"WARN: File {self.file_server.fake_url}/internet/myfile.txt not found in {self.file_server.fake_url}/backup/" in self.client.out
+        assert f"Downloaded {self.file_server.fake_url}/internet/myfile.txt from {self.file_server.fake_url}/internet/myfile.txt"
         self.client.run("upload * -c -r=default")
 
         rmdir(self.download_cache_folder)
@@ -284,15 +280,34 @@ class TestDownloadCacheBackupSources:
                             sha256="unused")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/internal_error/', "
-                            f"'{self.file_server.fake_url}/unused/']\n"},
-            path=self.client.cache.cache_folder)
+                            f"'{self.file_server.fake_url}/unused/']\n"})
+        self.client.save({"conanfile.py": conanfile})
+        self.client.run("create .", assert_error=True)
+        assert "ConanException: Error 500 downloading file" in self.client.out
+
+    def test_sources_backup_server_not_found(self):
+        conanfile = textwrap.dedent(f"""
+                   from conan import ConanFile
+                   from conan.tools.files import download
+                   class Pkg2(ConanFile):
+                       name = "pkg"
+                       version = "1.0"
+                       def source(self):
+                           download(self, "{self.file_server.fake_url}/internet/myfile.txt", "myfile.txt",
+                                    sha256="unused")
+                   """)
+
+        self.client.save_home(
+            {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
+                            f"core.download:retry=0\n"
+                            f"core.sources:download_urls=['http://locahost/nothing-here', 'origin']\n"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .", assert_error=True)
-        assert "ConanException: Error 500 downloading file " in self.client.out
+        assert "ConanException: Error downloading file" in self.client.out
 
     def test_upload_sources_backup_creds_needed(self):
         client = TestClient(default_server_user=True, light=True)
@@ -342,17 +357,18 @@ class TestDownloadCacheBackupSources:
                     self.output.info(f"CONTENT: {{load(self, 'myfile.txt')}}")
             """)
 
-        client.save({"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
-                                    f"core.sources:download_urls=['http://localhost:{http_server.port}/downloader/', 'origin']\n"
-                                    f"core.sources:upload_url=http://localhost:{http_server.port}/uploader/"},
-                    path=client.cache.cache_folder)
+        client.save_home(
+            {"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
+                            f"core.sources:download_urls=['http://localhost:{http_server.port}/downloader/', 'origin']\n"
+                            f"core.sources:upload_url=http://localhost:{http_server.port}/uploader/"})
 
         client.save({"conanfile.py": conanfile})
         client.run("create .", assert_error=True)
         assert f"ConanException: The source backup server 'http://localhost:{http_server.port}" \
                f"/downloader/' needs authentication" in client.out
-        content = {"credentials":
-                       [{"url": f"http://localhost:{http_server.port}", "token": "mytoken"}]}
+        content = {"credentials": [
+            {"url": f"http://localhost:{http_server.port}", "token": "mytoken"}
+        ]}
         save(os.path.join(client.cache_folder, "source_credentials.json"), json.dumps(content))
 
         client.run("create .")
@@ -360,8 +376,9 @@ class TestDownloadCacheBackupSources:
         client.run("upload * -c -r=default", assert_error=True)
         assert f"The source backup server 'http://localhost:{http_server.port}" \
                f"/uploader/' needs authentication" in client.out
-        content = {"credentials":
-                       [{"url": f"http://localhost:{http_server.port}", "token": "myuploadtoken"}]}
+        content = {"credentials": [
+            {"url": f"http://localhost:{http_server.port}", "token": "myuploadtoken"}
+        ]}
         # Now use the correct UPLOAD token
         save(os.path.join(client.cache_folder, "source_credentials.json"), json.dumps(content))
         client.run("upload * -c -r=default --force")  # need --force to guarantee cached updated
@@ -373,8 +390,9 @@ class TestDownloadCacheBackupSources:
         client.run("upload * -c -r=default")
         assert "already in server, skipping upload" in client.out
 
-        content = {"credentials":
-                       [{"url": f"http://localhost:{http_server.port}", "token": "mytoken"}]}
+        content = {"credentials": [
+            {"url": f"http://localhost:{http_server.port}", "token": "mytoken"}
+        ]}
 
         save(os.path.join(client.cache_folder, "source_credentials.json"), json.dumps(content))
         rmdir(download_cache_folder)
@@ -409,11 +427,11 @@ class TestDownloadCacheBackupSources:
                              sha256="{sha256}")
             """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:upload_url={self.file_server.fake_url}/backup/\n"
-                            f"core.sources:download_urls=['origin', '{self.file_server.fake_url}/downloader/', '{self.file_server.fake_url}/backup/']"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:download_urls=['origin', '{self.file_server.fake_url}/downloader/', "
+                            f"'{self.file_server.fake_url}/backup/']"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .")
@@ -462,9 +480,9 @@ class TestDownloadCacheBackupSources:
                         download(self, "http://fake/myfile.txt", "myfile.txt", sha256="{sha256}")
                 """)
 
-            client.save({"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
-                                        f"core.sources:download_urls=['origin', 'http://extrafake/']\n"},
-                        path=client.cache.cache_folder)
+            client.save_home(
+                {"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
+                                f"core.sources:download_urls=['origin', 'http://extrafake/']\n"})
             client.save({"conanfile.py": conanfile})
             client.run("source .", assert_error=True)
             assert "WARN: Sources for http://fake/myfile.txt failed in 'origin'" in client.out
@@ -490,12 +508,11 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": "tools.files.download:retry=0\n"
                             f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/empty/', "
-                            f"'origin', '{self.file_server.fake_url}/backup2/']\n"},
-            path=self.client.cache.cache_folder)
+                            f"'origin', '{self.file_server.fake_url}/backup2/']\n"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .")
@@ -537,11 +554,10 @@ class TestDownloadCacheBackupSources:
                    download(self, "http://localhost:{http_server.port}/internet/myfile.txt", "myfile.txt",
                             sha256="{sha256}")
            """)
+        client.save_home({"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
+                            f"core.sources:download_urls=['http://localhost:{http_server.port}/downloader1/', "
+                            f"'origin', 'http://localhost:{http_server.port}/downloader2/']\n"})
 
-        client.save({"global.conf": f"core.sources:download_cache={download_cache_folder}\n"
-                                    f"core.sources:download_urls=['http://localhost:{http_server.port}/downloader1/', "
-                                    f"'origin', 'http://localhost:{http_server.port}/downloader2/']\n"},
-                    path=client.cache.cache_folder)
 
         client.save({"conanfile.py": conanfile})
         client.run("create .")
@@ -570,11 +586,10 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup1/', "
-                            f"'origin', '{self.file_server.fake_url}/backup2/']\n"},
-            path=self.client.cache.cache_folder)
+                            f"'origin', '{self.file_server.fake_url}/backup2/']\n"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("create .")
@@ -601,11 +616,10 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("export .")
@@ -636,11 +650,10 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("export .")
@@ -669,11 +682,10 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("source .")
@@ -697,9 +709,8 @@ class TestDownloadCacheBackupSources:
                             sha256="{sha256}")
            """)
 
-        self.client.save(
-            {"global.conf": f"core.sources:download_cache={self.download_cache_folder}"},
-            path=self.client.cache.cache_folder)
+        self.client.save_home(
+            {"global.conf": f"core.sources:download_cache={self.download_cache_folder}"})
 
         self.client.save({"conanfile.py": conanfile})
         self.client.run("source .")
@@ -730,10 +741,9 @@ class TestDownloadCacheBackupSources:
                                                 sha256="{sha256}")
                                """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
-                            f"tools.files.download:retry=0"},
-            path=self.client.cache.cache_folder)
+                            f"tools.files.download:retry=0"})
 
         self.client.save({"conanfile.py": conanfile})
 
@@ -773,11 +783,10 @@ class TestDownloadCacheBackupSources:
                                     sha256="{sha256}")
                    """)
 
-        self.client.save(
+        self.client.save_home(
             {"global.conf": f"core.sources:download_cache={self.download_cache_folder}\n"
                             f"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\n"
-                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"},
-            path=self.client.cache.cache_folder)
+                            f"core.sources:upload_url={self.file_server.fake_url}/backup/"})
 
         self.client.save({"conanfile.py": conanfile})
         with mock.patch("conans.client.downloaders.file_downloader.FileDownloader._download_file",
diff --git a/conans/test/integration/cache/download_cache_test.py b/conans/test/integration/cache/download_cache_test.py
index 397803dcc..3cdf7b675 100644
--- a/conans/test/integration/cache/download_cache_test.py
+++ b/conans/test/integration/cache/download_cache_test.py
@@ -32,8 +32,7 @@ class TestDownloadCache:
 
         # enable cache
         tmp_folder = temp_folder()
-        client.save({"global.conf": f"core.download:download_cache={tmp_folder}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core.download:download_cache={tmp_folder}"})
         client.run("install --requires=mypkg/0.1@user/testing")
         assert "mypkg/0.1@user/testing: Downloading" in client.out
 
@@ -42,13 +41,12 @@ class TestDownloadCache:
         assert "mypkg/0.1@user/testing: Downloading" not in client.out
         assert "conan_package.tgz from download cache, instead of downloading it" in client.out
         # removing the config downloads things
-        client.save({"global.conf": ""}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": ""})
         client.run("remove * -c")
         client.run("install --requires=mypkg/0.1@user/testing")
         assert "mypkg/0.1@user/testing: Downloading" in client.out
 
-        client.save({"global.conf": f"core.download:download_cache={tmp_folder}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core.download:download_cache={tmp_folder}"})
 
         client.run("remove * -c")
         client.run("install --requires=mypkg/0.1@user/testing")
@@ -59,8 +57,7 @@ class TestDownloadCache:
         # https://github.com/conan-io/conan/issues/8578
         client = TestClient(default_server_user=True)
         tmp_folder = temp_folder()
-        client.save({"global.conf": f"core.download:download_cache={tmp_folder}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core.download:download_cache={tmp_folder}"})
 
         client.save({"conanfile.py": GenConanfile().with_package_file("file.txt", "content")})
         client.run("create . --name=pkg --version=0.1")
@@ -93,8 +90,7 @@ class TestDownloadCache:
         save(os.path.join(file_server.store, "myfile3.txt"), "some content 3")
 
         tmp_folder = temp_folder()
-        client.save({"global.conf": f"core.sources:download_cache={tmp_folder}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core.sources:download_cache={tmp_folder}"})
         # badchecksums are not cached
         conanfile = textwrap.dedent("""
            from conan import ConanFile
@@ -157,7 +153,6 @@ class TestDownloadCache:
         c.run("remove * -c")
 
         # enable cache
-        c.save({"global.conf": f"core.download:download_cache=mytmp_folder"},
-               path=c.cache.cache_folder)
+        c.save_home({"global.conf": f"core.download:download_cache=mytmp_folder"})
         c.run("install --requires=mypkg/0.1@user/testing", assert_error=True)
         assert 'core.download:download_cache must be an absolute path' in c.out
diff --git a/conans/test/integration/cache/storage_path_test.py b/conans/test/integration/cache/storage_path_test.py
index 2aef6a8fe..832b131ad 100644
--- a/conans/test/integration/cache/storage_path_test.py
+++ b/conans/test/integration/cache/storage_path_test.py
@@ -8,8 +8,7 @@ def test_storage_path():
     client = TestClient()
     client.save({"conanfile.py": GenConanfile()})
     tmp_folder = temp_folder(path_with_spaces=True)
-    client.save({"global.conf": f"core.cache:storage_path={tmp_folder}"},
-                path=client.cache.cache_folder)
+    client.save_home({"global.conf": f"core.cache:storage_path={tmp_folder}"})
     client.run("create . --name=mypkg --version=0.1")
     assert f"mypkg/0.1: Package folder {tmp_folder}" in client.out
     assert os.path.isfile(os.path.join(tmp_folder, "cache.sqlite3"))
diff --git a/conans/test/integration/command/config_test.py b/conans/test/integration/command/config_test.py
index f35d1ea1d..820a3e7be 100644
--- a/conans/test/integration/command/config_test.py
+++ b/conans/test/integration/command/config_test.py
@@ -24,7 +24,7 @@ class TestConfigHome:
     def test_config_home_default(self):
         client = TestClient()
         client.run("config home")
-        assert f"{client.cache.cache_folder}\n" == client.stdout
+        assert f"{client.cache_folder}\n" == client.stdout
 
         client.run("config home --format=text", assert_error=True)
         # It is not possible to use --format=text explicitly
diff --git a/conans/test/integration/command/download/download_parallel_test.py b/conans/test/integration/command/download/download_parallel_test.py
index 81e912651..5317e73f6 100644
--- a/conans/test/integration/command/download/download_parallel_test.py
+++ b/conans/test/integration/command/download/download_parallel_test.py
@@ -6,8 +6,7 @@ def test_basic_parallel_download():
     threads = 2
     packages = 2
     per_package = 4
-    client.save({"global.conf": f"core.download:parallel={threads}"},
-                path=client.cache.cache_folder)
+    client.save_home({"global.conf": f"core.download:parallel={threads}"})
     client.save({"conanfile.py": GenConanfile().with_option("myoption", '["ANY"]')})
 
     package_ids = []
diff --git a/conans/test/integration/command/export/export_test.py b/conans/test/integration/command/export/export_test.py
index 4bcdf7dee..45b59432a 100644
--- a/conans/test/integration/command/export/export_test.py
+++ b/conans/test/integration/command/export/export_test.py
@@ -421,7 +421,7 @@ def test_allow_temp_uppercase():
     c.save({"conanfile.py": GenConanfile()})
     c.run("export . --name=Pkg --version=0.1", assert_error=True)
     assert "ERROR: Conan packages names 'Pkg/0.1' must be all lowercase" in c.out
-    c.save({"global.conf": "core:allow_uppercase_pkg_names=True"}, path=c.cache.cache_folder)
+    c.save_home({"global.conf": "core:allow_uppercase_pkg_names=True"})
     c.run("export . --name=Pkg --version=0.1")
     assert "WARN: Package name 'Pkg/0.1' has uppercase, " \
            "and has been allowed by temporary config." in c.out
diff --git a/conans/test/integration/command/export_pkg_test.py b/conans/test/integration/command/export_pkg_test.py
index af0d6be38..3c52b662e 100644
--- a/conans/test/integration/command/export_pkg_test.py
+++ b/conans/test/integration/command/export_pkg_test.py
@@ -638,3 +638,34 @@ def test_remote_none_tool_requires():
     c.run(f"export-pkg pkg {settings} -s:b compiler.cppstd=17")  # This used to crash
     # No longer crash
     assert "pkg/0.1 (test package): Running test()" in c.out
+
+
+def test_export_pkg_set_version_python_requires():
+    # https://github.com/conan-io/conan/issues/16223
+    c = TestClient(light=True)
+    py_require = textwrap.dedent("""
+        from conan import ConanFile
+
+        class TestBuild:
+            def set_version(self):
+                assert self.version
+
+        class TestModule(ConanFile):
+            name = "pyreq"
+            version = "0.1"
+            package_type = "python-require"
+    """)
+    pkg = textwrap.dedent("""
+        from conan import ConanFile
+
+        class TestPkgConan(ConanFile):
+            name="testpkg"
+            python_requires = "pyreq/0.1"
+            python_requires_extend = "pyreq.TestBuild"
+        """)
+    c.save({"pyreq/conanfile.py": py_require,
+            "pkg/conanfile.py": pkg})
+
+    c.run("create pyreq")
+    c.run("export-pkg pkg --version=1.0+0")
+    assert "conanfile.py (testpkg/1.0+0): Exported package binary" in c.out
diff --git a/conans/test/integration/command/install/install_parallel_test.py b/conans/test/integration/command/install/install_parallel_test.py
index d8307d784..a6f60ae4a 100644
--- a/conans/test/integration/command/install/install_parallel_test.py
+++ b/conans/test/integration/command/install/install_parallel_test.py
@@ -10,8 +10,7 @@ class InstallParallelTest(unittest.TestCase):
         threads = 4
         counter = 8
 
-        client.save({"global.conf": f"core.download:parallel={threads}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core.download:parallel={threads}"})
         client.save({"conanfile.py": GenConanfile()})
 
         for i in range(counter):
diff --git a/conans/test/integration/command/runner_test.py b/conans/test/integration/command/runner_test.py
index 5341d7309..f809236bd 100644
--- a/conans/test/integration/command/runner_test.py
+++ b/conans/test/integration/command/runner_test.py
@@ -141,7 +141,8 @@ def test_create_docker_runner_dockerfile_file_path():
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
     client.run("create . -pr:h host -pr:b build")
-    print(client.out)
+
+    assert "Container conan-runner-docker running" in client.out
     assert "Restore: pkg/0.2" in client.out
     assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
     assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
@@ -249,7 +250,7 @@ def test_create_docker_runner_profile_abs_path():
     cache=copy
     remove=True
     """)
-    
+
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
     client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
@@ -272,6 +273,8 @@ def test_create_docker_runner_profile_abs_path_from_configfile():
         build:
             dockerfile: {dockerfile_path("Dockerfile_test")}
             build_context: {conan_base_path()}
+        run:
+            name: my-custom-conan-runner-container
         """)
     client.save({"configfile.yaml": configfile})
 
@@ -301,11 +304,12 @@ def test_create_docker_runner_profile_abs_path_from_configfile():
     cache=copy
     remove=True
     """)
-    
+
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
     client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
 
+    assert "Container my-custom-conan-runner-container running" in client.out
     assert "Restore: pkg/0.2" in client.out
     assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
     assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
@@ -357,11 +361,11 @@ def test_create_docker_runner_profile_abs_path_from_configfile_with_args():
     cache=copy
     remove=True
     """)
-    
+
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
     client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
-    print(client.out)
+
     assert "test/integration/command/dockerfiles/Dockerfile_args" in client.out
     assert "Restore: pkg/0.2" in client.out
     assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
@@ -434,4 +438,4 @@ def test_create_docker_runner_default_build_profile_error():
     client.save({"host_clean": profile_host})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
     with pytest.raises(Exception, match="ERROR: The default build profile '/root/.conan2/profiles/default' doesn't exist.") as exception:
-        client.run("create . -pr:h host_clean")
\ No newline at end of file
+        client.run("create . -pr:h host_clean")
diff --git a/conans/test/integration/command/source_test.py b/conans/test/integration/command/source_test.py
index 57644154e..1cc684d24 100644
--- a/conans/test/integration/command/source_test.py
+++ b/conans/test/integration/command/source_test.py
@@ -35,7 +35,7 @@ class TestexportConan(ConanFile):
         python = os.path.join(self.recipe_folder, "mypython.py")
         self.output.info("PYTHON: %s" % load(self, python))
 """
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({"conanfile.py": conanfile,
                      "patch.patch": "mypatch",
                      "mypython.py": "mypython"})
@@ -53,7 +53,7 @@ class TestexportConan(ConanFile):
         # https://github.com/conan-io/conan/issues/2327
         # Test if a patch can be applied in source() both in create
         # and local flow
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = """from conan import ConanFile
 from conan.tools.files import load
 import os
@@ -78,13 +78,13 @@ class Pkg(ConanFile):
 class ConanLib(ConanFile):
     pass
 '''
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({CONANFILE: conanfile})
         client.run("source .")
         self.assertNotIn("This package defines both 'os' and 'os_build'", client.out)
 
     def test_source_with_path_errors(self):
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({"conanfile.txt": "contents"}, clean_first=True)
 
         # Path with conanfile.txt
@@ -107,7 +107,7 @@ class ConanLib(ConanFile):
         self.output.info("Running source!")
         self.output.info("cwd=>%s" % os.getcwd())
 '''
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({CONANFILE: conanfile})
 
         client.run("install .")
@@ -128,7 +128,7 @@ class ConanLib(ConanFile):
         save("file1.txt", "Hello World")
 '''
         # First, failing source()
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({CONANFILE: conanfile})
 
         client.run("source .", assert_error=True)
@@ -229,7 +229,7 @@ class ConanLib(ConanFile):
                     assert False
             ''')
 
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({CONANFILE: conanfile})
 
         client.run("create . --name=lib --version=1.0", assert_error=True)
@@ -294,3 +294,18 @@ def test_source_python_requires():
     c.run("source . ")
     assert "pytool/0.1: Not found in local cache, looking in remotes" in c.out
     assert "pytool/0.1: Downloaded recipe" in c.out
+
+
+@pytest.mark.parametrize("attribute", ["info", "settings", "options"])
+def test_source_method_forbidden_attributes(attribute):
+    conanfile = textwrap.dedent(f"""
+    from conan import ConanFile
+    class Package(ConanFile):
+        def source(self):
+            self.output.info(self.{attribute})
+    """)
+    client = TestClient(light=True)
+    client.save({"conanfile.py": conanfile})
+
+    client.run("source .", assert_error=True)
+    assert f"'self.{attribute}' access in 'source()' method is forbidden" in client.out
diff --git a/conans/test/integration/command/test_profile.py b/conans/test/integration/command/test_profile.py
index db8e6d7b7..8de40adbb 100644
--- a/conans/test/integration/command/test_profile.py
+++ b/conans/test/integration/command/test_profile.py
@@ -43,7 +43,7 @@ def test_shorthand_syntax():
     tc.run(
         "profile show -o:a=both_options=True -pr:a=profile -s:a=os=WindowsCE -s:a=os.platform=conan -c:a=user.conf:cli=True -f=json")
 
-    out = json.loads(tc.out)
+    out = json.loads(tc.stdout)
     assert out == {'build': {'build_env': '',
                              'conf': {'user.conf:cli': True, 'user:profile': True},
                              'options': {'both_options': 'True'},
@@ -93,7 +93,7 @@ def test_shorthand_syntax():
                             'tool_requires': {}}}
 
     tc.run("profile show -pr:a=pre -pr:h=post -f=json")
-    out = json.loads(tc.out)
+    out = json.loads(tc.stdout)
     assert out == {'build': {'build_env': '',
                              'conf': {},
                              'options': {},
@@ -112,7 +112,7 @@ def test_shorthand_syntax():
                             'tool_requires': {}}}
 
     tc.run("profile show -pr:a=pre -o:b foo=False -o:a foo=True -o:h foo=False -f=json")
-    out = json.loads(tc.out)
+    out = json.loads(tc.stdout)
     assert out == {'build': {'build_env': '',
                              'conf': {},
                              'options': {'foo': 'True'},
diff --git a/conans/test/integration/command/upload/test_upload_parallel.py b/conans/test/integration/command/upload/test_upload_parallel.py
index c51d1e2af..6ce6b31fe 100644
--- a/conans/test/integration/command/upload/test_upload_parallel.py
+++ b/conans/test/integration/command/upload/test_upload_parallel.py
@@ -17,8 +17,7 @@ def test_upload_parallel_error():
                 return super(FailOnReferencesUploader, self).put(*args, **kwargs)
 
     client = TestClient(requester_class=FailOnReferencesUploader, default_server_user=True)
-    client.save({"global.conf": f"core.upload:parallel=2\ncore.upload:retry_wait=0"},
-                path=client.cache.cache_folder)
+    client.save_home({"global.conf": f"core.upload:parallel=2\ncore.upload:retry_wait=0"})
     client.save({"conanfile.py": GenConanfile()})
     client.run('remote login default admin -p password')
     for index in range(4):
@@ -32,7 +31,7 @@ def test_upload_parallel_success():
     """Upload 2 packages in parallel with success"""
 
     client = TestClient(default_server_user=True)
-    client.save({"global.conf": f"core.upload:parallel=2"}, path=client.cache.cache_folder)
+    client.save_home({"global.conf": f"core.upload:parallel=2"})
     client.save({"conanfile.py": GenConanfile()})
     client.run('create . --name=lib0 --version=1.0 --user=user --channel=channel')
     client.run('create . --name=lib1 --version=1.0 --user=user --channel=channel')
@@ -49,8 +48,7 @@ def test_upload_parallel_success():
 def test_upload_parallel_fail_on_interaction():
     """Upload 2 packages in parallel and fail because non_interactive forced"""
     client = TestClient(default_server_user=True)
-    client.save({"global.conf": f"core.upload:parallel=2\ncore:non_interactive=True"},
-                path=client.cache.cache_folder)
+    client.save_home({"global.conf": f"core.upload:parallel=2\ncore:non_interactive=True"})
     client.save({"conanfile.py": GenConanfile()})
     num_references = 2
     for index in range(num_references):
diff --git a/conans/test/integration/command/upload/upload_complete_test.py b/conans/test/integration/command/upload/upload_complete_test.py
index a29368815..84ade0d1e 100644
--- a/conans/test/integration/command/upload/upload_complete_test.py
+++ b/conans/test/integration/command/upload/upload_complete_test.py
@@ -175,7 +175,7 @@ class UploadTest(unittest.TestCase):
         if retry_wait is not None:
             lines.append("core.upload:retry_wait={}".format(retry_wait))
 
-        client.save({"global.conf": "\n".join(lines)}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": "\n".join(lines)})
 
     def test_upload_error_with_config(self):
         """Cause an error in the transfer and see some message"""
diff --git a/conans/test/integration/command/upload/upload_test.py b/conans/test/integration/command/upload/upload_test.py
index eda0c0695..b9287a296 100644
--- a/conans/test/integration/command/upload/upload_test.py
+++ b/conans/test/integration/command/upload/upload_test.py
@@ -334,7 +334,7 @@ class UploadTest(unittest.TestCase):
         client = TestClient(default_server_user=True)
         client.save(files)
         conan_conf = "core:non_interactive=True"
-        client.save({"global.conf": conan_conf}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": conan_conf})
 
         client.run("create . --user=user --channel=testing")
         client.run("remote logout '*'")
@@ -351,7 +351,7 @@ class UploadTest(unittest.TestCase):
         client = TestClient(default_server_user=True)
         client.save(files)
         conan_conf = "core:non_interactive=True"
-        client.save({"global.conf": conan_conf}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": conan_conf})
         client.run("create . --user=user --channel=testing")
         client.run("remote logout '*'")
         client.run("remote set-user default lasote")
@@ -367,7 +367,7 @@ class UploadTest(unittest.TestCase):
         client = TestClient(default_server_user=True)
         client.save({"conanfile.py": GenConanfile("hello0", "1.2.1")})
         conan_conf = "core:non_interactive=True"
-        client.save({"global.conf": conan_conf}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": conan_conf})
         client.run("create . --user=user --channel=testing")
         client.run("remote logout '*'")
         client.run("remote login default admin -p password")
diff --git a/conans/test/integration/command/user_test.py b/conans/test/integration/command/user_test.py
index 8e6fd7443..b81b517bd 100644
--- a/conans/test/integration/command/user_test.py
+++ b/conans/test/integration/command/user_test.py
@@ -5,6 +5,7 @@ import unittest
 from collections import OrderedDict
 from datetime import timedelta
 
+from conans.client.store.localdb import LocalDB
 from conans.test.utils.tools import TestClient, TestServer
 from conans.util.env import environment_update
 
@@ -55,7 +56,7 @@ class UserTest(unittest.TestCase):
         client.run('remote set-user default john')
         self.assertIn("Changed user of remote 'default' from 'None' (anonymous) to 'john'",
                       client.out)
-        localdb = client.cache.localdb
+        localdb = LocalDB(client.cache_folder)
         self.assertEqual(('john', None, None), localdb.get_login(test_server.fake_url))
 
         client.run('remote set-user default will')
@@ -86,7 +87,7 @@ class UserTest(unittest.TestCase):
         client.run('remote logout default')
         self.assertIn("Changed user of remote 'default' from 'admin' (authenticated) "
                       "to 'None' (anonymous)", client.out)
-        localdb = client.cache.localdb
+        localdb = LocalDB(client.cache_folder)
         self.assertEqual((None, None, None), localdb.get_login(test_server.fake_url))
         client.run('remote list-users')
         assert 'default:\n  No user' in client.out
@@ -150,7 +151,7 @@ class ConanLib(ConanFile):
         servers = {"default": test_server}
         client = TestClient(servers=servers,  inputs=[])
         conan_conf = "core:non_interactive=True"
-        client.save({"global.conf": conan_conf}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": conan_conf})
         client.run('remote login default admin -p', assert_error=True)
         self.assertIn('ERROR: Conan interactive mode disabled', client.out)
         self.assertNotIn("Please enter a password for \"admin\" account:", client.out)
@@ -335,10 +336,11 @@ def test_user_removed_remote_removed():
     c = TestClient(default_server_user=True)
     server_url = c.servers["default"].fake_url
     c.run("remote login default admin -p password")
-    login = c.cache.localdb.get_login(server_url)
+    localdb = LocalDB(c.cache_folder)
+    login = localdb.get_login(server_url)
     assert login[0] == "admin"
     c.run("remote remove default")
-    login = c.cache.localdb.get_login(server_url)
+    login = localdb.get_login(server_url)
     assert login == (None, None, None)
 
 
diff --git a/conans/test/integration/command_v2/test_cache_save_restore.py b/conans/test/integration/command_v2/test_cache_save_restore.py
index c5e7c5b91..53c8dda3a 100644
--- a/conans/test/integration/command_v2/test_cache_save_restore.py
+++ b/conans/test/integration/command_v2/test_cache_save_restore.py
@@ -3,7 +3,10 @@ import os
 import shutil
 import tarfile
 
+import pytest
+
 from conans.test.assets.genconanfile import GenConanfile
+from conans.test.utils.test_files import temp_folder
 from conans.test.utils.tools import TestClient
 from conans.util.files import save, load
 
@@ -218,3 +221,25 @@ def test_error_restore_not_existing():
     c = TestClient()
     c.run("cache restore potato.tgz", assert_error=True)
     assert "ERROR: Restore archive doesn't exist in " in c.out
+
+
+@pytest.mark.parametrize("src_store", (False, True))
+@pytest.mark.parametrize("dst_store", (False, True))
+def test_cache_save_restore_custom_storage_path(src_store, dst_store):
+    c = TestClient()
+    if src_store:
+        tmp_folder = temp_folder()
+        c.save_home({"global.conf": f"core.cache:storage_path={tmp_folder}"})
+    c.save({"conanfile.py": GenConanfile()})
+    c.run("create . --name=pkg --version=1.0")
+    c.run("cache save *:*")
+    cache_path = os.path.join(c.current_folder, "conan_cache_save.tgz")
+
+    c2 = TestClient()
+    if dst_store:
+        tmp_folder = temp_folder()
+        c2.save_home({"global.conf": f"core.cache:storage_path={tmp_folder}"})
+    shutil.copy2(cache_path, c2.current_folder)
+    c2.run("cache restore conan_cache_save.tgz")
+    c2.run("list *:*")
+    assert "pkg/1.0" in c2.out
diff --git a/conans/test/integration/command_v2/test_combined_pkglist_flows.py b/conans/test/integration/command_v2/test_combined_pkglist_flows.py
index fbd88317d..862400655 100644
--- a/conans/test/integration/command_v2/test_combined_pkglist_flows.py
+++ b/conans/test/integration/command_v2/test_combined_pkglist_flows.py
@@ -13,7 +13,7 @@ class TestListUpload:
 
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
@@ -54,7 +54,7 @@ class TestListUpload:
 
 class TestGraphCreatedUpload:
     def test_create_upload(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -69,7 +69,7 @@ class TestGraphCreatedUpload:
 
 class TestExportUpload:
     def test_export_upload(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0")})
         c.run("export zlib --format=pkglist", redirect_stdout="pkglist.json")
         c.run("upload --list=pkglist.json -r=default -c")
@@ -77,29 +77,34 @@ class TestExportUpload:
 
 
 class TestCreateGraphToPkgList:
+    def test_graph_pkg_nonexistant(self):
+        c = TestClient(light=True)
+        c.run("list --graph=non-existent-file.json", assert_error=True)
+        assert "ERROR: Graph file not found" in c.out
+
     def test_graph_pkg_list_only_built(self):
-        c = TestClient()
+        c = TestClient(light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")
                                                               .with_settings("os")
                                                               .with_shared_option(False)})
         c.run("create zlib")
-        c.run("create app --format=json -s os=Windows", redirect_stdout="graph.json")
+        c.run("create app --format=json -s os=Linux", redirect_stdout="graph.json")
         c.run("list --graph=graph.json --graph-binaries=build --format=json")
         pkglist = json.loads(c.stdout)["Local Cache"]
         assert len(pkglist) == 1
         pkgs = pkglist["app/1.0"]["revisions"]["8263c3c32802e14a2f03a0b1fcce0d95"]["packages"]
         assert len(pkgs) == 1
-        pkg_app = pkgs["e0bcc80c3f095670b71e535c193114d0155426cb"]
+        pkg_app = pkgs["d8b3bdd894c3eb9bf2a3119ee0f8c70843ace0ac"]
         assert pkg_app["info"]["requires"] == ["zlib/1.0.Z"]
-        assert pkg_app["info"]["settings"] == {'os': 'Windows'}
+        assert pkg_app["info"]["settings"] == {'os': 'Linux'}
         assert pkg_app["info"]["options"] == {'shared': 'False'}
 
     def test_graph_pkg_list_all_recipes_only(self):
         """
         --graph-recipes=* selects all the recipes in the graph
         """
-        c = TestClient()
+        c = TestClient(light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -114,7 +119,7 @@ class TestCreateGraphToPkgList:
         """
         include python_requires too
         """
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"pytool/conanfile.py": GenConanfile("pytool", "0.1"),
                 "zlib/conanfile.py": GenConanfile("zlib", "1.0").with_python_requires("pytool/0.1"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
@@ -135,7 +140,7 @@ class TestCreateGraphToPkgList:
         """
         include python_requires too
         """
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"conanfile.py": GenConanfile("pytool", "0.1").with_package_type("python-require")})
         c.run("create . --format=json", redirect_stdout="graph.json")
         c.run("list --graph=graph.json --format=json")
@@ -146,7 +151,7 @@ class TestCreateGraphToPkgList:
 
 class TestGraphInfoToPkgList:
     def test_graph_pkg_list_only_built(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -258,7 +263,7 @@ class TestPkgListMerge:
 class TestDownloadUpload:
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
@@ -315,7 +320,7 @@ class TestDownloadUpload:
 class TestListRemove:
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
diff --git a/conans/test/integration/configuration/client_certs_test.py b/conans/test/integration/configuration/client_certs_test.py
index b97201001..60fe4b576 100644
--- a/conans/test/integration/configuration/client_certs_test.py
+++ b/conans/test/integration/configuration/client_certs_test.py
@@ -48,7 +48,7 @@ class ClientCertsTest(unittest.TestCase):
         conan_conf = textwrap.dedent("""
                                     core.net.http:client_cert= ("{}", "{}")
                                 """.format(mycert_path, mykey_path))
-        client.save({"global.conf": conan_conf}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": conan_conf})
         client.save({"conanfile.py": conanfile})
         client.run("create . --name=foo --version=1.0")
         assert "KWARGS cert: ('{}', '{}')".format(mycert_path, mykey_path) in client.out
diff --git a/conans/test/integration/configuration/required_version_test.py b/conans/test/integration/configuration/required_version_test.py
index 4be140429..46e09fbaf 100644
--- a/conans/test/integration/configuration/required_version_test.py
+++ b/conans/test/integration/configuration/required_version_test.py
@@ -15,8 +15,7 @@ class RequiredVersionTest(unittest.TestCase):
     def test_wrong_version(self):
         required_version = "1.23.0"
         client = TestClient()
-        client.save({"global.conf": f"core:required_conan_version={required_version}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core:required_conan_version={required_version}"})
         client.run("help", assert_error=True)
         self.assertIn("Current Conan version (1.26.0) does not satisfy the defined "
                       "one ({})".format(required_version), client.out)
@@ -25,24 +24,21 @@ class RequiredVersionTest(unittest.TestCase):
     def test_exact_version(self):
         required_version = "1.22.0"
         client = TestClient()
-        client.save({"global.conf": f"core:required_conan_version={required_version}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core:required_conan_version={required_version}"})
         client.run("--help")
 
     @mock.patch("conans.client.conf.required_version.client_version", "2.1.0")
     def test_lesser_version(self):
         required_version = "<3.0"
         client = TestClient()
-        client.save({"global.conf": f"core:required_conan_version={required_version}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core:required_conan_version={required_version}"})
         client.run("--help")
 
     @mock.patch("conans.client.conf.required_version.client_version", "1.0.0")
     def test_greater_version(self):
         required_version = ">0.1.0"
         client = TestClient()
-        client.save({"global.conf": f"core:required_conan_version={required_version}"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": f"core:required_conan_version={required_version}"})
         client.run("--help")
 
     def test_bad_format(self):
diff --git a/conans/test/integration/extensions/test_plugin_cmd_wrapper.py b/conans/test/integration/extensions/test_plugin_cmd_wrapper.py
index ad72efbd2..5becbc1c1 100644
--- a/conans/test/integration/extensions/test_plugin_cmd_wrapper.py
+++ b/conans/test/integration/extensions/test_plugin_cmd_wrapper.py
@@ -8,7 +8,7 @@ from conans.util.files import save
 
 def test_plugin_cmd_wrapper():
     c = TestClient()
-    plugins = os.path.join(c.cache.cache_folder, "extensions", "plugins")
+    plugins = os.path.join(c.cache_folder, "extensions", "plugins")
     wrapper = textwrap.dedent("""
         def cmd_wrapper(cmd, **kwargs):
             return 'echo "{}"'.format(cmd)
@@ -32,7 +32,7 @@ def test_plugin_cmd_wrapper_conanfile():
     we can get the name of the caller conanfile too
     """
     c = TestClient()
-    plugins = os.path.join(c.cache.cache_folder, "extensions", "plugins")
+    plugins = os.path.join(c.cache_folder, "extensions", "plugins")
     wrapper = textwrap.dedent("""
         def cmd_wrapper(cmd, conanfile, **kwargs):
             return 'echo "{}!:{}!"'.format(conanfile.ref, cmd)
diff --git a/conans/test/integration/graph/conflict_diamond_test.py b/conans/test/integration/graph/conflict_diamond_test.py
index 1dbb0d5f7..6bd01301f 100644
--- a/conans/test/integration/graph/conflict_diamond_test.py
+++ b/conans/test/integration/graph/conflict_diamond_test.py
@@ -54,7 +54,7 @@ class TestConflictDiamondTest:
             c.save({"game/conanfile.py": _game_conanfile(v)})
             c.run("install game")
             c.assert_overrides({"math/1.0": [f"math/{v}"],
-                                "math/1.0.1": [f"math/{v}#8e1a7a5ce869d8c54ae3d33468fd657c"]})
+                                "math/1.0.1": [f"math/{v}"]})
             c.assert_listed_require({f"math/{v}": "Cache"})
 
         # Check that order of requirements doesn't affect
@@ -62,7 +62,7 @@ class TestConflictDiamondTest:
             c.save({"game/conanfile.py": _game_conanfile(v, reverse=True)})
             c.run("install game")
             c.assert_overrides({"math/1.0": [f"math/{v}"],
-                                "math/1.0.1": [f"math/{v}#8e1a7a5ce869d8c54ae3d33468fd657c"]})
+                                "math/1.0.1": [f"math/{v}"]})
             c.assert_listed_require({f"math/{v}": "Cache"})
 
         c.run("install --requires=engine/1.0  --requires=ai/1.0", assert_error=True)
diff --git a/conans/test/integration/graph/core/graph_manager_base.py b/conans/test/integration/graph/core/graph_manager_base.py
index 1889aacb2..a22e3245f 100644
--- a/conans/test/integration/graph/core/graph_manager_base.py
+++ b/conans/test/integration/graph/core/graph_manager_base.py
@@ -5,8 +5,8 @@ import unittest
 import yaml
 
 from conan.api.conan_api import ConanAPI
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.conf import default_settings_yml
 from conans.model.conf import ConfDefinition
 from conans.model.manifest import FileTreeManifest
@@ -24,7 +24,7 @@ class GraphManagerTest(unittest.TestCase):
 
     def setUp(self):
         cache_folder = temp_folder()
-        cache = ClientCache(cache_folder, ConfDefinition())
+        cache = PkgCache(cache_folder, ConfDefinition())
         home = HomePaths(cache_folder)
         save(os.path.join(home.profiles_path, "default"), "")
         save(home.settings_path, "os: [Windows, Linux]")
diff --git a/conans/test/integration/graph/test_repackaging.py b/conans/test/integration/graph/test_repackaging.py
index a057d740c..97386dbcc 100644
--- a/conans/test/integration/graph/test_repackaging.py
+++ b/conans/test/integration/graph/test_repackaging.py
@@ -37,3 +37,115 @@ def test_repackage():
     client.run("install .")
     assert re.search(r"Skipped binaries(\s*)liba/1.0, libb/1.0", client.out)
     assert "repackager/1.0: Already installed!" in client.out
+
+
+def test_repackage_library_self():
+    c = TestClient()
+    c.save({"conanfile.py": GenConanfile("liba", "1.0").with_package_file("a.txt", "A1.0!")})
+    c.run("create .")
+
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.files import copy
+        class Pkg(ConanFile):
+            name = "liba"
+            version = "2.0"
+
+            def requirements(self):
+                self.requires("liba/1.0", visible=False)
+
+            def package(self):
+                for _, dep in self.dependencies.items():
+                    copy(self, "*", src=dep.package_folder, dst=self.package_folder)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+
+    c.run("install --requires=liba/2.0 --deployer=full_deploy")
+    assert re.search(r"Skipped binaries(\s*)liba/1.0", c.out)
+    assert "liba/2.0: Already installed!" in c.out
+    assert c.load("full_deploy/host/liba/2.0/a.txt") == "A1.0!"
+
+
+def test_repackage_library_self_infinite_loop():
+    c = TestClient()
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            name = "liba"
+            version = "1.0"
+
+            def requirements(self):
+                self.requires("liba/1.0", visible=False, headers=False, libs=False, run=False)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .", assert_error=True)
+    assert "There is a cycle/loop in the graph" in c.out
+
+
+def test_repackage_library_self_multiple():
+    c = TestClient()
+    c.save({"1/conanfile.py": GenConanfile("liba", "1.0").with_package_file("a1.txt", "A1.0!"),
+            "2/conanfile.py": GenConanfile("liba", "2.0").with_package_file("a2.txt", "A2.0!")})
+    c.run("create 1")
+    c.run("create 2")
+
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.files import copy
+        class Pkg(ConanFile):
+            name = "liba"
+            version = "3.0"
+
+            def requirements(self):
+                # To avoid conflict among liba versions
+                self.requires("liba/1.0", headers=False, libs=False, visible=False)
+                self.requires("liba/2.0", visible=False)
+
+            def package(self):
+                for _, dep in self.dependencies.items():
+                    copy(self, "*", src=dep.package_folder, dst=self.package_folder)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+
+    c.run("install --requires=liba/3.0 --deployer=full_deploy")
+    assert re.search(r"Skipped binaries(\s*)liba/1.0, liba/2.0", c.out)
+    assert "liba/3.0: Already installed!" in c.out
+    assert c.load("full_deploy/host/liba/3.0/a1.txt") == "A1.0!"
+    assert c.load("full_deploy/host/liba/3.0/a2.txt") == "A2.0!"
+
+
+def test_repackage_library_self_transitive():
+    c = TestClient()
+    c.save({"a/conanfile.py": GenConanfile("liba", "1.0").with_package_file("a1.txt", "A1.0!"),
+            "b/conanfile.py": GenConanfile("libb", "1.0").with_requires("liba/1.0")})
+    c.run("create a")
+    c.run("create b")
+
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.files import copy
+        class Pkg(ConanFile):
+            name = "liba"
+            version = "3.0"
+
+            def requirements(self):
+                # libs=True, otherwise transitive liba is skipped
+                self.requires("libb/1.0", headers=False, libs=True, visible=False, run=False)
+
+            def package(self):
+                for _, dep in self.dependencies.items():
+                    copy(self, "*", src=dep.package_folder, dst=self.package_folder)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+
+    c.run("install --requires=liba/3.0 --deployer=full_deploy")
+    assert re.search(r"Skipped binaries(\s*)liba/1.0, libb/1.0", c.out)
+    assert "liba/3.0: Already installed!" in c.out
+    assert c.load("full_deploy/host/liba/3.0/a1.txt") == "A1.0!"
diff --git a/conans/test/integration/graph/test_test_requires.py b/conans/test/integration/graph/test_test_requires.py
index 9347ab1ae..1f385f4ea 100644
--- a/conans/test/integration/graph/test_test_requires.py
+++ b/conans/test/integration/graph/test_test_requires.py
@@ -106,7 +106,7 @@ class TestTestRequiresDiamond:
         c.run("create rapidcheck")
         c.run("install game")
         c.assert_listed_require({"gtest/1.0": "Cache"}, test=True)
-        c.assert_overrides({"gtest/1.1": ["gtest/1.0#08dd14dd79315dd95c94b85d13bd1388"]})
+        c.assert_overrides({"gtest/1.1": ["gtest/1.0"]})
 
 
 def test_require_options():
diff --git a/conans/test/integration/graph/version_ranges/test_version_range_conf.py b/conans/test/integration/graph/version_ranges/test_version_range_conf.py
index 00980a681..8301e4db9 100644
--- a/conans/test/integration/graph/version_ranges/test_version_range_conf.py
+++ b/conans/test/integration/graph/version_ranges/test_version_range_conf.py
@@ -12,19 +12,19 @@ def test_version_range_conf_nonexplicit_expression():
     tc.save({"v1/conanfile.py": GenConanfile("pkg", "1.0").with_requires("base/[>1 <2]"),
              "v2/conanfile.py": GenConanfile("pkg", "2.0").with_requires("base/[>2 <3]")})
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=False"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=False"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2]: base/1.5.1" in tc.out
     tc.run("create v2/conanfile.py", assert_error=True)
     assert "Package 'base/[>2 <3]' not resolved" in tc.out
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=True"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=True"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2]: base/1.5.1" in tc.out
     tc.run("create v2/conanfile.py")
     assert "base/[>2 <3]: base/2.5.0-pre" in tc.out
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=None"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=None"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2]: base/1.5.1" in tc.out
 
@@ -42,19 +42,19 @@ def test_version_range_conf_explicit_expression():
     tc.save({"v1/conanfile.py": GenConanfile("pkg", "1.0").with_requires("base/[>1 <2, include_prerelease]"),
              "v2/conanfile.py": GenConanfile("pkg", "2.0").with_requires("base/[>2 <3, include_prerelease]")})
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=False"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=False"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
     tc.run("create v2/conanfile.py", assert_error=True)
     assert "Package 'base/[>2 <3, include_prerelease]' not resolved" in tc.out
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=True"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=True"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
     tc.run("create v2/conanfile.py")
     assert "base/[>2 <3, include_prerelease]: base/2.5.0-pre" in tc.out
 
-    tc.save({"global.conf": "core.version_ranges:resolve_prereleases=None"}, path=tc.cache.cache_folder)
+    tc.save_home({"global.conf": "core.version_ranges:resolve_prereleases=None"})
     tc.run("create v1/conanfile.py")
     assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
     tc.run("create v2/conanfile.py")
diff --git a/conans/test/integration/graph/version_ranges/version_range_override_test.py b/conans/test/integration/graph/version_ranges/version_range_override_test.py
index ba28f2a27..280abca7c 100644
--- a/conans/test/integration/graph/version_ranges/version_range_override_test.py
+++ b/conans/test/integration/graph/version_ranges/version_range_override_test.py
@@ -104,7 +104,7 @@ class TestVersionRangeOverrideFail:
                 "ros_core/pr-53@3rdparty/snapshot"
             ],
             "ros_core/1.1.4@3rdparty/unstable": [
-                "ros_core/pr-53@3rdparty/snapshot#4d670581ccb765839f2239cc8dff8fbd"
+                "ros_core/pr-53@3rdparty/snapshot"
             ]
         }
         assert info['graph']["overrides"] == expected_overrides
diff --git a/conans/test/integration/lockfile/test_ci_overrides.py b/conans/test/integration/lockfile/test_ci_overrides.py
new file mode 100644
index 000000000..e587988df
--- /dev/null
+++ b/conans/test/integration/lockfile/test_ci_overrides.py
@@ -0,0 +1,389 @@
+import json
+
+import pytest
+
+from conans.model.recipe_ref import RecipeReference
+from conans.test.assets.genconanfile import GenConanfile
+from conans.test.utils.tools import TestClient
+
+
+def test_graph_build_order_override_error():
+    """
+    libc -> libb -> liba -> zlib/1.2
+              |--------------/
+      |-----override------> zlib/1.3
+    """
+    c = TestClient()
+    c.save({"zlib/conanfile.py": GenConanfile("zlib"),
+            "liba/conanfile.py": GenConanfile("liba", "0.1").with_requires("zlib/1.0"),
+            "libb/conanfile.py": GenConanfile("libb", "0.1").with_requires("liba/0.1", "zlib/2.0"),
+            "libc/conanfile.py": GenConanfile("libc", "0.1").with_requirement("libb/0.1")
+                                                            .with_requirement("zlib/3.0",
+                                                                              override=True)
+            })
+    c.run("export zlib --version=2.0")
+    c.run("export zlib --version=3.0")
+    c.run("export liba")
+    c.run("export libb")
+    c.run("export libc")
+    c.run("graph info --requires=libc/0.1 --lockfile-out=output.lock")
+
+    c.run("graph build-order --requires=libc/0.1 --lockfile=output.lock --order-by=configuration "
+          "--build=missing --format=json")
+
+    to_build = json.loads(c.stdout)
+    for level in to_build["order"]:
+        for package in level:
+            binary = package["binary"]
+            if binary != "Build":
+                continue
+            build_args = package["build_args"]
+            c.run(f"install {build_args} --lockfile=output.lock")
+            ref = RecipeReference.loads(package["ref"])
+            assert f"{ref}: Building from source"
+
+    c.run("install --requires=libc/0.1 --lockfile=output.lock")
+    # All works, all binaries exist now
+    assert "zlib/3.0: Already installed!" in c.out
+    assert "liba/0.1: Already installed!" in c.out
+    assert "libb/0.1: Already installed!" in c.out
+    assert "libc/0.1: Already installed!" in c.out
+
+
+@pytest.mark.parametrize("replace_pattern", ["*", "3.0"])
+def test_graph_build_order_override_replace_requires(replace_pattern):
+    """
+    libc -> libb -> liba -> zlib/1.2
+              |--------------/
+      |-----override------> zlib/1.3
+
+    replace_requires zlib -> zlib/system
+    """
+    c = TestClient()
+    c.save({"zlib/conanfile.py": GenConanfile("zlib"),
+            "liba/conanfile.py": GenConanfile("liba", "0.1").with_requires("zlib/1.0"),
+            "libb/conanfile.py": GenConanfile("libb", "0.1").with_requires("liba/0.1", "zlib/2.0"),
+            "libc/conanfile.py": GenConanfile("libc", "0.1").with_requirement("libb/0.1")
+                                                            .with_requirement("zlib/3.0",
+                                                                              override=True),
+            "profile": f"[replace_requires]\nzlib/{replace_pattern}: zlib/system"
+            })
+    c.run("export zlib --version=2.0")
+    c.run("export zlib --version=3.0")
+    c.run("export zlib --version=system")
+    c.run("export liba")
+    c.run("export libb")
+    c.run("export libc")
+    c.run("lock create --requires=libc/0.1 --lockfile-out=output.lock -pr=profile")
+
+    c.run("graph build-order --requires=libc/0.1 --lockfile=output.lock --order-by=configuration "
+          "--build=missing -pr=profile --format=json")
+
+    to_build = json.loads(c.stdout)
+    for level in to_build["order"]:
+        for package in level:
+            binary = package["binary"]
+            if binary != "Build":
+                continue
+            build_args = package["build_args"]
+            c.run(f"install {build_args} --lockfile=output.lock -pr=profile")
+            ref = RecipeReference.loads(package["ref"])
+            assert f"{ref}: Building from source"
+
+    c.run("install --requires=libc/0.1 --lockfile=output.lock -pr=profile")
+    # All works, all binaries exist now
+    assert "zlib/system: Already installed!" in c.out
+    assert "liba/0.1: Already installed!" in c.out
+    assert "libb/0.1: Already installed!" in c.out
+    assert "libc/0.1: Already installed!" in c.out
+
+
+def test_single_config_decentralized_overrides():
+    r""" same scenario as "test_single_config_centralized()", but distributing the build in
+    different build servers, using the "build-order"
+    Now with overrides
+
+    pkga -> toola/1.0 -> toolb/1.0 -> toolc/1.0
+                \------override-----> toolc/2.0
+    pkgb -> toola/2.0 -> toolb/1.0 -> toolc/1.0
+                \------override-----> toolc/3.0
+    pkgc -> toola/3.0 -> toolb/1.0 -> toolc/1.0
+    """
+    c = TestClient()
+    c.save({"toolc/conanfile.py": GenConanfile("toolc"),
+            "toolb/conanfile.py": GenConanfile("toolb").with_requires("toolc/1.0"),
+            "toola/conanfile.py": GenConanfile("toola", "1.0").with_requirement("toolb/1.0")
+                                                              .with_requirement("toolc/2.0",
+                                                                                override=True),
+            "toola2/conanfile.py": GenConanfile("toola", "2.0").with_requirement("toolb/1.0")
+                                                               .with_requirement("toolc/3.0",
+                                                                                 override=True),
+            "toola3/conanfile.py": GenConanfile("toola", "3.0").with_requirement("toolb/1.0"),
+            "pkga/conanfile.py": GenConanfile("pkga", "1.0").with_tool_requires("toola/1.0"),
+            "pkgb/conanfile.py": GenConanfile("pkgb", "1.0").with_requires("pkga/1.0")
+                                                            .with_tool_requires("toola/2.0"),
+            "pkgc/conanfile.py": GenConanfile("pkgc", "1.0").with_requires("pkgb/1.0")
+                                                            .with_tool_requires("toola/3.0"),
+            })
+    c.run("export toolc --version=1.0")
+    c.run("export toolc --version=2.0")
+    c.run("export toolc --version=3.0")
+
+    c.run("export toolb --version=1.0")
+
+    c.run("export toola")
+    c.run("export toola2")
+    c.run("export toola3")
+
+    c.run("export pkga")
+    c.run("export pkgb")
+    c.run("lock create pkgc")
+    lock = json.loads(c.load("pkgc/conan.lock"))
+    requires = "\n".join(lock["build_requires"])
+    assert "toolc/3.0" in requires
+    assert "toolc/2.0" in requires
+    assert "toolc/1.0" in requires
+    assert len(lock["overrides"]) == 1
+    assert set(lock["overrides"]["toolc/1.0"]) == {"toolc/3.0", "toolc/2.0", None}
+
+    c.run("graph build-order pkgc --lockfile=pkgc/conan.lock --format=json --build=missing")
+    to_build = json.loads(c.stdout)
+    for level in to_build:
+        for elem in level:
+            for package in elem["packages"][0]:  # assumes no dependencies between packages
+                binary = package["binary"]
+                if binary != "Build":
+                    continue
+                build_args = package["build_args"]
+                c.run(f"install {build_args} --lockfile=pkgc/conan.lock")
+
+    c.run("install pkgc --lockfile=pkgc/conan.lock")
+    # All works, all binaries exist now
+    assert "pkga/1.0: Already installed!" in c.out
+    assert "pkgb/1.0: Already installed!" in c.out
+
+
+def test_single_config_decentralized_overrides_nested():
+    r""" same scenario as "test_single_config_centralized()", but distributing the build in
+    different build servers, using the "build-order"
+    Now with overrides
+
+    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+               \                          \-----------override---------> libf/2.0
+                \--------------------override--------------------------> libf/3.0
+    """
+    c = TestClient()
+    c.save({"libf/conanfile.py": GenConanfile("libf"),
+            "libe/conanfile.py": GenConanfile("libe", "1.0").with_requires("libf/1.0"),
+            "libd/conanfile.py": GenConanfile("libd", "1.0").with_requires("libe/1.0"),
+            "libc/conanfile.py": GenConanfile("libc", "1.0").with_requirement("libd/1.0")
+                                                            .with_requirement("libf/2.0",
+                                                                              override=True),
+            "libb/conanfile.py": GenConanfile("libb", "1.0").with_requires("libc/1.0"),
+            "toola/conanfile.py": GenConanfile("toola", "1.0").with_requirement("libb/1.0")
+                                                              .with_requirement("libf/3.0",
+                                                                                override=True),
+            "pkga/conanfile.py": GenConanfile("pkga", "1.0").with_tool_requires("toola/1.0"),
+            })
+
+    c.run("export libf --version=3.0")
+    c.run("export libe")
+    c.run("export libd")
+    c.run("export libc")
+    c.run("export libb")
+    c.run("export toola")
+
+    c.run("lock create pkga")
+    lock = json.loads(c.load("pkga/conan.lock"))
+    assert lock["overrides"] == {"libf/1.0": ["libf/3.0"],
+                                 "libf/2.0": ["libf/3.0"]}
+
+    c.run("graph build-order pkga --lockfile=pkga/conan.lock --format=json --build=missing")
+    to_build = json.loads(c.stdout)
+    for level in to_build:
+        for elem in level:
+            ref = elem["ref"]
+            if "libc" in ref:
+                pass
+            for package in elem["packages"][0]:  # assumes no dependencies between packages
+                binary = package["binary"]
+                if binary != "Build":
+                    continue
+                build_args = package["build_args"]
+                c.run(f"install {build_args} --lockfile=pkga/conan.lock")
+
+    c.run("install pkga --lockfile=pkga/conan.lock")
+    # All works, all binaries exist now
+    assert "Install finished successfully" in c.out
+
+
+@pytest.mark.parametrize("forced", [False, True])
+def test_single_config_decentralized_overrides_multi(forced):
+    r""" same scenario as "test_single_config_centralized()", but distributing the build in
+    different build servers, using the "build-order"
+    Now with overrides
+
+    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+      |         \                          \-----------override--------> libf/2.0
+      |          \--------------------override-------------------------> libf/3.0
+    pkgb -> toola/1.1 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+      |         \                          \-----------override--------> libf/2.0
+      |          \--------------------override-------------------------> libf/4.0
+    pkgc -> toola/1.2 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+                                           \-----------override--------> libf/2.0
+    """
+    override, force = (True, False) if not forced else (False, True)
+    c = TestClient()
+    c.save({"libf/conanfile.py": GenConanfile("libf"),
+            "libe/conanfile.py": GenConanfile("libe", "1.0").with_requires("libf/1.0"),
+            "libd/conanfile.py": GenConanfile("libd", "1.0").with_requires("libe/1.0"),
+            "libc/conanfile.py": GenConanfile("libc", "1.0").with_requirement("libd/1.0")
+                                                            .with_requirement("libf/2.0",
+                                                                              override=override,
+                                                                              force=force),
+            "libb/conanfile.py": GenConanfile("libb", "1.0").with_requires("libc/1.0"),
+            "toola/conanfile.py": GenConanfile("toola", "1.0").with_requirement("libb/1.0")
+                                                              .with_requirement("libf/3.0",
+                                                                                override=override,
+                                                                                force=force),
+            "toola1/conanfile.py": GenConanfile("toola", "1.1").with_requirement("libb/1.0")
+                                                               .with_requirement("libf/4.0",
+                                                                                 override=override,
+                                                                                 force=force),
+            "toola2/conanfile.py": GenConanfile("toola", "1.2").with_requirement("libb/1.0"),
+            "pkga/conanfile.py": GenConanfile("pkga", "1.0").with_tool_requires("toola/1.0"),
+            "pkgb/conanfile.py": GenConanfile("pkgb", "1.0").with_requires("pkga/1.0")
+                                                            .with_tool_requires("toola/1.1"),
+            "pkgc/conanfile.py": GenConanfile("pkgc", "1.0").with_requires("pkgb/1.0")
+                                                            .with_tool_requires("toola/1.2"),
+            })
+
+    c.run("export libf --version=2.0")
+    c.run("export libf --version=3.0")
+    c.run("export libf --version=4.0")
+    c.run("export libe")
+    c.run("export libd")
+    c.run("export libc")
+    c.run("export libb")
+
+    c.run("export toola")
+    c.run("export toola1")
+    c.run("export toola2")
+
+    c.run("export pkga")
+    c.run("export pkgb")
+    c.run("lock create pkgc")
+    lock = json.loads(c.load("pkgc/conan.lock"))
+    assert len(lock["overrides"]) == 2
+    assert set(lock["overrides"]["libf/1.0"]) == {"libf/4.0", "libf/2.0", "libf/3.0"}
+
+    if forced:  # When forced, there is one libf/2.0 that is not overriden
+        assert set(lock["overrides"]["libf/2.0"]) == {"libf/4.0", "libf/3.0", None}
+    else:
+        assert set(lock["overrides"]["libf/2.0"]) == {"libf/4.0", "libf/3.0"}
+
+    c.run("graph build-order pkgc --lockfile=pkgc/conan.lock --format=json --build=missing")
+    to_build = json.loads(c.stdout)
+    for level in to_build:
+        for elem in level:
+            ref = elem["ref"]
+            if "libc" in ref:
+                pass
+            for package in elem["packages"][0]:  # assumes no dependencies between packages
+                binary = package["binary"]
+                if binary != "Build":
+                    continue
+                build_args = package["build_args"]
+                c.run(f"install {build_args} --lockfile=pkgc/conan.lock")
+
+    c.run("install pkgc --lockfile=pkgc/conan.lock")
+    # All works, all binaries exist now
+    assert "pkga/1.0: Already installed!" in c.out
+    assert "pkgb/1.0: Already installed!" in c.out
+
+
+@pytest.mark.parametrize("replace_pattern", ["*", "1.0", "2.0", "3.0", "4.0"])
+@pytest.mark.parametrize("forced", [False, True])
+def test_single_config_decentralized_overrides_multi_replace_requires(replace_pattern, forced):
+    r""" same scenario as "test_single_config_centralized()", but distributing the build in
+    different build servers, using the "build-order"
+    Now with overrides
+
+    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+      |         \                          \-----------override--------> libf/2.0
+      |          \--------------------override-------------------------> libf/3.0
+    pkgb -> toola/1.1 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+      |         \                          \-----------override--------> libf/2.0
+      |          \--------------------override-------------------------> libf/4.0
+    pkgc -> toola/1.2 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0
+                                           \-----------override--------> libf/2.0
+    """
+    override, force = (True, False) if not forced else (False, True)
+    c = TestClient()
+    c.save({"libf/conanfile.py": GenConanfile("libf"),
+            "libe/conanfile.py": GenConanfile("libe", "1.0").with_requires("libf/1.0"),
+            "libd/conanfile.py": GenConanfile("libd", "1.0").with_requires("libe/1.0"),
+            "libc/conanfile.py": GenConanfile("libc", "1.0").with_requirement("libd/1.0")
+                                                            .with_requirement("libf/2.0",
+                                                                              override=override,
+                                                                              force=force),
+            "libb/conanfile.py": GenConanfile("libb", "1.0").with_requires("libc/1.0"),
+            "toola/conanfile.py": GenConanfile("toola", "1.0").with_requirement("libb/1.0")
+                                                              .with_requirement("libf/3.0",
+                                                                                override=override,
+                                                                                force=force),
+            "toola1/conanfile.py": GenConanfile("toola", "1.1").with_requirement("libb/1.0")
+                                                               .with_requirement("libf/4.0",
+                                                                                 override=override,
+                                                                                 force=force),
+            "toola2/conanfile.py": GenConanfile("toola", "1.2").with_requirement("libb/1.0"),
+            "pkga/conanfile.py": GenConanfile("pkga", "1.0").with_tool_requires("toola/1.0"),
+            "pkgb/conanfile.py": GenConanfile("pkgb", "1.0").with_requires("pkga/1.0")
+                                                            .with_tool_requires("toola/1.1"),
+            "pkgc/conanfile.py": GenConanfile("pkgc", "1.0").with_requires("pkgb/1.0")
+                                                            .with_tool_requires("toola/1.2"),
+            "profile": f"include(default)\n[replace_requires]\nlibf/{replace_pattern}: libf/system"
+            })
+
+    c.run("export libf --version=2.0")
+    c.run("export libf --version=3.0")
+    c.run("export libf --version=4.0")
+    c.run("export libf --version=system")
+    c.run("export libe")
+    c.run("export libd")
+    c.run("export libc")
+    c.run("export libb")
+
+    c.run("export toola")
+    c.run("export toola1")
+    c.run("export toola2")
+
+    c.run("export pkga")
+    c.run("export pkgb")
+    c.run("lock create pkgc -pr:b=profile")
+
+    # overrides will be different everytime, just checking that things can be built
+    c.run("graph build-order pkgc --lockfile=pkgc/conan.lock --format=json -pr:b=profile "
+          "--build=missing")
+
+    to_build = json.loads(c.stdout)
+    for level in to_build:
+        for elem in level:
+            ref = elem["ref"]
+            if "libc" in ref:
+                pass
+            for package in elem["packages"][0]:  # assumes no dependencies between packages
+                binary = package["binary"]
+                if binary != "Build":
+                    continue
+                build_args = package["build_args"]
+                c.run(f"install {build_args} --lockfile=pkgc/conan.lock -pr:b=profile")
+
+    c.run("install pkgc --lockfile=pkgc/conan.lock -pr:b=profile")
+    # All works, all binaries exist now
+    assert "pkga/1.0: Already installed!" in c.out
+    assert "pkgb/1.0: Already installed!" in c.out
+    if replace_pattern == "1.0":  # These will overriden by downstream
+        assert "libf/system#7fb6d926dabeb955bcea1cafedf953c8 - Cache" not in c.out
+    else:
+        assert "libf/system#7fb6d926dabeb955bcea1cafedf953c8 - Cache" in c.out
diff --git a/conans/test/integration/lockfile/test_ci_revisions.py b/conans/test/integration/lockfile/test_ci_revisions.py
index b1e4632f0..5e5b2bf15 100644
--- a/conans/test/integration/lockfile/test_ci_revisions.py
+++ b/conans/test/integration/lockfile/test_ci_revisions.py
@@ -49,8 +49,7 @@ pkgapp_01_id = "dda63a9bddbbe704d4858d67156d5dad0361dc19"
 @pytest.fixture()
 def client_setup():
     c = TestClient()
-    c.save({"global.conf": "core.package_id:default_unknown_mode=recipe_revision_mode"},
-           path=c.cache.cache_folder)
+    c.save_home({"global.conf": "core.package_id:default_unknown_mode=recipe_revision_mode"})
     pkb_requirements = """
     def requirements(self):
         if self.settings.os == "Windows":
diff --git a/conans/test/integration/lockfile/test_graph_overrides.py b/conans/test/integration/lockfile/test_graph_overrides.py
index 6c64ecb1a..4c42a9c67 100644
--- a/conans/test/integration/lockfile/test_graph_overrides.py
+++ b/conans/test/integration/lockfile/test_graph_overrides.py
@@ -134,7 +134,7 @@ def test_overrides_diamond(override, force):
     overrides = json_graph['graph']["overrides"]
     assert len(overrides) == 2
     assert overrides['pkga/0.1'] == ['pkga/0.3']
-    assert overrides['pkga/0.2'] == ['pkga/0.3#e3afb975277bc245212d6e8de88f4f8f']
+    assert overrides['pkga/0.2'] == ['pkga/0.3']
 
     # apply the lockfile to pkgb, should it lock to pkga/0.3
     c.run("graph info pkgb --lockfile=pkgd/conan.lock --format=json")
diff --git a/conans/test/integration/lockfile/test_lock_requires_revisions.py b/conans/test/integration/lockfile/test_lock_requires_revisions.py
index e84680c08..1f6e16ab7 100644
--- a/conans/test/integration/lockfile/test_lock_requires_revisions.py
+++ b/conans/test/integration/lockfile/test_lock_requires_revisions.py
@@ -132,20 +132,20 @@ def test_conditional_os(requires):
     client.run("install consumer --lockfile=consumer.lock -s os=Windows -s:b os=Windows")
     assert "REV1!!!" in client.out
     assert "REV2!!!" not in client.out
-    assert "nix" not in client.out
+    assert "nix/0.1" not in client.out
     client.run("install consumer -s os=Windows -s:b os=Windows")
     assert "REV2!!!" in client.out
     assert "REV1!!!" not in client.out
-    assert "nix" not in client.out
+    assert "nix/0.1" not in client.out
 
     client.run("install consumer --lockfile=consumer.lock -s os=Linux -s:b os=Linux")
     assert "REV1!!!" in client.out
     assert "REV2!!!" not in client.out
-    assert "win" not in client.out
+    assert "win/0.1" not in client.out
     client.run("install consumer -s os=Linux -s:b os=Linux")
     assert "REV2!!!" in client.out
     assert "REV1!!!" not in client.out
-    assert "win" not in client.out
+    assert "win/0.1" not in client.out
 
 
 @pytest.mark.parametrize("requires", ["requires", "tool_requires"])
diff --git a/conans/test/integration/options/options_test.py b/conans/test/integration/options/options_test.py
index 65f4d77e7..fcc825765 100644
--- a/conans/test/integration/options/options_test.py
+++ b/conans/test/integration/options/options_test.py
@@ -23,6 +23,7 @@ class OptionsTest(unittest.TestCase):
         client.run("create . --name=pkg --version=0.1 --user=user --channel=testing -o *:shared=1")
         self.assertIn("pkg/0.1@user/testing: BUILD SHARED: 1", client.out)
         client.run("create . --name=pkg --version=0.1 --user=user --channel=testing -o shared=2")
+        assert 'legacy: Unscoped option definition is ambiguous' in client.out
         self.assertIn("pkg/0.1@user/testing: BUILD SHARED: 2", client.out)
         # With test_package
         client.save({"conanfile.py": conanfile,
diff --git a/conans/test/integration/package_id/compatible_test.py b/conans/test/integration/package_id/compatible_test.py
index 782fe7ca2..8e4e0a999 100644
--- a/conans/test/integration/package_id/compatible_test.py
+++ b/conans/test/integration/package_id/compatible_test.py
@@ -71,14 +71,17 @@ class CompatibleIDsTest(unittest.TestCase):
         client.run("export . --name=pkg --version=0.1 --user=user --channel=stable")
         self.assertIn("pkg/0.1@user/stable: Exported: "
                       "pkg/0.1@user/stable#d165eb4bcdd1c894a97d2a212956f5fe", client.out)
+        client.run("export . --name=lib --version=0.1 --user=user --channel=stable")
 
         # package can be used with a profile gcc 4.9 falling back to 4.8 binary
-        client.save({"conanfile.py": GenConanfile().with_require("pkg/0.1@user/stable")})
+        client.save({"conanfile.py": GenConanfile().with_requires("pkg/0.1@user/stable", "lib/0.1@user/stable")})
         # No fallback
-        client.run("install . -pr=myprofile --build=missing")
+        client.run("install . -pr=myprofile --build=missing -u=lib")
         self.assertIn("pkg/0.1@user/stable: PackageInfo!: Gcc version: 4.9!", client.out)
         client.assert_listed_binary({"pkg/0.1@user/stable":
                                      ("1ded27c9546219fbd04d4440e05b2298f8230047", "Build")})
+        assert "lib/0.1@user/stable: Compatible configurations not found in cache, checking servers" not in client.out
+        assert "pkg/0.1@user/stable: Compatible configurations not found in cache, checking servers" in client.out
 
     def test_compatible_setting_no_user_channel(self):
         client = TestClient()
diff --git a/conans/test/integration/package_id/test_cache_compatibles.py b/conans/test/integration/package_id/test_cache_compatibles.py
index f98dd7fe6..702b11e6d 100644
--- a/conans/test/integration/package_id/test_cache_compatibles.py
+++ b/conans/test/integration/package_id/test_cache_compatibles.py
@@ -377,6 +377,27 @@ class TestDefaultCompat:
         c.run("install --requires=app/0.1  --build=missing")
         assert re.search(r"Skipped binaries(\s*)tool/0.1", c.out)
 
+    def test_msvc_194_fallback(self):
+        c = TestClient()
+        save(c.cache.default_profile_path, "")
+        c.save({"conanfile.py": GenConanfile("mylib", "1.0").with_settings("os", "arch",
+                                                                           "compiler", "build_type"),
+                "profile_build": "[settings]\nos=Windows\narch=x86_64"})
+
+        c.run("create . -s os=Windows -s arch=x86_64 -s build_type=Release "
+              "-s compiler=msvc "
+              "-s compiler.version=193 -s compiler.cppstd=17 "
+              "-s compiler.runtime=dynamic -pr:b=profile_build")
+        package_id1 = c.created_package_id("mylib/1.0")
+
+        # Try to install with cppstd 14, it will find cppstd 17 as compatible
+        c.run("install --requires=mylib/1.0@ -s os=Windows -s arch=x86_64 -s build_type=Release "
+              "-s compiler=msvc "
+              "-s compiler.version=194 -s compiler.cppstd=14 "
+              "-s compiler.runtime=dynamic -pr:b=profile_build")
+        assert "mylib/1.0: Main binary package 'e340edd75790e7156c595edebd3d98b10a2e091e' missing."\
+               f"Using compatible package '{package_id1}'"
+
 
 class TestErrorsCompatibility:
     """ when the plugin fails, we want a clear message and a helpful trace
diff --git a/conans/test/integration/package_id/test_config_package_id.py b/conans/test/integration/package_id/test_config_package_id.py
index 9932497dd..1dfcb7953 100644
--- a/conans/test/integration/package_id/test_config_package_id.py
+++ b/conans/test/integration/package_id/test_config_package_id.py
@@ -34,7 +34,7 @@ def test_config_package_id(config_version, mode, result):
 
 def test_error_config_package_id():
     c = TestClient()
-    save(c.cache.global_conf_path, f"core.package_id:config_mode=minor_mode")
+    c.save_home({"global.conf": "core.package_id:config_mode=minor_mode"})
     c.save({"conanfile.py": GenConanfile("pkg", "0.1")})
     c.run("create .", assert_error=True)
     assert "ERROR: core.package_id:config_mode defined, " \
diff --git a/conans/test/integration/remote/auth_test.py b/conans/test/integration/remote/auth_test.py
index cba84dc9b..cd1b9df6a 100644
--- a/conans/test/integration/remote/auth_test.py
+++ b/conans/test/integration/remote/auth_test.py
@@ -5,6 +5,7 @@ import unittest
 
 from requests.models import Response
 
+from conans.client.store.localdb import LocalDB
 from conans.errors import AuthenticationException
 from conans.model.recipe_ref import RecipeReference
 from conans.paths import CONANFILE
@@ -206,7 +207,8 @@ def test_token_expired():
     c.save({"conanfile.py": GenConanfile()})
     c.run("create . --name=pkg --version=0.1 --user=user --channel=stable")
     c.run("upload * -r=default -c")
-    user, token, _ = c.cache.localdb.get_login(server.fake_url)
+    localdb = LocalDB(c.cache_folder)
+    user, token, _ = localdb.get_login(server.fake_url)
     assert user == "admin"
     assert token is not None
 
@@ -214,10 +216,10 @@ def test_token_expired():
     time.sleep(3)
     c.users = {}
     conan_conf = "core:non_interactive=True"
-    c.save({"global.conf": conan_conf}, path=c.cache.cache_folder)
+    c.save_home({"global.conf": conan_conf})
     c.run("remove * -c")
     c.run("install --requires=pkg/0.1@user/stable")
-    user, token, _ = c.cache.localdb.get_login(server.fake_url)
+    user, token, _ = localdb.get_login(server.fake_url)
     assert user == "admin"
     assert token is None
 
diff --git a/conans/test/integration/remote/broken_download_test.py b/conans/test/integration/remote/broken_download_test.py
index bd23e7f4b..65a8afdd9 100644
--- a/conans/test/integration/remote/broken_download_test.py
+++ b/conans/test/integration/remote/broken_download_test.py
@@ -118,7 +118,7 @@ def test_client_retries():
 
     client = TestClient(servers=servers, inputs=["admin", "password"],
                         requester_class=DownloadFilesBrokenRequesterTimesOne)
-    client.save({"global.conf": "core.download:retry_wait=1"}, path=client.cache.cache_folder)
+    client.save_home({"global.conf": "core.download:retry_wait=1"})
     client.run("install --requires=lib/1.0@lasote/stable")
     assert 1 == str(client.out).count("Waiting 1 seconds to retry...")
 
@@ -126,8 +126,8 @@ def test_client_retries():
         return DownloadFilesBrokenRequester(10, *args, **kwargs)
     client = TestClient(servers=servers, inputs=["admin", "password"],
                         requester_class=DownloadFilesBrokenRequesterTimesTen)
-    client.save({"global.conf": "core.download:retry_wait=0\n"
-                                "core.download:retry=11"}, path=client.cache.cache_folder)
+    client.save_home({"global.conf": "core.download:retry_wait=0\n"
+                                "core.download:retry=11"})
     client.run("install --requires=lib/1.0@lasote/stable")
     assert 10 == str(client.out).count("Waiting 0 seconds to retry...")
 
diff --git a/conans/test/integration/remote/requester_test.py b/conans/test/integration/remote/requester_test.py
index 5cc4eb8f3..fb16744ba 100644
--- a/conans/test/integration/remote/requester_test.py
+++ b/conans/test/integration/remote/requester_test.py
@@ -27,15 +27,14 @@ class TestRequester:
 
     def test_requester_timeout(self):
         client = TestClient(requester_class=MyRequester)
-        client.save({"global.conf": "core.net.http:timeout=4.3"}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": "core.net.http:timeout=4.3"})
         client.save({"conanfile.py": conanfile})
         client.run("create . --name=foo --version=1.0")
         assert "TIMEOUT: 4.3" in client.out
 
     def test_requester_timeout_tuple(self):
         client = TestClient(requester_class=MyRequester)
-        client.save({"global.conf": "core.net.http:timeout=(2, 3.4)"},
-                    path=client.cache.cache_folder)
+        client.save_home({"global.conf": "core.net.http:timeout=(2, 3.4)"})
         client.save({"conanfile.py": conanfile})
         client.run("create . --name=foo --version=1.0")
         assert "TIMEOUT: (2, 3.4)" in client.out
@@ -43,14 +42,14 @@ class TestRequester:
     def test_request_infinite_timeout(self):
         # Test that not having timeout works
         client = TestClient(requester_class=MyRequester)
-        client.save({"global.conf": "core.net.http:timeout=-1"}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": "core.net.http:timeout=-1"})
         client.save({"conanfile.py": conanfile})
         client.run("create . --name=foo --version=1.0")
         assert "TIMEOUT: NOT SPECIFIED" in client.out
 
     def test_unset_request_timeout_use_default_one(self):
         client = TestClient(requester_class=MyRequester)
-        client.save({"global.conf": "core.net.http:timeout=!"}, path=client.cache.cache_folder)
+        client.save_home({"global.conf": "core.net.http:timeout=!"})
         client.save({"conanfile.py": conanfile})
         client.run("create . --name=foo --version=1.0")
         assert "TIMEOUT: (30, 60)" in client.out
diff --git a/conans/test/integration/remote/rest_api_test.py b/conans/test/integration/remote/rest_api_test.py
index 94bdaf5e7..324a673e5 100644
--- a/conans/test/integration/remote/rest_api_test.py
+++ b/conans/test/integration/remote/rest_api_test.py
@@ -24,7 +24,6 @@ from conans.test.utils.tools import get_free_port
 from conans.util.files import md5, save
 
 
-@pytest.mark.slow
 @pytest.mark.rest_api
 class RestApiTest(unittest.TestCase):
     """Open a real server (sockets) to test rest_api function."""
@@ -46,15 +45,13 @@ class RestApiTest(unittest.TestCase):
                 client_factory = RestApiClientFactory(requester=requester,
                                                       config=config)
                 localdb = LocalDBMock()
-                cache = Mock()
-                cache.localdb = localdb
 
                 mocked_user_input = UserInput(non_interactive=False)
                 mocked_user_input.get_username = Mock(return_value="private_user")
                 mocked_user_input.get_password = Mock(return_value="private_pass")
 
                 # FIXME: Missing mock
-                cls.auth_manager = ConanApiAuthManager(client_factory, cache, config)
+                cls.auth_manager = ConanApiAuthManager(client_factory, temp_folder(), localdb, config)
                 cls.remote = Remote("myremote", "http://127.0.0.1:%s" % str(cls.server.port), True,
                                     True)
                 cls.auth_manager._authenticate(cls.remote, user="private_user",
diff --git a/conans/test/integration/remote/token_refresh_test.py b/conans/test/integration/remote/token_refresh_test.py
index 2d57d6b1c..7679d60b5 100644
--- a/conans/test/integration/remote/token_refresh_test.py
+++ b/conans/test/integration/remote/token_refresh_test.py
@@ -1,7 +1,6 @@
 import unittest
 
 import mock
-from mock import Mock
 
 from conan.api.model import Remote
 from conans.client.rest.auth_manager import ConanApiAuthManager
@@ -81,10 +80,7 @@ class TestTokenRefresh(unittest.TestCase):
         config = ConfDefinition()
         self.rest_client_factory = RestApiClientFactory(requester, config=config)
         self.localdb = LocalDBMock()
-        cache = Mock()
-        cache.localdb = self.localdb
-        cache.cache_folder = temp_folder()
-        self.auth_manager = ConanApiAuthManager(self.rest_client_factory, cache, config)
+        self.auth_manager = ConanApiAuthManager(self.rest_client_factory, temp_folder(), self.localdb, config)
         self.remote = Remote("myremote", "myurl", True, True)
         self.ref = RecipeReference.loads("lib/1.0@conan/stable#myreciperev")
 
diff --git a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
index f8a7eddf5..53dee8032 100644
--- a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
+++ b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
@@ -707,3 +707,38 @@ def test_cmakedeps_set_property_overrides():
     assert 'set(dep_NO_SONAME_MODE_RELEASE TRUE)' in dep
     other = c.load("app/other-release-data.cmake")
     assert 'set(other_other_mycomp1_NO_SONAME_MODE_RELEASE TRUE)' in other
+
+def test_cmakedeps_set_legacy_variable_name():
+    client = TestClient()
+    base_conanfile = str(GenConanfile("dep", "1.0"))
+    conanfile = base_conanfile + """
+    def package_info(self):
+        self.cpp_info.set_property("cmake_file_name", "CMakeFileName")
+    """
+    client.save({"dep/conanfile.py": conanfile})
+    client.run("create dep")
+    client.run("install --requires=dep/1.0 -g CMakeDeps")
+
+    # Check that all the CMake variables are generated with the file_name
+    dep_config = client.load("CMakeFileNameConfig.cmake")
+    cmake_variables = ["VERSION_STRING", "INCLUDE_DIRS", "INCLUDE_DIR", "LIBRARIES", "DEFINITIONS"]
+    for variable in cmake_variables:
+        assert f"CMakeFileName_{variable}" in dep_config
+
+    conanfile = base_conanfile + """
+    def package_info(self):
+        self.cpp_info.set_property("cmake_file_name", "NewCMakeFileName")
+        self.cpp_info.set_property("cmake_additional_variables_prefixes", ["PREFIX", "prefix", "PREFIX"])
+    """
+    client.save({"dep/conanfile.py": conanfile})
+    client.run("create dep")
+    client.run("install --requires=dep/1.0 -g CMakeDeps")
+
+    # Check that all the CMake variables are generated with the file_name and both prefixes
+    dep_config = client.load("NewCMakeFileNameConfig.cmake")
+    for variable in cmake_variables:
+        assert f"NewCMakeFileName_{variable}" in dep_config
+        assert f"PREFIX_{variable}" in dep_config
+        assert f"prefix_{variable}" in dep_config
+    # Check that variables are not duplicated
+    assert dep_config.count("PREFIX_VERSION") == 1
diff --git a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
index ebaf41649..25601b1df 100644
--- a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -1,6 +1,7 @@
 import json
 import os
 import platform
+import re
 import textwrap
 
 import pytest
@@ -352,6 +353,67 @@ def test_find_builddirs():
         assert "/path/to/builddir" in contents
 
 
+@pytest.fixture
+def lib_dir_setup():
+    client = TestClient()
+    client.save({"conanfile.py": GenConanfile().with_generator("CMakeToolchain")})
+    client.run("create . --name=onelib --version=1.0")
+    client.run("create . --name=twolib --version=1.0")
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+
+            class Conan(ConanFile):
+                requires = "onelib/1.0", "twolib/1.0"
+
+            """)
+    client.save({"conanfile.py": conanfile})
+    client.run("create . --name=dep --version=1.0")
+
+    conanfile = (GenConanfile().with_requires("dep/1.0").with_generator("CMakeToolchain")
+                 .with_settings("os", "arch", "compiler", "build_type"))
+
+    client.save({"conanfile.py": conanfile})
+    return client
+
+def test_runtime_lib_dirs_single_conf(lib_dir_setup):
+    client = lib_dir_setup
+    generator = ""
+    is_windows = platform.system() == "Windows"
+    if is_windows:
+        generator = '-c tools.cmake.cmaketoolchain:generator=Ninja'
+    
+    client.run(f'install . -s build_type=Release {generator}')
+    contents = client.load("conan_toolchain.cmake")
+    pattern_lib_path = r'list\(PREPEND CMAKE_LIBRARY_PATH (.*)\)'
+    pattern_lib_dirs = r'set\(CONAN_RUNTIME_LIB_DIRS (.*) \)'
+
+    # On *nix platforms: the list in `CMAKE_LIBRARY_PATH` 
+    # is the same as `CONAN_RUNTIME_LIB_DIRS`
+    # On windows, it's the same but with `bin` instead of `lib`
+    cmake_library_path = re.search(pattern_lib_path, contents).group(1)
+    conan_runtime_lib_dirs = re.search(pattern_lib_dirs, contents).group(1)
+    lib_path = cmake_library_path.replace("/p/lib", "/p/bin") if is_windows else cmake_library_path
+
+    assert lib_path == conan_runtime_lib_dirs
+
+
+def test_runtime_lib_dirs_multiconf(lib_dir_setup):
+    client = lib_dir_setup
+    generator = ""
+    if platform.system() != "Windows":
+        generator = '-c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config"'
+
+    client.run(f'install . -s build_type=Release {generator}')
+    client.run(f'install . -s build_type=Debug {generator}')
+
+    contents = client.load("conan_toolchain.cmake")
+    pattern_lib_dirs = r"set\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\)"
+    runtime_lib_dirs = re.search(pattern_lib_dirs, contents).group(1)
+
+    assert "<CONFIG:Release>" in runtime_lib_dirs
+    assert "<CONFIG:Debug>" in runtime_lib_dirs
+
+
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
 def test_cmaketoolchain_cmake_system_processor_cross_apple():
     """
@@ -1414,3 +1476,102 @@ def test_toolchain_and_compilers_build_context():
     })
     client.run("export tool")
     client.run("create consumer -pr:h host -pr:b build --build=missing")
+
+
+def test_toolchain_keep_absolute_paths():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.cmake import CMakeToolchain, cmake_layout
+        class Pkg(ConanFile):
+            settings = "build_type"
+            def generate(self):
+                tc = CMakeToolchain(self)
+                tc.absolute_paths = True
+                tc.generate()
+            def layout(self):
+                cmake_layout(self)
+        """)
+    c.save({"conanfile.py": conanfile,
+            "CMakeLists.txt": ""})
+    c.run('install . ')
+
+    user_presets = json.loads(c.load("CMakeUserPresets.json"))
+    assert os.path.isabs(user_presets["include"][0])
+    presets = json.loads(c.load(user_presets["include"][0]))
+    assert os.path.isabs(presets["configurePresets"][0]["toolchainFile"])
+
+
+def test_output_dirs_gnudirs_local_default():
+    # https://github.com/conan-io/conan/issues/14733
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.cmake import cmake_layout
+        from conan.tools.files import load
+
+        class Conan(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "arch", "compiler", "build_type"
+            generators = "CMakeToolchain"
+            def build(self):
+                tc = load(self, "conan_toolchain.cmake")
+                self.output.info(tc)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+
+    def _assert_install(out):
+        assert 'set(CMAKE_INSTALL_BINDIR "bin")' in out
+        assert 'set(CMAKE_INSTALL_SBINDIR "bin")' in out
+        assert 'set(CMAKE_INSTALL_LIBEXECDIR "bin")' in out
+        assert 'set(CMAKE_INSTALL_LIBDIR "lib")' in out
+        assert 'set(CMAKE_INSTALL_INCLUDEDIR "include")' in out
+
+    _assert_install(c.out)
+    assert "CMAKE_INSTALL_PREFIX" in c.out
+
+    c.run("build .")
+    _assert_install(c.out)
+    assert "CMAKE_INSTALL_PREFIX" not in c.out
+
+
+def test_output_dirs_gnudirs_local_custom():
+    # https://github.com/conan-io/conan/issues/14733
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.cmake import cmake_layout
+        from conan.tools.files import load
+
+        class Conan(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "arch", "compiler", "build_type"
+            generators = "CMakeToolchain"
+            def layout(self):
+                self.cpp.package.bindirs = ["mybindir"]
+                self.cpp.package.includedirs = ["myincludedir"]
+                self.cpp.package.libdirs = ["mylibdir"]
+
+            def build(self):
+                tc = load(self, "conan_toolchain.cmake")
+                self.output.info(tc)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+
+    def _assert_install(out):
+        assert 'set(CMAKE_INSTALL_BINDIR "mybindir")' in out
+        assert 'set(CMAKE_INSTALL_SBINDIR "mybindir")' in out
+        assert 'set(CMAKE_INSTALL_LIBEXECDIR "mybindir")' in out
+        assert 'set(CMAKE_INSTALL_LIBDIR "mylibdir")' in out
+        assert 'set(CMAKE_INSTALL_INCLUDEDIR "myincludedir")' in out
+
+    _assert_install(c.out)
+    assert "CMAKE_INSTALL_PREFIX" in c.out
+
+    c.run("build .")
+    _assert_install(c.out)
+    assert "CMAKE_INSTALL_PREFIX" not in c.out
diff --git a/conans/test/unittests/client/conf/config_installer/test_install_folder.py b/conans/test/unittests/client/conf/config_installer/test_install_folder.py
index 47a7fe319..77a8efdae 100644
--- a/conans/test/unittests/client/conf/config_installer/test_install_folder.py
+++ b/conans/test/unittests/client/conf/config_installer/test_install_folder.py
@@ -1,10 +1,8 @@
-# coding=utf-8
-
 import unittest
 import os
 
 from conans.client.conf.config_installer import tmp_config_install_folder
-from conans.test.utils.tools import TestClient
+from conans.test.utils.test_files import temp_folder
 
 
 class InstallFolderTests(unittest.TestCase):
@@ -15,11 +13,11 @@ class InstallFolderTests(unittest.TestCase):
         tmp_config_install_folder must create the same folder, but all items must be exclude when a
         new folder is created.
         """
-        client = TestClient()
+        cache_folder = temp_folder()
 
-        with tmp_config_install_folder(client.cache) as tmp_folder_first:
+        with tmp_config_install_folder(cache_folder) as tmp_folder_first:
             temp_file = os.path.join(tmp_folder_first, "foobar.txt")
             open(temp_file, "w+")
-            with tmp_config_install_folder(client.cache) as tmp_folder_second:
+            with tmp_config_install_folder(cache_folder) as tmp_folder_second:
                 self.assertEqual(tmp_folder_first, tmp_folder_second)
                 self.assertFalse(os.path.exists(temp_file))
diff --git a/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py b/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
index 1cd8ed1ba..360853968 100644
--- a/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
+++ b/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
@@ -5,8 +5,8 @@ import unittest
 import yaml
 from jinja2 import Template
 
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.conf import default_settings_yml
 from conans.client.profile_loader import ProfileLoader
 from conans.errors import ConanException
@@ -20,7 +20,7 @@ class SettingsCppStdTests(unittest.TestCase):
 
     def setUp(self):
         self.cache_folder = temp_folder()
-        self.cache = ClientCache(self.cache_folder, ConfDefinition())
+        self.cache = PkgCache(self.cache_folder, ConfDefinition())
         self.home_paths = HomePaths(self.cache_folder)
         save(self.home_paths.profile_plugin_path, "")
 
diff --git a/conans/test/unittests/model/version/test_version_range.py b/conans/test/unittests/model/version/test_version_range.py
index 7f82d625c..da684f08e 100644
--- a/conans/test/unittests/model/version/test_version_range.py
+++ b/conans/test/unittests/model/version/test_version_range.py
@@ -1,8 +1,11 @@
+import textwrap
+
 import pytest
 
 from conans.errors import ConanException
 from conans.model.version import Version
 from conans.model.version_range import VersionRange
+from conans.test.utils.tools import TestClient
 
 values = [
     ['=1.0.0',  [[['=', '1.0.0']]],                   ["1.0.0"],          ["0.1"]],
@@ -42,7 +45,7 @@ values = [
     ['>=1.0.0+2', [[['>=', '1.0.0+2']]], ["1.0.0+2", "1.0.0+3"], ["1.0.0+1"]],
     ['>=1.0.0', [[['>=', '1.0.0-']]], ["1.0.0+2", "1.0.0+3"], []],
     # Build metadata and pre-releases
-    ['>=1.0.0-pre.1+2', [[['>=', '1.0.0-pre.1+2']]], ["1.0.0+1", "1.0.0+2"], ["1.0.0-pre.1+3"]], # excluded 1+3 because is a pre-release!
+    ['>=1.0.0-pre.1+2', [[['>=', '1.0.0-pre.1+2']]], ["1.0.0+1", "1.0.0+2"], ["1.0.0-pre.1+3"]],  # excluded 1+3 because is a pre-release!
     ['>=1.0.0-pre.1+2, include_prerelease=True', [[['>=', '1.0.0-pre.1+2']]], ["1.0.0+1", "1.0.0+2", "1.0.0-pre.1+3"], ["1.0.0-pre.1+1"]],
     ['<1.0.1-pre.1+2', [[['<', '1.0.1-pre.1+2']]], ["1.0.0+1", "1.0.0+2"], ["1.0.0-pre.1+2"]],
     ['<1.0.1-pre.1+2, include_prerelease=True', [[['<', '1.0.1-pre.1+2']]], ["1.0.0+1", "1.0.0+2", "1.0.1-pre.1+1"], ["1.0.1-pre.1+2"]],
@@ -129,3 +132,19 @@ def test_wrong_range_option_syntax(version_range):
     but for now this test ensures we don't change it without realizing"""
     vr = VersionRange(version_range)
     assert all(cs.prerelease for cs in vr.condition_sets)
+
+
+def test_version_range_error_ux():
+    # https://github.com/conan-io/conan/issues/16288
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            requires = "mydep/[>1.0 < 3]"
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("install .", assert_error=True)
+    assert "Recipe 'conanfile' requires 'mydep/[>1.0 < 3]' version-range definition error" in c.out
+    c.run("export . --name=mypkg --version=0.1")
+    c.run("install --requires=mypkg/0.1", assert_error=True)
+    assert "Recipe 'mypkg/0.1' requires 'mydep/[>1.0 < 3]' version-range definition error" in c.out
diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
index b08dc13b7..8bba79509 100644
--- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -194,7 +194,7 @@ def test_osx_deployment_target(conanfile_apple):
 def conanfile_msvc():
     c = ConanFile(None)
     c.settings = Settings({"os": ["Windows"],
-                           "compiler": {"msvc": {"version": ["193"], "cppstd": ["20"],
+                           "compiler": {"msvc": {"version": ["193", "194"], "cppstd": ["20"],
                                                  "update": [None, 8, 9]}},
                            "build_type": ["Release"],
                            "arch": ["x86"]})
@@ -226,6 +226,14 @@ def test_toolset_update_version(conanfile_msvc):
     assert 'set(CMAKE_GENERATOR_TOOLSET "v143,version=14.38" CACHE STRING "" FORCE)' in toolchain.content
 
 
+def test_toolset_update_version_overflow(conanfile_msvc):
+    # https://github.com/conan-io/conan/issues/15583
+    conanfile_msvc.settings.compiler.version = "194"
+    conanfile_msvc.settings.compiler.update = "8"
+    toolchain = CMakeToolchain(conanfile_msvc)
+    assert 'set(CMAKE_GENERATOR_TOOLSET "v143,version=14.48" CACHE STRING "" FORCE)' in toolchain.content
+
+
 def test_toolset_x64(conanfile_msvc):
     # https://github.com/conan-io/conan/issues/11144
     conanfile_msvc.conf.define("tools.cmake.cmaketoolchain:toolset_arch", "x64")
diff --git a/conans/test/unittests/tools/microsoft/test_msvs_toolset.py b/conans/test/unittests/tools/microsoft/test_msvs_toolset.py
index b5f8b1a5d..14574127e 100644
--- a/conans/test/unittests/tools/microsoft/test_msvs_toolset.py
+++ b/conans/test/unittests/tools/microsoft/test_msvs_toolset.py
@@ -15,6 +15,7 @@ def test_invalid_compiler():
 
 
 @pytest.mark.parametrize("compiler_version,expected_toolset", [
+    ("194", "v143"),
     ("193", "v143"),
     ("192", "v142"),
     ("191", "v141"),
diff --git a/conans/test/utils/mocks.py b/conans/test/utils/mocks.py
index cb538224b..6c1a160ef 100644
--- a/conans/test/utils/mocks.py
+++ b/conans/test/utils/mocks.py
@@ -103,7 +103,7 @@ class ConanFileMock(ConanFile):
         self.win_bash = None
         self.command = None
         self._commands = []
-        self._conan_helpers = ConanFileHelpers(None, None, self.conf, None)
+        self._conan_helpers = ConanFileHelpers(None, None, self.conf, None, None)
 
     def run(self, *args, **kwargs):
         self.command = args[0]
diff --git a/conans/test/utils/tools.py b/conans/test/utils/tools.py
index f9d2efe9a..1ac1e4525 100644
--- a/conans/test/utils/tools.py
+++ b/conans/test/utils/tools.py
@@ -25,13 +25,12 @@ from requests.exceptions import HTTPError
 from webtest.app import TestApp
 
 from conan.cli.exit_codes import SUCCESS, ERROR_GENERAL
-from conan.internal.cache.cache import PackageLayout, RecipeLayout
+from conan.internal.cache.cache import PackageLayout, RecipeLayout, PkgCache
 from conan.internal.cache.home_paths import HomePaths
 from conans import REVISIONS
 from conan.api.conan_api import ConanAPI
 from conan.api.model import Remote
 from conan.cli.cli import Cli, _CONAN_INTERNAL_CUSTOM_COMMANDS_PATH
-from conans.client.cache.cache import ClientCache
 from conans.util.env import environment_update
 from conans.errors import NotFoundException, ConanException
 from conans.model.manifest import FileTreeManifest
@@ -442,18 +441,18 @@ class TestClient:
         api = ConanAPI(cache_folder=self.cache_folder)
         global_conf = api.config.global_conf
 
-        class MyCache(ClientCache, HomePaths):  # Temporary class to avoid breaking all tests
+        class MyCache(PkgCache, HomePaths):  # Temporary class to avoid breaking all tests
             def __init__(self, cache_folder):
-                ClientCache.__init__(self, cache_folder, global_conf)
+                PkgCache.__init__(self, cache_folder, global_conf)
                 HomePaths.__init__(self, cache_folder)
 
             @property
             def plugins_path(self):  # Temporary to not break tests
-                return os.path.join(self.cache_folder, "extensions", "plugins")
+                return os.path.join(self._home, "extensions", "plugins")
 
             @property
             def default_profile_path(self):
-                return os.path.join(self.cache_folder, "profiles", "default")
+                return os.path.join(self._home, "profiles", "default")
 
         return MyCache(self.cache_folder)