示例#1
0
文件: cache.py 项目: ninjayash/conan
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()
示例#2
0
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