diff --git a/pym/gentoolkit/eclean/clean.py b/pym/gentoolkit/eclean/clean.py index 87d7aaca..e99fe55a 100644 --- a/pym/gentoolkit/eclean/clean.py +++ b/pym/gentoolkit/eclean/clean.py @@ -5,6 +5,7 @@ import os +import shutil import sys import gentoolkit.pprinter as pp @@ -23,7 +24,7 @@ def __init__(self, controller, quiet): self.controller = controller self.quiet = quiet - def clean_dist(self, clean_dict): + def clean_dist(self, clean_dict, git): """Calculate size of each entry for display, prompt user if needed, delete files if approved and return the total size of files that have been deleted. @@ -39,6 +40,7 @@ def clean_dist(self, clean_dict): for key in sorted(clean_dict): clean_size += self._clean_files(clean_dict[key], key, file_type) # return total size of deleted or to delete files + clean_size += self._clean_git_src(git) return clean_size def clean_pkgs(self, clean_dict, pkgdir): @@ -148,3 +150,29 @@ def _clean_files(self, files, key, file_type): print(pp.error("Could not delete " + file_), file=sys.stderr) print(pp.error("Error: %s" % str(er)), file=sys.stderr) return clean_size + + def _clean_git_src(self, deprecated_git): + clean_size = 0 + for checkout in deprecated_git: + csize = 0 + for path, dirs, files in os.walk(checkout): + for f in files: + fp = os.path.join(path, f) + try: + statinfo = os.stat(fp) + except OSError as er: + print( + pp.error("Could not get stat info for:" + fp), + file=sys.stderr, + ) + print(pp.error("Error: %s" % str(er)), file=sys.stderr) + clean_size += statinfo.st_size + csize += statinfo.st_size + + try: + self.controller(csize, checkout, checkout, "checkout") + shutil.rmtree(checkout) + except OSError as er: + print(pp.error("Could not delete " + checkout), file=sys.stderr) + print(pp.error("Error: %s" % str(er)), file=sys.stderr) + return clean_size diff --git a/pym/gentoolkit/eclean/cli.py b/pym/gentoolkit/eclean/cli.py index b180641b..70637701 100644 --- a/pym/gentoolkit/eclean/cli.py +++ b/pym/gentoolkit/eclean/cli.py @@ -13,25 +13,25 @@ __productname__ = "eclean" __description__ = "A cleaning tool for Gentoo distfiles and binaries." +import getopt import os -import sys import re +import sys import time -import getopt import portage -from portage.output import white, yellow, turquoise, green, red +from portage.output import green, red, turquoise, white, yellow import gentoolkit.pprinter as pp +from gentoolkit.eclean.clean import CleanUp +from gentoolkit.eclean.exclude import ParseExcludeFileException, parseExcludeFile +from gentoolkit.eclean.output import OutputControl from gentoolkit.eclean.search import ( DistfilesSearch, findPackages, - port_settings, pkgdir, + port_settings, ) -from gentoolkit.eclean.exclude import parseExcludeFile, ParseExcludeFileException -from gentoolkit.eclean.clean import CleanUp -from gentoolkit.eclean.output import OutputControl # from gentoolkit.eclean.dbapi import Dbapi from gentoolkit.eprefix import EPREFIX @@ -546,6 +546,7 @@ def doAction(action, options, exclude={}, output=None): files_type = "distfiles" saved = {} deprecated = {} + git = [] # find files to delete, depending on the action if not options["quiet"]: output.einfo("Building file list for " + action + " cleaning...") @@ -567,7 +568,7 @@ def doAction(action, options, exclude={}, output=None): # portdb=Dbapi(portage.db[portage.root]["porttree"].dbapi), # var_dbapi=Dbapi(portage.db[portage.root]["vartree"].dbapi), ) - clean_me, saved, deprecated = engine.findDistfiles( + clean_me, saved, deprecated, git = engine.findDistfiles( exclude=exclude, destructive=options["destructive"], fetch_restricted=options["fetch-restricted"], @@ -581,7 +582,7 @@ def doAction(action, options, exclude={}, output=None): cleaner = CleanUp(output.progress_controller, options["quiet"]) # actually clean files if something was found - if clean_me: + if clean_me or git: # verbose pretend message if options["pretend"] and not options["quiet"]: output.einfo("Here are the " + files_type + " that would be deleted:") @@ -592,7 +593,7 @@ def doAction(action, options, exclude={}, output=None): if options["pretend"]: clean_size = cleaner.pretend_clean(clean_me) elif action in ["distfiles"]: - clean_size = cleaner.clean_dist(clean_me) + clean_size = cleaner.clean_dist(clean_me, git) elif action in ["packages"]: clean_size = cleaner.clean_pkgs(clean_me, pkgdir) # vocabulary for final message @@ -602,7 +603,7 @@ def doAction(action, options, exclude={}, output=None): verb = "were" # display freed space if not options["quiet"]: - output.total("normal", clean_size, len(clean_me), verb, action) + output.total("normal", clean_size, len(clean_me) + len(git), verb, action) # nothing was found elif not options["quiet"]: output.einfo("Your " + action + " directory was already clean.") diff --git a/pym/gentoolkit/eclean/output.py b/pym/gentoolkit/eclean/output.py index ebba499c..67387380 100644 --- a/pym/gentoolkit/eclean/output.py +++ b/pym/gentoolkit/eclean/output.py @@ -5,7 +5,9 @@ import sys -from portage.output import blue, yellow, teal, green, red + +from portage.output import blue, green, red, teal, yellow + from gentoolkit.pprinter import cpv, number diff --git a/pym/gentoolkit/eclean/search.py b/pym/gentoolkit/eclean/search.py index a2ac0ce4..239cbfd3 100644 --- a/pym/gentoolkit/eclean/search.py +++ b/pym/gentoolkit/eclean/search.py @@ -16,13 +16,12 @@ import gentoolkit.pprinter as pp from gentoolkit.eclean.exclude import ( - exclDictMatchCP, exclDictExpand, exclDictExpandPkgname, + exclDictMatchCP, exclMatchFilename, ) - # Misc. shortcuts to some portage stuff: port_settings = portage.settings pkgdir = port_settings["PKGDIR"] @@ -134,6 +133,7 @@ def findDistfiles( # gather the files to be cleaned self.output("...checking limits for %d ebuild sources" % len(pkgs)) + git = self.git_check(_distdir) checks = self._get_default_checks(size_limit, time_limit, exclude, destructive) checks.extend(extra_checks) clean_me = self._check_limits(_distdir, checks, clean_me) @@ -148,7 +148,7 @@ def findDistfiles( + "%s remaining candidates to clean" % len(clean_me) ) clean_me, saved = self._check_excludes(exclude, clean_me) - return clean_me, saved, deprecated + return clean_me, saved, deprecated, git # begin _check_limits code block @@ -332,6 +332,18 @@ def _non_destructive( deprecated.update(_deprecated) return pkgs, deprecated + def git_check(self, distdir): + """Checks $DISTDIR/git3-src for checkouts which are not in the vardb""" + expected_dirs = [ + self.vardb._aux_env_search(i, ["EGIT_DIR"])["EGIT_DIR"] + for i in set(self.vardb.cpv_all()) + if "live" in self.vardb.aux_get(i, ["PROPERTIES"]) + ] + git_src = os.path.join(distdir, "git3-src") + gitdir = [os.path.join(git_src, i) for i in os.listdir(git_src)] + deprecated_git = [i for i in gitdir if i not in expected_dirs] + return deprecated_git + def _fetch_restricted(self, pkgs_, cpvs): """perform fetch restricted non-destructive source filename lookups