diff --git a/conan/api/subapi/config.py b/conan/api/subapi/config.py index f661c204ede..9c9d33960bb 100644 --- a/conan/api/subapi/config.py +++ b/conan/api/subapi/config.py @@ -46,32 +46,38 @@ def global_conf(self): to the profile ones and passed to the conanfiles.conf, which can be passed to collaborators """ if self._new_config is None: - self._new_config = ConfDefinition() cache_folder = self.conan_api.cache_folder - home_paths = HomePaths(cache_folder) - global_conf_path = home_paths.global_conf_path - if os.path.exists(global_conf_path): - text = load(global_conf_path) - distro = None - if platform.system() in ["Linux", "FreeBSD"]: - import distro - template = Environment(loader=FileSystemLoader(cache_folder)).from_string(text) - content = template.render({"platform": platform, "os": os, "distro": distro, - "conan_version": conan_version, - "conan_home_folder": cache_folder, - "detect_api": detect_api}) - self._new_config.loads(content) - else: # creation of a blank global.conf file for user convenience - default_global_conf = textwrap.dedent("""\ - # Core configuration (type 'conan config list' to list possible values) - # e.g, for CI systems, to raise if user input would block - # core:non_interactive = True - # some tools.xxx config also possible, though generally better in profiles - # tools.android:ndk_path = my/path/to/android/ndk - """) - save(global_conf_path, default_global_conf) + self._new_config = self.load_config(cache_folder) return self._new_config + @staticmethod + def load_config(home_folder): + # Do not document yet, keep it private + home_paths = HomePaths(home_folder) + global_conf_path = home_paths.global_conf_path + new_config = ConfDefinition() + if os.path.exists(global_conf_path): + text = load(global_conf_path) + distro = None + if platform.system() in ["Linux", "FreeBSD"]: + import distro + template = Environment(loader=FileSystemLoader(home_folder)).from_string(text) + content = template.render({"platform": platform, "os": os, "distro": distro, + "conan_version": conan_version, + "conan_home_folder": home_folder, + "detect_api": detect_api}) + new_config.loads(content) + else: # creation of a blank global.conf file for user convenience + default_global_conf = textwrap.dedent("""\ + # Core configuration (type 'conan config list' to list possible values) + # e.g, for CI systems, to raise if user input would block + # core:non_interactive = True + # some tools.xxx config also possible, though generally better in profiles + # tools.android:ndk_path = my/path/to/android/ndk + """) + save(global_conf_path, default_global_conf) + return new_config + @property def builtin_confs(self): return BUILT_IN_CONFS diff --git a/conans/client/migrations.py b/conans/client/migrations.py index f7ea7af9008..c7213bdfaec 100644 --- a/conans/client/migrations.py +++ b/conans/client/migrations.py @@ -3,6 +3,7 @@ import textwrap from conan.api.output import ConanOutput +from conan.api.subapi.config import ConfigAPI from conans.migrations import Migrator from conans.util.dates import timestamp_now from conans.util.files import load, save @@ -59,7 +60,9 @@ def _apply_migrations(self, old_version): def _migrate_pkg_db_lru(cache_folder, old_version): ConanOutput().warning(f"Upgrade cache from Conan version '{old_version}'") ConanOutput().warning("Running 2.0.14 Cache DB migration to add LRU column") - db_filename = os.path.join(cache_folder, 'p', 'cache.sqlite3') + config = ConfigAPI.load_config(cache_folder) + storage = config.get("core.cache:storage_path") or os.path.join(cache_folder, "p") + db_filename = os.path.join(storage, 'cache.sqlite3') connection = sqlite3.connect(db_filename, isolation_level=None, timeout=1, check_same_thread=False) try: @@ -73,10 +76,30 @@ def _migrate_pkg_db_lru(cache_folder, old_version): raise else: # generate the back-migration script undo_lru = textwrap.dedent("""\ - import os + import os, platform import sqlite3 - def migrate(cache_folder): - db = os.path.join(cache_folder, 'p', 'cache.sqlite3') + from jinja2 import Environment, FileSystemLoader + + from conan import conan_version + from conan.internal.api import detect_api + from conans.model.conf import ConfDefinition + + def migrate(home_folder): + config = os.path.join(home_folder, "global.conf") + global_conf = open(config, "r").read() if os.path.isfile(config) else "" + distro = None + if platform.system() in ["Linux", "FreeBSD"]: + import distro + template = Environment(loader=FileSystemLoader(home_folder)).from_string(global_conf) + content = template.render({"platform": platform, "os": os, "distro": distro, + "conan_version": conan_version, + "conan_home_folder": home_folder, + "detect_api": detect_api}) + conf = ConfDefinition() + conf.loads(content) + storage = conf.get("core.cache:storage_path") or os.path.join(home_folder, "p") + + db = os.path.join(storage, 'cache.sqlite3') connection = sqlite3.connect(db, isolation_level=None, timeout=1, check_same_thread=False) rec_cols = 'reference, rrev, path, timestamp' diff --git a/conans/test/integration/test_migrations.py b/conans/test/integration/test_migrations.py index 363b30ba0c1..efa75434e5d 100644 --- a/conans/test/integration/test_migrations.py +++ b/conans/test/integration/test_migrations.py @@ -5,12 +5,14 @@ import pytest from conan import conan_version +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 -def _drop_lru_column(cache_folder): - db = os.path.join(cache_folder, 'p', 'cache.sqlite3') +def _drop_lru_column(db_folder): + db = os.path.join(db_folder, "cache.sqlite3") connection = sqlite3.connect(db, isolation_level=None, timeout=1, check_same_thread=False) rec_cols = 'reference, rrev, path, timestamp' pkg_cols = 'reference, rrev, pkgid, prev, path, timestamp, build_id' @@ -39,7 +41,8 @@ def test_migration_profile_checker_plugin(plugin_path, string_replace, new_strin # Let's change the version version_txt_file_path = os.path.join(t.cache_folder, "version.txt") save(version_txt_file_path, "1.0.0") - _drop_lru_column(t.cache_folder) + db = os.path.join(t.cache_folder, 'p') + _drop_lru_column(db) # Do a modification to the profile plugin without changing the comment contents = contents.replace(string_replace, new_string) @@ -70,7 +73,8 @@ def test_migration_profile_checker_plugin(plugin_path, string_replace, new_strin # Let's change the version version_txt_file_path2 = os.path.join(t2.cache_folder, "version.txt") save(version_txt_file_path2, "1.0.0") - _drop_lru_column(t2.cache_folder) + db = os.path.join(t2.cache_folder, 'p') + _drop_lru_column(db) # Trigger the migrations t2.run("-v") assert "WARN: Running 2.0.14 Cache DB migration to add LRU column" in t2.out @@ -82,6 +86,24 @@ def test_migration_profile_checker_plugin(plugin_path, string_replace, new_strin assert new_string in contents +def test_migration_db_lru(): + t = TestClient() + storage = temp_folder() + save(t.cache.global_conf_path, f"core.cache:storage_path={storage}") + t.save({"conanfile.py": GenConanfile("pkg", "0.1")}) + t.run("create .") + # Any command generates the profile and compatibility plugin files + # Let's change the version + version_txt_file_path = os.path.join(t.cache_folder, "version.txt") + save(version_txt_file_path, "1.0.0") + _drop_lru_column(storage) + + # Trigger the migrations + t.run("list *") + assert "WARN: Running 2.0.14 Cache DB migration to add LRU column" in t.out + assert "pkg/0.1" in t.out + + def test_back_migrations(): t = TestClient()