Пример #1
0
 def _rmtree(self, path):
     try:
         forceful_rmtree(path)
     except Exception as e:
         print_warning("Failed to delete %s - %s", path, e)
Пример #2
0
    def save(self, path, verbose=False):
        """Save the suite to disk.

        Args:
            path (str): Path to save the suite to. If a suite is already saved
                at `path`, then it will be overwritten. Otherwise, if `path`
                exists, an error is raised.
            verbose (bool): Show more messages.
        """
        if verbose and self._is_live:
            print("saving live suite...")

        # todo:
        #   1. instead of wiping it all out, cherry-pick tools to update/remove
        #       by requests.
        #   2. make a copy of current suite (in timestamp dir)

        path = os.path.realpath(path)
        if os.path.exists(path):
            if self.load_path and self.load_path == path:
                if verbose:
                    print("saving over previous suite...")
                for context_name in self.context_names:
                    self.context(context_name)  # load before dir deleted

                forceful_rmtree(path)
            else:
                raise SuiteError("Cannot save, path exists: %r" % path)

        os.makedirs(path)

        # write suite data
        data = self.to_dict()
        filepath = os.path.join(path, "suite.yaml")
        with open(filepath, "w") as f:
            f.write(dump_yaml(data))

        # write contexts
        for context_name in self.context_names:
            context = self.context(context_name)
            context._set_parent_suite(path, context_name)  # noqa
            self._save_context_rxt(context_name, context, path)

        # create alias wrappers
        tools_path = os.path.join(path, "bin")
        os.makedirs(tools_path)
        if verbose:
            print("creating alias wrappers in %r..." % tools_path)

        tools = self.get_tools()
        for tool_alias, d in tools.items():
            tool_name = d["tool_name"]
            context_name = d["context_name"]

            data = self._context(context_name)
            prefix_char = data.get("prefix_char")

            if verbose:
                print("creating %r -> %r (%s context)..." %
                      (tool_alias, tool_name, context_name))
            filepath = os.path.join(tools_path, tool_alias)

            if self._is_live:
                context = data["context"]
                requests = [str(r) for r in context.requested_packages()]
                kwargs = {
                    "module": ("command", "sweet"),  # rez plugin
                    "func_name": "_FWD__invoke_suite_tool_alias_in_live",
                    "package_requests": requests,
                    "context_name": context_name,
                    "tool_name": tool_name,
                    "prefix_char": prefix_char,
                }
            else:
                kwargs = {
                    "module": "suite",
                    "func_name": "_FWD__invoke_suite_tool_alias",
                    "context_name": context_name,
                    "tool_name": tool_name,
                    "prefix_char": prefix_char,
                }

            create_forwarding_script(filepath, **kwargs)
Пример #3
0
    def clean(self, time_limit=None):
        """Delete unused package cache files.

        This should be run periodically via 'rez-pkg-cache --clean'.

        This removes:
        - Variants that have not been used in more than
          'config.package_cache_max_variant_days' days;
        - Variants that have stalled;
        - Variants that are already pending deletion (remove_variant() was used).

        Args:
            time_limit (float): Perform cleaning operations only up until this
                limit, resulting in a possibly incomplete cleanup. This is used
                to keep the cache size down without having to periodically
                run 'rez-pkg-cache --clean'.
        """
        logger = self._init_logging()
        unused_variants = []
        stalled_variants = []
        now = time.time()

        def should_exit():
            return (time_limit is not None
                    and (time.time() - now) > time_limit)

        # find variants to delete
        for variant, rootpath, status in self.get_variants():
            if status == self.VARIANT_FOUND:
                max_secs = config.package_cache_max_variant_days * 3600 * 24
                if max_secs == 0:
                    continue  # 0 means no age limit on unused variants

                # determine how long since cached variant has been used
                json_filepath = rootpath + ".json"
                try:
                    st = os.stat(json_filepath)
                except:
                    # may have just been deleted
                    continue

                since = int(now - st.st_mtime)
                if since > max_secs:
                    unused_variants.append(variant)

            elif status == self.VARIANT_COPY_STALLED:
                stalled_variants.append(variant)

        # remove unused variants. This puts them in our to_delete dir
        for variant in unused_variants:
            status = self.remove_variant(variant)
            if status == self.VARIANT_REMOVED:
                logger.info("Removed unused variant %s from cache",
                            variant.uri)

            if should_exit():
                return

        # Remove stalled variants. This puts them in our to_delete dir.
        #
        # Note that this is not done when cleaning up as part of cache updating.
        # Doing so could result in the same problematic variant getting copied,
        # then stalled, then deleted, then copied again, over and over.
        #
        if time_limit is None:
            for variant in stalled_variants:
                status = self.remove_variant(variant)
                if status == self.VARIANT_REMOVED:
                    logger.info("Removed stalled variant %s from cache",
                                variant.uri)

        # delete everything in to_delete dir
        for name in os.listdir(self._remove_dir):
            path = os.path.join(self._remove_dir, name)

            try:
                forceful_rmtree(path)
            except Exception as e:
                logger.warning("Could not delete %s: %s", path, e)
                continue

            logger.info("Deleted %s", path)
            if should_exit():
                return