Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config clean command sketch #17514

Open
wants to merge 23 commits into
base: develop2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions conan/api/conan_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from conan.api.subapi.local import LocalAPI
from conan.api.subapi.lockfile import LockfileAPI
from conan.api.subapi.workspace import WorkspaceAPI
from conan import conan_version
from conan.api.subapi.config import ConfigAPI
from conan.api.subapi.download import DownloadAPI
from conan.api.subapi.export import ExportAPI
Expand All @@ -19,9 +18,9 @@
from conan.api.subapi.remove import RemoveAPI
from conan.api.subapi.search import SearchAPI
from conan.api.subapi.upload import UploadAPI
from conans.client.migrations import ClientMigrator
from conan.errors import ConanException
from conan.internal.paths import get_conan_user_home
from conans.client.migrations import ClientMigrator
from conan.internal.model.version_range import validate_conan_version


Expand All @@ -36,12 +35,11 @@ def __init__(self, cache_folder=None):
self.workspace = WorkspaceAPI(self)
self.cache_folder = self.workspace.home_folder() or cache_folder or get_conan_user_home()
self.home_folder = self.cache_folder # Lets call it home, deprecate "cache"
self.migrate()

# Migration system
migrator = ClientMigrator(self.cache_folder, conan_version)
migrator.migrate()

# This API is depended upon by the subsequent ones, it should be initialized first
self.config = ConfigAPI(self)

self.remotes = RemotesAPI(self)
self.command = CommandAPI(self)
# Search recipes by wildcard and packages filtering by configuration
Expand All @@ -60,6 +58,24 @@ def __init__(self, cache_folder=None):
self.lockfile = LockfileAPI(self)
self.local = LocalAPI(self)

required_range_new = self.config.global_conf.get("core:required_conan_version")
if required_range_new:
validate_conan_version(required_range_new)
_check_conan_version(self)

def reinit(self):
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
self.config.reinit()
self.remotes.reinit()
self.local.reinit()

_check_conan_version(self)

def migrate(self):
# Migration system
# TODO: A prettier refactoring of migrators would be nice
from conan import conan_version
migrator = ClientMigrator(self.cache_folder, conan_version)
migrator.migrate()


def _check_conan_version(conan_api):
required_range_new = conan_api.config.global_conf.get("core:required_conan_version")
if required_range_new:
validate_conan_version(required_range_new)
21 changes: 20 additions & 1 deletion conan/api/subapi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from conan.internal.model.pkg_type import PackageType
from conan.internal.model.recipe_ref import RecipeReference
from conan.internal.model.settings import Settings
from conans.util.files import load, save
from conans.util.files import load, save, rmdir, remove


class ConfigAPI:
Expand Down Expand Up @@ -191,3 +191,22 @@ def appending_recursive_dict_update(d, u):
appending_recursive_dict_update(settings, settings_user)

return Settings(settings)

def clean(self):
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
contents = os.listdir(self.home())
packages_folder = self.global_conf.get("core.cache:storage_path") or os.path.join(self.home(), "p")
for content in contents:
content_path = os.path.join(self.home(), content)
if content_path == packages_folder or content == "version.txt":
continue
ConanOutput().debug(f"Removing {content_path}")
if os.path.isdir(content_path):
rmdir(content_path)
else:
remove(content_path)
self.conan_api.reinit()
# CHECK: This also generates a remotes.json that is not there after a conan profile show?
self.conan_api.migrate()

