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, output): self.cache_folder = cache_folder self._output = output # Caching self._no_lock = None self._config = None self.editable_packages = EditablePackages(self.cache_folder) # paths self._store_folder = self.config.storage_path or self.cache_folder # Just call it to make it raise in case of short_paths misconfiguration _ = self.config.short_paths_home def all_refs(self): subdirs = list_folder_subdirs(basedir=self._store_folder, level=4) return [ConanFileReference.load_dir_repr(folder) for folder in subdirs] @property def store(self): return self._store_folder def installed_as_editable(self, ref): return isinstance(self.package_layout(ref), PackageEditableLayout) @property def config_install_file(self): return os.path.join(self.cache_folder, "config_install.json") def package_layout(self, ref, short_paths=None): assert isinstance(ref, ConanFileReference), "It is a {}".format(type(ref)) edited_ref = self.editable_packages.get(ref.copy_clear_rev()) if edited_ref: conanfile_path = edited_ref["path"] layout_file = edited_ref["layout"] return PackageEditableLayout(os.path.dirname(conanfile_path), layout_file, ref, conanfile_path) else: check_ref_case(ref, self.store) base_folder = os.path.normpath( os.path.join(self.store, ref.dir_repr())) return PackageCacheLayout(base_folder=base_folder, ref=ref, short_paths=short_paths, no_lock=self._no_locks()) @property def remotes_path(self): return join(self.cache_folder, REMOTES) @property def registry(self): return RemoteRegistry(self, self._output) def _no_locks(self): if self._no_lock is None: self._no_lock = self.config.cache_no_locks return self._no_lock @property def artifacts_properties_path(self): return join(self.cache_folder, ARTIFACTS_PROPERTIES_FILE) def read_artifacts_properties(self): ret = {} if not os.path.exists(self.artifacts_properties_path): save(self.artifacts_properties_path, "") return ret try: contents = load(self.artifacts_properties_path) for line in contents.splitlines(): if line and not line.strip().startswith("#"): tmp = line.split("=", 1) if len(tmp) != 2: raise Exception() name = tmp[0].strip() value = tmp[1].strip() ret[str(name)] = str(value) return ret except Exception: raise ConanException("Invalid %s file!" % self.artifacts_properties_path) @property def config(self): if not self._config: self.initialize_config() self._config = ConanClientConfigParser(self.conan_conf_path) return self._config @property def localdb(self): return join(self.cache_folder, LOCALDB) @property def conan_conf_path(self): return join(self.cache_folder, CONAN_CONF) @property def profiles_path(self): return join(self.cache_folder, PROFILES_FOLDER) @property def settings_path(self): return join(self.cache_folder, CONAN_SETTINGS) @property def generators_path(self): return join(self.cache_folder, GENERATORS_FOLDER) @property def default_profile_path(self): if os.path.isabs(self.config.default_profile): return self.config.default_profile else: return join(self.cache_folder, PROFILES_FOLDER, self.config.default_profile) @property def hooks_path(self): """ :return: Hooks folder in client cache """ return join(self.cache_folder, HOOKS_FOLDER) @property def default_profile(self): self.initialize_default_profile() default_profile, _ = read_profile(self.default_profile_path, get_cwd(), self.profiles_path) # Mix profile settings with environment mixed_settings = _mix_settings_with_env(default_profile.settings) default_profile.settings = mixed_settings return default_profile @property def settings(self): """Returns {setting: [value, ...]} defining all the possible settings without values""" self.initialize_settings() content = load(self.settings_path) return Settings.loads(content) @property def hooks(self): """Returns a list of hooks inside the hooks folder""" hooks = [] for hook_name in os.listdir(self.hooks_path): if os.path.isfile(hook_name) and hook_name.endswith(".py"): hooks.append(hook_name[:-3]) return hooks @property def generators(self): """Returns a list of generator paths inside the generators folder""" generators = [] if os.path.exists(self.generators_path): for path in os.listdir(self.generators_path): generator = os.path.join(self.generators_path, path) if os.path.isfile(generator) and generator.endswith(".py"): generators.append(generator) return generators def delete_empty_dirs(self, deleted_refs): for ref in deleted_refs: ref_path = self.package_layout(ref).base_folder() for _ in range(4): if os.path.exists(ref_path): try: # Take advantage that os.rmdir does not delete non-empty dirs os.rmdir(ref_path) except OSError: break # not empty ref_path = os.path.dirname(ref_path) def remove_locks(self): folders = list_folder_subdirs(self._store_folder, 4) for folder in folders: conan_folder = os.path.join(self._store_folder, folder) Lock.clean(conan_folder) shutil.rmtree(os.path.join(conan_folder, "locks"), ignore_errors=True) def get_template(self, template_name, user_overrides=False): # TODO: It can be initialized only once together with the Conan app loaders = [dict_loader] if user_overrides: loaders.insert( 0, FileSystemLoader(os.path.join(self.cache_folder, 'templates'))) env = Environment(loader=ChoiceLoader(loaders), autoescape=select_autoescape(['html', 'xml'])) return env.get_template(template_name) def initialize_config(self): if not os.path.exists(self.conan_conf_path): save(self.conan_conf_path, normalize(get_default_client_conf())) def reset_config(self): if os.path.exists(self.conan_conf_path): remove(self.conan_conf_path) self.initialize_config() def initialize_default_profile(self): if not os.path.exists(self.default_profile_path): self._output.writeln( "Auto detecting your dev setup to initialize the " "default profile (%s)" % self.default_profile_path, Color.BRIGHT_YELLOW) default_settings = detect_defaults_settings( self._output, profile_path=self.default_profile_path) self._output.writeln("Default settings", Color.BRIGHT_YELLOW) self._output.writeln( "\n".join(["\t%s=%s" % (k, v) for (k, v) in default_settings]), Color.BRIGHT_YELLOW) self._output.writeln( "*** You can change them in %s ***" % self.default_profile_path, Color.BRIGHT_MAGENTA) self._output.writeln( "*** Or override with -s compiler='other' -s ...s***\n\n", Color.BRIGHT_MAGENTA) default_profile = Profile() tmp = OrderedDict(default_settings) default_profile.update_settings(tmp) save(self.default_profile_path, default_profile.dumps()) def reset_default_profile(self): if os.path.exists(self.default_profile_path): remove(self.default_profile_path) self.initialize_default_profile() def initialize_settings(self): if not os.path.exists(self.settings_path): save(self.settings_path, normalize(get_default_settings_yml())) def reset_settings(self): if os.path.exists(self.settings_path): remove(self.settings_path) self.initialize_settings()
class ClientCache(SimplePaths): """ 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, base_folder, store_folder, output): self.conan_folder = join(base_folder, ".conan") self._config = None self._output = output self._store_folder = store_folder or self.config.storage_path or self.conan_folder self._no_lock = None self.client_cert_path = normpath(join(self.conan_folder, CLIENT_CERT)) self.client_cert_key_path = normpath( join(self.conan_folder, CLIENT_KEY)) self._registry = None super(ClientCache, self).__init__(self._store_folder) self.editable_packages = EditablePackages(self.conan_folder) @property def config_install_file(self): return os.path.join(self.conan_folder, "config_install.json") def package_layout(self, ref, short_paths=None, *args, **kwargs): assert isinstance(ref, ConanFileReference), "It is a {}".format(type(ref)) edited_ref = self.editable_packages.get(ref.copy_clear_rev()) if edited_ref: base_path = edited_ref["path"] layout_file = edited_ref["layout"] return PackageEditableLayout(base_path, layout_file, ref) else: check_ref_case(ref, self.store) base_folder = os.path.normpath( os.path.join(self.store, ref.dir_repr())) return PackageCacheLayout(base_folder=base_folder, ref=ref, short_paths=short_paths, no_lock=self._no_locks()) @property def registry(self): if not self._registry: self._registry = RemoteRegistry(self.registry_path, self._output) return self._registry @property def cacert_path(self): return self.config.cacert_path def _no_locks(self): if self._no_lock is None: self._no_lock = self.config.cache_no_locks return self._no_lock def conanfile_read_lock(self, ref): layout = self.package_layout(ref) return layout.conanfile_read_lock(self._output) def conanfile_write_lock(self, ref): layout = self.package_layout(ref) return layout.conanfile_write_lock(self._output) def conanfile_lock_files(self, ref): layout = self.package_layout(ref) return layout.conanfile_lock_files(self._output) def package_lock(self, pref): layout = self.package_layout(pref.ref) return layout.package_lock(pref) @property def put_headers_path(self): return join(self.conan_folder, PUT_HEADERS) def read_put_headers(self): ret = {} if not os.path.exists(self.put_headers_path): save(self.put_headers_path, "") return ret try: contents = load(self.put_headers_path) for line in contents.splitlines(): if line and not line.strip().startswith("#"): tmp = line.split("=", 1) if len(tmp) != 2: raise Exception() name = tmp[0].strip() value = tmp[1].strip() ret[str(name)] = str(value) return ret except Exception: raise ConanException("Invalid %s file!" % self.put_headers_path) @property def registry_path(self): reg_json_path = join(self.conan_folder, REGISTRY_JSON) if not os.path.exists(reg_json_path): # Load the txt if exists and convert to json reg_txt = join(self.conan_folder, REGISTRY) if os.path.exists(reg_txt): migrate_registry_file(reg_txt, reg_json_path) else: self._output.warn("Remotes registry file missing, " "creating default one in %s" % reg_json_path) save(reg_json_path, dump_registry(default_remotes, {}, {})) return reg_json_path @property def config(self): if not self._config: if not os.path.exists(self.conan_conf_path): save(self.conan_conf_path, normalize(default_client_conf)) self._config = ConanClientConfigParser(self.conan_conf_path) return self._config @property def localdb(self): return join(self.conan_folder, LOCALDB) @property def conan_conf_path(self): return join(self.conan_folder, CONAN_CONF) @property def profiles_path(self): return join(self.conan_folder, PROFILES_FOLDER) @property def settings_path(self): return join(self.conan_folder, CONAN_SETTINGS) @property def default_profile_path(self): if os.path.isabs(self.config.default_profile): return self.config.default_profile else: return join(self.conan_folder, PROFILES_FOLDER, self.config.default_profile) @property def hooks_path(self): """ :return: Hooks folder in client cache """ return join(self.conan_folder, HOOKS_FOLDER) @property def default_profile(self): if not os.path.exists(self.default_profile_path): self._output.writeln( "Auto detecting your dev setup to initialize the " "default profile (%s)" % self.default_profile_path, Color.BRIGHT_YELLOW) default_settings = detect_defaults_settings( self._output, profile_path=self.default_profile_path) self._output.writeln("Default settings", Color.BRIGHT_YELLOW) self._output.writeln( "\n".join(["\t%s=%s" % (k, v) for (k, v) in default_settings]), Color.BRIGHT_YELLOW) self._output.writeln( "*** You can change them in %s ***" % self.default_profile_path, Color.BRIGHT_MAGENTA) self._output.writeln( "*** Or override with -s compiler='other' -s ...s***\n\n", Color.BRIGHT_MAGENTA) default_profile = Profile() tmp = OrderedDict(default_settings) default_profile.update_settings(tmp) save(self.default_profile_path, default_profile.dumps()) else: default_profile, _ = read_profile(self.default_profile_path, get_cwd(), self.profiles_path) # Mix profile settings with environment mixed_settings = _mix_settings_with_env(default_profile.settings) default_profile.settings = mixed_settings return default_profile @property def settings(self): """Returns {setting: [value, ...]} defining all the possible settings without values""" if not os.path.exists(self.settings_path): save(self.settings_path, normalize(default_settings_yml)) settings = Settings.loads(default_settings_yml) else: content = load(self.settings_path) settings = Settings.loads(content) return settings @property def hooks(self): """Returns a list of hooks inside the hooks folder""" hooks = [] for hook_name in os.listdir(self.hooks_path): if os.path.isfile(hook_name) and hook_name.endswith(".py"): hooks.append(hook_name[:-3]) return hooks def conan_packages(self, ref): """ Returns a list of package_id from a local cache package folder """ layout = self.package_layout(ref) return layout.conan_packages() def conan_builds(self, ref): """ Returns a list of package ids from a local cache build folder """ layout = self.package_layout(ref) return layout.conan_builds() def delete_empty_dirs(self, deleted_refs): for ref in deleted_refs: ref_path = self.conan(ref) for _ in range(4): if os.path.exists(ref_path): try: # Take advantage that os.rmdir does not delete non-empty dirs os.rmdir(ref_path) except OSError: break # not empty ref_path = os.path.dirname(ref_path) def remove_package_system_reqs(self, reference): assert isinstance(reference, ConanFileReference) conan_folder = self.conan(reference) system_reqs_folder = os.path.join(conan_folder, SYSTEM_REQS_FOLDER) if not os.path.exists(conan_folder): raise ValueError("%s does not exist" % repr(reference)) if not os.path.exists(system_reqs_folder): return try: rmdir(system_reqs_folder) except Exception as e: raise ConanException( "Unable to remove system requirements at %s: %s" % (system_reqs_folder, str(e))) def remove_locks(self): folders = list_folder_subdirs(self._store_folder, 4) for folder in folders: conan_folder = os.path.join(self._store_folder, folder) Lock.clean(conan_folder) shutil.rmtree(os.path.join(conan_folder, "locks"), ignore_errors=True) def remove_package_locks(self, ref): package_layout = self.package_layout(ref=ref) package_layout.remove_package_locks() def invalidate(self): self._config = None self._no_lock = None