def _rmtree(self, path): try: forceful_rmtree(path) except Exception as e: print_warning("Failed to delete %s - %s", path, e)
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)
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