def reinit(self):
self._new_config = None
3 changes: 3 additions & 0 deletions conan/api/subapi/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,6 @@ def inspect(self, conanfile_path, remotes, lockfile, name=None, version=None, us
conanfile = app.loader.load_named(conanfile_path, name=name, version=version, user=user,
channel=channel, remotes=remotes, graph_lock=lockfile)
return conanfile

def reinit(self):
self.editable_packages = EditablePackages(self._conan_api.home_folder)
3 changes: 3 additions & 0 deletions conan/api/subapi/remotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def __init__(self, conan_api):
# Wraps an http_requester to inject proxies, certs, etc
self._requester = ConanRequester(self.conan_api.config.global_conf, self.conan_api.cache_folder)

def reinit(self):
self._requester = ConanRequester(self.conan_api.config.global_conf, self.conan_api.cache_folder)
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved

def list(self, pattern=None, only_enabled=True):
"""
Obtain a list of ``Remote`` objects matching the pattern.
Expand Down
10 changes: 10 additions & 0 deletions conan/cli/commands/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.api.input import UserInput
from conan.api.model import Remote
from conan.api.output import cli_out_write
from conan.cli.command import conan_command, conan_subcommand, OnceArgument
Expand Down Expand Up @@ -132,3 +133,12 @@ def config_show(conan_api, parser, subparser, *args):
args = parser.parse_args(*args)

return conan_api.config.show(args.pattern)


@conan_subcommand()
def config_clean(conan_api, parser, subparser, *args):
"""
Clean the configuration files in the Conan home folder. (Keeping installed packages)
"""
parser.parse_args(*args)
conan_api.config.clean()
2 changes: 1 addition & 1 deletion conans/client/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import textwrap

from conan.api.output import ConanOutput
from conan.api.subapi.config import ConfigAPI
from conan.internal.default_settings import migrate_settings_file
from conans.migrations import Migrator
from conans.util.dates import timestamp_now
Expand Down Expand Up @@ -76,6 +75,7 @@ def migrate(home_folder):


def _migrate_pkg_db_lru(cache_folder, old_version):
from conan.api.subapi.config import ConfigAPI
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
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')
Expand Down
53 changes: 53 additions & 0 deletions test/integration/command/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import os
import textwrap

import pytest

from conan.api.conan_api import ConanAPI
from conan.test.assets.genconanfile import GenConanfile
from conan.internal.model.conf import BUILT_IN_CONFS
from conan.test.utils.test_files import temp_folder
from conan.test.utils.tools import TestClient
Expand Down Expand Up @@ -201,3 +204,53 @@ def test_config_show():
tc.run("config show zlib/*:foo")
assert "zlib/*:user.mycategory:foo" in tc.out
assert "zlib/*:user.myothercategory:foo" in tc.out


@pytest.mark.parametrize("storage_path", [None, "p", "../foo"])
def test_config_clean(storage_path):
tc = TestClient(light=True)
absolut_storage_path = os.path.abspath(os.path.join(tc.current_folder, storage_path)) if storage_path else os.path.join(tc.cache_folder, "p")

storage = f"core.cache:storage_path={storage_path}" if storage_path else ""
tc.save_home({"global.conf": f"core.upload:retry=7\n{storage}",
"extensions/compatibility/mycomp.py": "",
"extensions/commands/cmd_foo.py": "",
})

tc.run("profile detect --name=foo")
tc.run("remote add bar http://fakeurl")

tc.save({"conanfile.py": GenConanfile("pkg", "0.1")})
tc.run("create .")

assert os.path.exists(absolut_storage_path)

tc.run("config clean")
tc.run("profile list")
assert "foo" not in tc.out
tc.run("remote list")
assert "bar" not in tc.out
tc.run("config show core.upload:retry")
assert "7" not in tc.out
assert not os.path.exists(os.path.join(tc.cache_folder, "extensions"))
assert os.path.exists(absolut_storage_path)
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved


def test_config_reinit():
custom_global_conf = "core.upload:retry=7"
global_conf_folder = temp_folder()
with open(os.path.join(global_conf_folder, "global.conf"), "w") as f:
f.write(custom_global_conf)

cache_folder = temp_folder()
conan_api = ConanAPI(cache_folder=cache_folder)
# Ensure reinitialization does not invalidate references
config_api = conan_api.config
assert config_api.global_conf.get("core.upload:retry", check_type=int) != 7

conan_api.config.install(global_conf_folder, verify_ssl=False)
# No effect yet, we haven't reinitialized the API after the config installation
assert config_api.global_conf.get("core.upload:retry", check_type=int) != 7

conan_api.reinit()
assert config_api.global_conf.get("core.upload:retry", check_type=int) == 7
Loading