diff --git a/conan/api/model.py b/conan/api/model.py index 5c6387d878f..14983fc1427 100644 --- a/conan/api/model.py +++ b/conan/api/model.py @@ -13,16 +13,12 @@ class Remote: def __init__(self, name, url, verify_ssl=True, disabled=False, allowed_packages=None): - self._name = name # Read only, is the key + self.name = name # Read only, is the key self.url = url self.verify_ssl = verify_ssl self.disabled = disabled self.allowed_packages = allowed_packages - @property - def name(self): - return self._name - def __eq__(self, other): if other is None: return False diff --git a/conan/api/subapi/remotes.py b/conan/api/subapi/remotes.py index d77cb9d252a..1360794ec27 100644 --- a/conan/api/subapi/remotes.py +++ b/conan/api/subapi/remotes.py @@ -1,102 +1,237 @@ import fnmatch +import json import os +from urllib.parse import urlparse +from conan.api.model import Remote +from conan.api.output import ConanOutput from conan.internal.cache.home_paths import HomePaths from conan.internal.conan_app import ConanApp -from conans.client.cache.remote_registry import Remote, RemoteRegistry -from conans.client.cmd.user import user_set, users_clean, users_list + from conans.errors import ConanException +from conans.util.files import save, load + +CONAN_CENTER_REMOTE_NAME = "conancenter" class RemotesAPI: + """ The ``RemotesAPI`` manages the definition of remotes, contained in the "remotes.json" file + in the Conan home, supporting addition, removal, update, rename, enable, disable of remotes. + These operations do not contact the servers or check their existence at all. If they are not + available, they will fail later when used. + + The ``user_xxx`` methods perform authentication related tasks, and some of them will contact + the servers to perform such authentication + """ def __init__(self, conan_api): + # This method is private, the subapi is not instantiated by users self.conan_api = conan_api self._remotes_file = HomePaths(self.conan_api.cache_folder).remotes_path def list(self, pattern=None, only_enabled=True): """ - :param pattern: if None, all remotes will be listed - it can be a single value or a list of values - :param only_enabled: - :return: + Obtain a list of ``Remote`` objects matching the pattern. + + :param pattern: ``None``, single ``str`` or list of ``str``. If it is ``None``, + all remotes will be returned (equivalent to ``pattern="*"``). + :param only_enabled: boolean, by default return only enabled remotes + :return: A list of ``Remote`` objects + """ - remotes = RemoteRegistry(self._remotes_file).list() + remotes = _load(self._remotes_file) if only_enabled: remotes = [r for r in remotes if not r.disabled] if pattern: - filtered_remotes = [] - patterns = [pattern] if isinstance(pattern, str) else pattern - for p in patterns: - is_match = False - for remote in remotes: - if fnmatch.fnmatch(remote.name, p): - is_match = True - if remote not in filtered_remotes: - filtered_remotes.append(remote) - if not is_match: - if "*" in p or "?" in p: - if only_enabled: - raise ConanException( - f"Remotes for pattern '{p}' can't be found or are disabled") - else: - raise ConanException(f"Remote '{p}' can't be found or is disabled") - - remotes = filtered_remotes + remotes = _filter(remotes, pattern, only_enabled) return remotes def disable(self, pattern): - remotes = self.list(pattern, only_enabled=False) - for r in remotes: - r.disabled = True - self.update(r.name, disabled=True) - return remotes + """ + Disable all remotes matching ``pattern`` + + :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without + wildcards like "*" and no remote is found matching that exact name, it will raise an error. + :return: the list of disabled ``Remote`` objects (even if they were already disabled) + """ + remotes = _load(self._remotes_file) + disabled = _filter(remotes, pattern, only_enabled=False) + result = [] + if disabled: + for r in disabled: + r.disabled = True + result.append(r) + _save(self._remotes_file, remotes) + return result def enable(self, pattern): - remotes = self.list(pattern, only_enabled=False) - for r in remotes: - r.disabled = False - self.update(r.name, disabled=False) - return remotes + """ + Enable all remotes matching ``pattern``. + + :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without + wildcards like "*" and no remote is found matching that exact name, it will raise an error. + :return: the list of enabled ``Remote`` objects (even if they were already enabled) + """ + remotes = _load(self._remotes_file) + enabled = _filter(remotes, pattern, only_enabled=False) + result = [] + if enabled: + for r in enabled: + r.disabled = False + result.append(r) + _save(self._remotes_file, remotes) + return result def get(self, remote_name): - return RemoteRegistry(self._remotes_file).read(remote_name) + """ + Obtain a ``Remote`` object + + :param remote_name: the exact name of the remote to be returned + :return: the ``Remote`` object, or raise an Exception if the remote does not exist. + """ + remotes = _load(self._remotes_file) + try: + return {r.name: r for r in remotes}[remote_name] + except KeyError: + raise ConanException(f"Remote '{remote_name}' doesn't exist") def add(self, remote: Remote, force=False, index=None): - return RemoteRegistry(self._remotes_file).add(remote, force=force, index=index) + """ + Add a new ``Remote`` object to the existing ones + + :param remote: a ``Remote`` object to be added + :param force: do not fail if the remote already exist (but default it failes) + :param index: if not defined, the new remote will be last one. Pass an integer to insert + the remote in that position instead of the last one + """ + remotes = _load(self._remotes_file) + _validate_url(remote.url) + current = {r.name: r for r in remotes}.get(remote.name) + if current: # same name remote existing! + if not force: + raise ConanException(f"Remote '{remote.name}' already exists in remotes " + "(use --force to continue)") + ConanOutput().warning(f"Remote '{remote.name}' already exists in remotes") + if current.url != remote.url: + ConanOutput().warning("Updating existing remote with new url") - def remove(self, pattern: str): + _check_urls(remotes, remote.url, force, current) + if index is None: # append or replace in place + d = {r.name: r for r in remotes} + d[remote.name] = remote + remotes = list(d.values()) + else: + remotes = [r for r in remotes if r.name != remote.name] + remotes.insert(index, remote) + _save(self._remotes_file, remotes) + + def remove(self, pattern): + """ + Remove the remotes matching the ``pattern`` + + :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without + wildcards like "*" and no remote is found matching that exact name, it will raise an error. + :return: The list of removed ``Remote`` objects + """ + remotes = _load(self._remotes_file) + 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) - remotes = self.list(pattern, only_enabled=False) - for remote in remotes: - RemoteRegistry(self._remotes_file).remove(remote.name) - users_clean(app.cache.localdb, remote.url) + for remote in removed: + app.cache.localdb.clean(remote_url=remote.url) + return removed + + def update(self, remote_name: str, url=None, secure=None, disabled=None, index=None, + allowed_packages=None): + """ + Update an existing remote + + :param remote_name: The name of the remote to update, must exist + :param url: optional url to update, if not defined it will not be updated + :param secure: optional ssl secure connection to update + :param disabled: optional disabled state + :param index: optional integer to change the order of the remote + :param allowed_packages: optional list of packages allowed from this remote + """ + remotes = _load(self._remotes_file) + try: + remote = {r.name: r for r in remotes}[remote_name] + except KeyError: + raise ConanException(f"Remote '{remote_name}' doesn't exist") + if url is not None: + _validate_url(url) + _check_urls(remotes, url, force=False, current=remote) + remote.url = url + if secure is not None: + remote.verify_ssl = secure + if disabled is not None: + remote.disabled = disabled + if allowed_packages is not None: + remote.allowed_packages = allowed_packages - def update(self, remote_name, url=None, secure=None, disabled=None, index=None, allowed_packages=None): - RemoteRegistry(self._remotes_file).update(remote_name, url, secure, disabled=disabled, - index=index, allowed_packages=allowed_packages) + if index is not None: + remotes = [r for r in remotes if r.name != remote.name] + remotes.insert(index, remote) + _save(self._remotes_file, remotes) def rename(self, remote_name: str, new_name: str): - RemoteRegistry(self._remotes_file).rename(remote_name, new_name) + """ + Change the name of an existing remote + + :param remote_name: The previous existing name + :param new_name: The new name + """ + remotes = _load(self._remotes_file) + d = {r.name: r for r in remotes} + if new_name in d: + raise ConanException(f"Remote '{new_name}' already exists") + try: + d[remote_name].name = new_name + except KeyError: + raise ConanException(f"Remote '{remote_name}' doesn't exist") + _save(self._remotes_file, remotes) def user_info(self, remote: Remote): + # TODO: Review app = ConanApp(self.conan_api) - return users_list(app.cache.localdb, remotes=[remote])[0] + user_info = {} + user, token, _ = app.cache.localdb.get_login(remote.url) + user_info["name"] = remote.name + user_info["user_name"] = user + user_info["authenticated"] = True if token else False + return user_info - def login(self, remote: Remote, username, password): + def user_login(self, remote: Remote, username: str, password: str): + """ + Perform user authentication against the given remote with the provided username and password + + :param remote: a ``Remote`` object + :param username: the user login as ``str`` + :param password: password ``str`` + """ app = ConanApp(self.conan_api) app.remote_manager.authenticate(remote, username, password) - def logout(self, remote: Remote): + def user_logout(self, remote: Remote): + """ + Logout from the given ``Remote`` + + :param remote: The ``Remote`` object to logout + """ app = ConanApp(self.conan_api) # The localdb only stores url + username + token, not remote name, so use URL as key - users_clean(app.cache.localdb, remote.url) + app.cache.localdb.clean(remote_url=remote.url) def user_set(self, remote: Remote, username): + # TODO: Review app = ConanApp(self.conan_api) - return user_set(app.cache.localdb, username, remote) + if username == "": + username = None + app.cache.localdb.store(username, token=None, refresh_token=None, remote_url=remote.url) - def auth(self, remote: Remote, with_user=False): + 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) @@ -108,3 +243,79 @@ def auth(self, remote: Remote, with_user=False): app.remote_manager.check_credentials(remote) user, token, _ = app.cache.localdb.get_login(remote.url) return user + + +def _load(remotes_file): + if not os.path.exists(remotes_file): + remote = Remote(CONAN_CENTER_REMOTE_NAME, "https://center.conan.io", True, False) + _save(remotes_file, [remote]) + return [remote] + + data = json.loads(load(remotes_file)) + result = [] + for r in data.get("remotes", []): + remote = Remote(r["name"], r["url"], r["verify_ssl"], r.get("disabled", False), + r.get("allowed_packages")) + result.append(remote) + return result + + +def _save(remotes_file, remotes): + remote_list = [] + for r in remotes: + remote = {"name": r.name, "url": r.url, "verify_ssl": r.verify_ssl} + if r.disabled: + remote["disabled"] = True + if r.allowed_packages: + remote["allowed_packages"] = r.allowed_packages + remote_list.append(remote) + save(remotes_file, json.dumps({"remotes": remote_list}, indent=True)) + + +def _filter(remotes, pattern, only_enabled=True): + filtered_remotes = [] + patterns = [pattern] if isinstance(pattern, str) else pattern + for p in patterns: + is_match = False + for remote in remotes: + if fnmatch.fnmatch(remote.name, p): + is_match = True + if remote not in filtered_remotes: + filtered_remotes.append(remote) + if not is_match: + if "*" in p or "?" in p: + if only_enabled: + raise ConanException( + f"Remotes for pattern '{p}' can't be found or are disabled") + else: + raise ConanException(f"Remote '{p}' can't be found or is disabled") + return filtered_remotes + + +def _validate_url(url): + """ Check if URL contains protocol and address + :param url: URL to be validated + """ + out = ConanOutput() + if url: + if url.startswith("https://conan.io/center"): + raise ConanException("Wrong ConanCenter remote URL. You are adding the web " + "https://conan.io/center the correct remote API is " + "https://center.conan.io") + address = urlparse(url) + if not all([address.scheme, address.netloc]): + out.warning(f"The URL '{url}' is invalid. It must contain scheme and hostname.") + else: + out.warning("The URL is empty. It must contain scheme and hostname.") + + +def _check_urls(remotes, url, force, current): + # The remote name doesn't exist + for r in remotes: + if r is not current and r.url == url: + msg = f"Remote url already existing in remote '{r.name}'. " \ + f"Having different remotes with same URL is not recommended." + if not force: + raise ConanException(msg + " Use '--force' to override.") + else: + ConanOutput().warning(msg + " Adding duplicated remote url because '--force'.") diff --git a/conan/cli/commands/remote.py b/conan/cli/commands/remote.py index 72ccc49b8fb..ef76a01d2af 100644 --- a/conan/cli/commands/remote.py +++ b/conan/cli/commands/remote.py @@ -56,6 +56,7 @@ def remote_list(conan_api: ConanAPI, parser, subparser, *args): """ List current remotes. """ + parser.parse_args(*args) return conan_api.remotes.list(only_enabled=False) @@ -80,15 +81,17 @@ def remote_add(conan_api, parser, subparser, *args): conan_api.remotes.add(r, force=args.force, index=args.index) -@conan_subcommand() +@conan_subcommand(formatters={"text": print_remote_list}) def remote_remove(conan_api, parser, subparser, *args): """ - Remove a remote. + Remove remotes. """ subparser.add_argument("remote", help="Name of the remote to remove. " "Accepts 'fnmatch' style wildcards.") # to discuss args = parser.parse_args(*args) - conan_api.remotes.remove(args.remote) + remotes = conan_api.remotes.remove(args.remote) + cli_out_write("Removed remotes:") + return remotes @conan_subcommand() @@ -190,7 +193,7 @@ def remote_login(conan_api, parser, subparser, *args): ret = OrderedDict() for r in remotes: previous_info = conan_api.remotes.user_info(r) - conan_api.remotes.login(r, user, password) + conan_api.remotes.user_login(r, user, password) info = conan_api.remotes.user_info(r) ret[r.name] = {"previous_info": previous_info, "info": info} @@ -215,7 +218,7 @@ def remote_set_user(conan_api, parser, subparser, *args): for r in remotes: previous_info = conan_api.remotes.user_info(r) if previous_info["user_name"] != args.username: - conan_api.remotes.logout(r) + conan_api.remotes.user_logout(r) conan_api.remotes.user_set(r, args.username) ret[r.name] = {"previous_info": previous_info, "info": conan_api.remotes.user_info(r)} return ret @@ -236,7 +239,7 @@ def remote_logout(conan_api, parser, subparser, *args): ret = OrderedDict() for r in remotes: previous_info = conan_api.remotes.user_info(r) - conan_api.remotes.logout(r) + conan_api.remotes.user_logout(r) info = conan_api.remotes.user_info(r) ret[r.name] = {"previous_info": previous_info, "info": info} return ret @@ -274,7 +277,7 @@ def remote_auth(conan_api, parser, subparser, *args): results = {} for r in remotes: try: - results[r.name] = {"user": conan_api.remotes.auth(r, args.with_user)} + results[r.name] = {"user": conan_api.remotes.user_auth(r, args.with_user)} except Exception as e: results[r.name] = {"error": str(e)} return results diff --git a/conans/client/cache/cache.py b/conans/client/cache/cache.py index 6b8b6087090..aa25c8199bd 100644 --- a/conans/client/cache/cache.py +++ b/conans/client/cache/cache.py @@ -130,4 +130,4 @@ def store(self): @property def localdb(self): localdb_filename = os.path.join(self.cache_folder, LOCALDB) - return LocalDB.create(localdb_filename) + return LocalDB(localdb_filename) diff --git a/conans/client/cache/remote_registry.py b/conans/client/cache/remote_registry.py deleted file mode 100644 index 860d39265eb..00000000000 --- a/conans/client/cache/remote_registry.py +++ /dev/null @@ -1,192 +0,0 @@ -import json -import os -from urllib.parse import urlparse - -from conan.api.model import Remote -from conan.api.output import ConanOutput -from conans.errors import ConanException -from conans.util.files import load, save - -CONAN_CENTER_REMOTE_NAME = "conancenter" - - -class _Remotes: - """Class to manage an ordered list of Remote objects, performing validations - and updating the remotes. Used by RemoteRegistry only! """ - - def __init__(self): - self._remotes = {} - - def __bool__(self): - return bool(self._remotes) - - def __getitem__(self, remote_name): - try: - return self._remotes[remote_name] - except KeyError: - raise ConanException(f"Remote '{remote_name}' doesn't exist") - - @staticmethod - def load(filename): - text = load(filename) - result = _Remotes() - data = json.loads(text) - for r in data.get("remotes", []): - disabled = r.get("disabled", False) - allowed_packages = r.get("allowed_packages", None) - # TODO: Remote.serialize/deserialize - remote = Remote(r["name"], r["url"], r["verify_ssl"], disabled, allowed_packages) - result._remotes[r["name"]] = remote - return result - - def dumps(self): - remote_list = [] - for r in self._remotes.values(): - remote = {"name": r.name, "url": r.url, "verify_ssl": r.verify_ssl} - if r.disabled: - remote["disabled"] = True - if r.allowed_packages: - remote["allowed_packages"] = r.allowed_packages - remote_list.append(remote) - ret = {"remotes": remote_list} - return json.dumps(ret, indent=True) - - def rename(self, remote_name, new_remote_name): - if new_remote_name in self._remotes: - raise ConanException("Remote '%s' already exists" % new_remote_name) - - r = self[remote_name] - r._name = new_remote_name - # Keep the remotes order - self._remotes = {r.name: r for r in self._remotes.values()} - - def remove(self, remote_name): - try: - self._remotes.pop(remote_name) - except KeyError: - raise ConanException(f"Remote '{remote_name}' doesn't exist") - - def add(self, new_remote: Remote, index=None, force=False): - assert isinstance(new_remote, Remote) - current = self._remotes.get(new_remote.name) - if current: # same name remote existing! - if not force: - raise ConanException(f"Remote '{new_remote.name}' already exists in remotes " - "(use --force to continue)") - ConanOutput().warning(f"Remote '{new_remote.name}' already exists in remotes") - if current.url != new_remote.url: - ConanOutput().warning("Updating existing remote with new url") - - self._check_urls(new_remote.url, force, current) - if index is None: - self._remotes[new_remote.name] = new_remote - else: - self._remotes.pop(new_remote.name, None) - remotes = list(self._remotes.values()) - remotes.insert(index, new_remote) - self._remotes = {r.name: r for r in remotes} - - def _check_urls(self, url, force, current): - # The remote name doesn't exist - for r in self._remotes.values(): - if r is not current and r.url == url: - msg = f"Remote url already existing in remote '{r.name}'. " \ - f"Having different remotes with same URL is not recommended." - if not force: - raise ConanException(msg + " Use '--force' to override.") - else: - ConanOutput().warning(msg + " Adding duplicated remote url because '--force'.") - - def update(self, remote_name, url=None, secure=None, disabled=None, index=None, force=False, allowed_packages=None): - remote = self[remote_name] - if url is not None: - self._check_urls(url, force, remote) - remote.url = url - if secure is not None: - remote.verify_ssl = secure - if disabled is not None: - remote.disabled = disabled - - if index is not None: - self._remotes.pop(remote.name, None) - remotes = list(self._remotes.values()) - remotes.insert(index, remote) - self._remotes = {r.name: r for r in remotes} - - if allowed_packages is not None: - remote.allowed_packages = allowed_packages - - def items(self): - return list(self._remotes.values()) - - -class RemoteRegistry(object): - """Store remotes in disk and modify remotes for the 'conan remote' command. - It never returns an _Remotes object, only Remote model""" - - def __init__(self, remotes_json): - self._output = ConanOutput() - self._filename = remotes_json - - def _validate_url(self, url): - """ Check if URL contains protocol and address - - :param url: URL to be validated - """ - if url: - if url.startswith("https://conan.io/center"): - raise ConanException("Wrong ConanCenter remote URL. You are adding the web " - "https://conan.io/center the correct remote API is " - "https://center.conan.io") - address = urlparse(url) - if not all([address.scheme, address.netloc]): - self._output.warning("The URL '%s' is invalid. It must contain scheme and hostname." - % url) - else: - self._output.warning("The URL is empty. It must contain scheme and hostname.") - - def initialize_remotes(self): - if not os.path.exists(self._filename): - remotes = _Remotes() - remote = Remote(CONAN_CENTER_REMOTE_NAME, "https://center.conan.io", True, False) - remotes.add(remote) - self.save_remotes(remotes) - - def _load_remotes(self): - self.initialize_remotes() - return _Remotes.load(self._filename) - - def list(self): - return self._load_remotes().items() - - def read(self, remote_name): - remotes = self._load_remotes() - ret = remotes[remote_name] - return ret - - def add(self, remote: Remote, force=False, index=None): - self._validate_url(remote.url) - remotes = self._load_remotes() - remotes.add(remote, force=force, index=index) - self.save_remotes(remotes) - - def remove(self, remote_name): - assert isinstance(remote_name, str) - remotes = self._load_remotes() - remotes.remove(remote_name) - self.save_remotes(remotes) - - def update(self, remote_name, url, secure, disabled, index, allowed_packages): - if url is not None: - self._validate_url(url) - remotes = self._load_remotes() - remotes.update(remote_name, url, secure, disabled, index, allowed_packages=allowed_packages) - self.save_remotes(remotes) - - def rename(self, remote, new_name): - remotes = self._load_remotes() - remotes.rename(remote, new_name) - self.save_remotes(remotes) - - def save_remotes(self, remotes): - save(self._filename, remotes.dumps()) diff --git a/conans/client/cmd/user.py b/conans/client/cmd/user.py deleted file mode 100644 index 5b4539a0c7c..00000000000 --- a/conans/client/cmd/user.py +++ /dev/null @@ -1,32 +0,0 @@ -from conans.errors import ConanException - - -def users_list(localdb, remotes): - if not remotes: - raise ConanException("No remotes defined") - - remotes_info = [] - for remote in remotes: - user_info = {} - 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 - remotes_info.append(user_info) - return remotes_info - - -def users_clean(localdb, remote_url=None): - localdb.clean(remote_url=remote_url) - - -def user_set(localdb, user, remote_name=None): - if user == "": - user = None - return update_localdb(localdb, user, token=None, refresh_token=None, remote=remote_name) - - -def update_localdb(localdb, user, token, refresh_token, remote): - previous_user = localdb.get_username(remote.url) - localdb.store(user, token, refresh_token, remote.url) - return remote.name, previous_user, user diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 7a9e4f40e33..30c0ab72029 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -4,9 +4,9 @@ from requests.exceptions import ConnectionError +from conan.api.model import Remote from conan.api.output import ConanOutput from conan.internal.cache.conan_reference_layout import METADATA -from conans.client.cache.remote_registry import Remote from conans.client.pkg_sign import PkgSignaturesPlugin from conans.errors import ConanConnectionError, ConanException, NotFoundException, \ PackageNotFoundException diff --git a/conans/client/rest/auth_manager.py b/conans/client/rest/auth_manager.py index fd353318f8e..603cc5177b0 100644 --- a/conans/client/rest/auth_manager.py +++ b/conans/client/rest/auth_manager.py @@ -15,7 +15,6 @@ from uuid import getnode as get_mac from conan.api.output import ConanOutput -from conans.client.cmd.user import update_localdb from conans.client.rest.remote_credentials import RemoteCredentials from conans.errors import AuthenticationException, ConanException, ForbiddenException @@ -120,6 +119,4 @@ def _authenticate(self, remote, user, password): raise ConanException("Password contains not allowed symbols") # Store result in DB - remote_name, prev_user, user = update_localdb(self._localdb, user, token, refresh_token, - remote) - return remote_name, prev_user, user + self._localdb.store(user, token, refresh_token, remote.url) diff --git a/conans/client/store/localdb.py b/conans/client/store/localdb.py index 832855f09ba..9ae82f9ebf1 100644 --- a/conans/client/store/localdb.py +++ b/conans/client/store/localdb.py @@ -11,12 +11,28 @@ _localdb_encryption_key = os.environ.pop('CONAN_LOGIN_ENCRYPTION_KEY', None) -class LocalDB(object): +class LocalDB: def __init__(self, dbfile): self.dbfile = dbfile 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) + os.makedirs(par, exist_ok=True) + open(dbfile, 'w').close() + + with self._connect() as connection: + try: + cursor = connection.cursor() + cursor.execute("create table if not exists %s " + "(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}" + raise ConanException(message, e) + def _encode(self, value): if value and self.encryption_key: return encrypt.encode(value, self.encryption_key) @@ -44,29 +60,6 @@ def clean(self, remote_url=None): except Exception as e: raise ConanException("Could not initialize local sqlite database", e) - @staticmethod - def create(dbfile): - # 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(par): - os.makedirs(par) - db = open(dbfile, 'w+') - db.close() - - db = LocalDB(dbfile) - with db._connect() as connection: - try: - cursor = connection.cursor() - cursor.execute("create table if not exists %s " - "(remote_url TEXT UNIQUE, user TEXT, " - "token TEXT, refresh_token TEXT)" % REMOTES_USER_TABLE) - except Exception as e: - message = "Could not initialize local sqlite database" - raise ConanException(message, e) - - return db - @contextmanager def _connect(self): connection = sqlite3.connect(self.dbfile, detect_types=sqlite3.PARSE_DECLTYPES) diff --git a/conans/test/functional/command/config_install_test.py b/conans/test/functional/command/config_install_test.py index 67897d29de3..b8ef676018b 100644 --- a/conans/test/functional/command/config_install_test.py +++ b/conans/test/functional/command/config_install_test.py @@ -7,7 +7,7 @@ import pytest from mock import patch -from conans.client.cache.remote_registry import Remote +from conan.api.model import Remote from conans.client.conf.config_installer import _hide_password from conans.client.downloaders.file_downloader import FileDownloader from conans.paths import DEFAULT_CONAN_HOME diff --git a/conans/test/integration/command/remote_test.py b/conans/test/integration/command/remote_test.py index df291fbb187..0a1975ef174 100644 --- a/conans/test/integration/command/remote_test.py +++ b/conans/test/integration/command/remote_test.py @@ -3,8 +3,6 @@ import unittest from collections import OrderedDict -import pytest - from conans.test.assets.genconanfile import GenConanfile from conans.test.utils.tools import TestClient, TestServer from conans.util.files import load @@ -238,7 +236,7 @@ def test_remote_disable(self): self.assertEqual(data["remotes"][3]["disabled"], True) # check that they are still listed, as disabled - client.run("remote list *") + client.run("remote list") assert "my-remote0: http://someurl0 [Verify SSL: True, Enabled: False]" in client.out assert "my-remote3: http://someurl3 [Verify SSL: True, Enabled: False]" in client.out @@ -340,6 +338,7 @@ def test_add_wrong_conancenter(): c.run("remote add whatever https://conan.io/center", assert_error=True) assert "Wrong ConanCenter remote URL. You are adding the web https://conan.io/center" in c.out assert "the correct remote API is https://center.conan.io" in c.out + c.run("remote add conancenter https://center.conan.io") c.run("remote update conancenter --url=https://conan.io/center", assert_error=True) assert "Wrong ConanCenter remote URL. You are adding the web https://conan.io/center" in c.out assert "the correct remote API is https://center.conan.io" in c.out diff --git a/conans/test/integration/remote/token_refresh_test.py b/conans/test/integration/remote/token_refresh_test.py index a81eaef9e13..2d57d6b1c5e 100644 --- a/conans/test/integration/remote/token_refresh_test.py +++ b/conans/test/integration/remote/token_refresh_test.py @@ -3,7 +3,7 @@ import mock from mock import Mock -from conans.client.cache.remote_registry import Remote +from conan.api.model import Remote from conans.client.rest.auth_manager import ConanApiAuthManager from conans.client.rest.rest_client import RestApiClientFactory from conans.model.conf import ConfDefinition diff --git a/conans/test/unittests/util/local_db_test.py b/conans/test/unittests/util/local_db_test.py index 3b5ba43ea30..650c6d414d6 100644 --- a/conans/test/unittests/util/local_db_test.py +++ b/conans/test/unittests/util/local_db_test.py @@ -10,7 +10,7 @@ class LocalStoreTest(unittest.TestCase): def test_localdb(self): tmp_dir = temp_folder() db_file = os.path.join(tmp_dir, "dbfile") - localdb = LocalDB.create(db_file) + localdb = LocalDB(db_file) # Test write and read login user, token, access_token = localdb.get_login("myurl1") diff --git a/conans/test/utils/tools.py b/conans/test/utils/tools.py index 39bf1e27967..5e96c8550cc 100644 --- a/conans/test/utils/tools.py +++ b/conans/test/utils/tools.py @@ -32,7 +32,6 @@ 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.client.cache.remote_registry import RemoteRegistry from conans.util.env import environment_update from conans.errors import NotFoundException, ConanException from conans.model.manifest import FileTreeManifest @@ -471,13 +470,12 @@ def update_servers(self): api.remotes.remove(r.name) for name, server in self.servers.items(): - remotes_registry = RemoteRegistry(HomePaths(self.cache_folder).remotes_path) if isinstance(server, ArtifactoryServer): - remotes_registry.add(Remote(name, server.repo_api_url)) + api.remotes.add(Remote(name, server.repo_api_url)) elif isinstance(server, TestServer): - remotes_registry.add(Remote(name, server.fake_url)) + api.remotes.add(Remote(name, server.fake_url)) else: - remotes_registry.add(Remote(name, server)) + api.remotes.add(Remote(name, server)) @contextmanager def chdir(self, newdir):