Skip to content

Commit 2972728

Browse files
laumannthesamesam
authored andcommitted
eclean-pkg: handle extra binhost cache locations
Support multiple cache locations for binhosts. This is implemented by instantiating a bintree for each defined location. A big chunk of code in findPackages() that looks for dead binpkgs is simply moved into a for-loop to repeat the same search for each location. The output from findPackages() is now a dictionary of locations that, for each location, is a dictionary of binpkgs. Closes: https://bugs.gentoo.org/947694 Signed-off-by: Thomas Bracht Laumann Jespersen <t@laumann.xyz> Part-of: https://codeberg.org/gentoo/gentoolkit/pulls/3 Merges: https://codeberg.org/gentoo/gentoolkit/pulls/3 Signed-off-by: Sam James <sam@gentoo.org>
1 parent aae28fd commit 2972728

3 files changed

Lines changed: 122 additions & 87 deletions

File tree

pym/gentoolkit/eclean/clean.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ def clean_pkgs(self, clean_dict, pkgdir):
6060
file_type = "binary package"
6161
clean_size = 0
6262
# clean all entries one by one; sorting helps reading
63-
for key in sorted(clean_dict):
64-
clean_size += self._clean_binary_package(clean_dict[key], key)
63+
for location, loc_clean_dict in clean_dict.items():
64+
print(" * Location", pp.path(location))
65+
for key in sorted(loc_clean_dict):
66+
clean_size += self._clean_binary_package(loc_clean_dict[key], key)
6567

6668
# run 'emaint --fix' here
6769
if clean_size:
@@ -95,11 +97,13 @@ def pretend_clean(self, clean_dict, vcs={}, file_type="file"):
9597
clean_size += key_size
9698
else:
9799
# binary package
98-
for key in sorted(clean_dict):
99-
(binpkg, debugpack) = clean_dict[key]
100-
key_size = self._get_size([binpkg, debugpack] if debugpack else [binpkg])
101-
self.controller(key_size, key, clean_dict[key], file_type)
102-
clean_size += key_size
100+
for location, loc_clean_dict in clean_dict.items():
101+
print(" * Location", pp.path(location))
102+
for key in sorted(loc_clean_dict):
103+
(binpkg, debugpack) = loc_clean_dict[key]
104+
key_size = self._get_size([binpkg, debugpack] if debugpack else [binpkg])
105+
self.controller(key_size, key, loc_clean_dict[key], file_type)
106+
clean_size += key_size
103107

104108
return clean_size
105109

pym/gentoolkit/eclean/cli.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,13 @@ def doAction(action, options, exclude={}, output=None):
594594

595595
# actually clean files if something was found
596596
if clean_me or vcs:
597+
file_count = len(clean_me)
598+
if action in ["packages"]:
599+
file_count = sum(
600+
2 if entry[1] else 1
601+
for loc_entries in clean_me.values()
602+
for entry in loc_entries.values()
603+
)
597604
# verbose pretend message
598605
if options["pretend"] and not options["quiet"]:
599606
output.einfo("Here are the " + files_type + " that would be deleted:")
@@ -616,7 +623,7 @@ def doAction(action, options, exclude={}, output=None):
616623
verb = "would be" if options["pretend"] else "were"
617624
# display freed space
618625
if not options["quiet"]:
619-
output.total("normal", clean_size, len(clean_me) + len(vcs), verb, action)
626+
output.total("normal", clean_size, file_count + len(vcs), verb, action)
620627
# nothing was found
621628
elif not options["quiet"]:
622629
output.einfo("Your " + action + " directory was already clean.")

pym/gentoolkit/eclean/search.py

Lines changed: 103 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from portage.dep._slot_operator import strip_slots
1919
from portage.dep.libc import find_libc_deps, strip_libc_deps
2020
from portage.exception import InvalidDependString
21+
from portage.binrepo.config import BinRepoConfigLoader
2122

2223
import gentoolkit.pprinter as pp
2324
from gentoolkit.eclean.exclude import (
@@ -659,9 +660,9 @@ def findPackages(
659660
else:
660661
installed = {}
661662

662-
# Dictionary of binary packages to clean. Organized as cpv->[pkgs] in order
663-
# to support FEATURES=binpkg-multi-instance.
664-
dead_binpkgs: dict[str, tuple[str, str | None]] = {}
663+
# Dictionary of binary packages to clean. Organized as
664+
# { location -> { cpv~build-id -> (binpkg, debugpack) } }
665+
dead_binpkgs: dict[str, dict[str, tuple[str, str | None]]] = {}
665666
keep_binpkgs = {}
666667

667668
def mk_binpkg_key(cpv):
@@ -672,91 +673,114 @@ def mk_binpkg_key(cpv):
672673
# FEATURES=pkgdir-index-trusted is now on by default which makes Portage's
673674
# invalids inaccessible
674675
settings = var_dbapi.settings
675-
bin_dbapi = portage.binarytree(pkgdir=pkgdir, settings=settings).dbapi
676-
populate_kwargs = {}
677-
if "invalid_errors" in signature(bin_dbapi.bintree.populate).parameters:
678-
populate_kwargs["invalid_errors"] = False
679-
if "force_reindex" in signature(bin_dbapi.bintree.populate).parameters:
680-
bin_dbapi.bintree.populate(force_reindex=True, **populate_kwargs)
681-
for cpv in bin_dbapi.cpv_all():
682-
cp = portage.cpv_getkey(cpv)
683-
binpkg_key = mk_binpkg_key(cpv)
684-
685-
# Exclude per --exclude-file=...
686-
if exclDictMatchCP(exclude, cp):
687-
continue
688-
689-
# Exclude if binpkg is newer than --time-limit=...
690-
if time_limit:
691-
mtime = int(bin_dbapi.aux_get(cpv, ["_mtime_"])[0])
692-
if mtime >= time_limit:
676+
677+
# Load binrepos.conf if possible, get all cache locations
678+
binrepos_conf_path = os.path.join(
679+
settings['PORTAGE_CONFIGROOT'], portage.const.BINREPOS_CONF_FILE
680+
)
681+
binrepos_conf = BinRepoConfigLoader((binrepos_conf_path,), settings)
682+
locations = {pkgdir}
683+
if binrepos_conf:
684+
# check for additional cache locations
685+
for v in binrepos_conf.values():
686+
if v.location:
687+
locations.add(v.location)
688+
689+
invalid_paths = {}
690+
for location in locations:
691+
# Initialize bintree with location
692+
bin_dbapi = portage.binarytree(pkgdir=location, settings=settings).dbapi
693+
populate_kwargs = {}
694+
if "invalid_errors" in signature(bin_dbapi.bintree.populate).parameters:
695+
populate_kwargs["invalid_errors"] = False
696+
if "force_reindex" in signature(bin_dbapi.bintree.populate).parameters:
697+
bin_dbapi.bintree.populate(force_reindex=True, **populate_kwargs)
698+
for cpv in bin_dbapi.cpv_all():
699+
cp = portage.cpv_getkey(cpv)
700+
binpkg_key = mk_binpkg_key(cpv)
701+
702+
# Exclude per --exclude-file=...
703+
if exclDictMatchCP(exclude, cp):
693704
continue
694705

695-
# Exclude if binpkg has exact same USEs
696-
if not destructive and options["unique-use"]:
697-
keys = ("CPV", "EAPI", "USE")
698-
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
699-
cpv_key = "_".join(binpkg_metadata[key] for key in keys)
700-
if cpv_key in keep_binpkgs:
701-
old_cpv = keep_binpkgs[cpv_key]
702-
# compare BUILD_TIME, keep the new one
703-
old_time = int(bin_dbapi.aux_get(old_cpv, ["BUILD_TIME"])[0])
704-
new_time = int(bin_dbapi.aux_get(cpv, ["BUILD_TIME"])[0])
705-
drop_cpv = old_cpv if new_time >= old_time else cpv
706-
707-
binpkg_key = mk_binpkg_key(drop_cpv)
708-
binpkg_path = bin_dbapi.bintree.getname(drop_cpv)
709-
debuginfo_path = _find_debuginfo_tarball(drop_cpv, cp)
710-
dead_binpkgs[binpkg_key] = (binpkg_path, debuginfo_path)
711-
712-
if new_time < old_time:
706+
# Exclude if binpkg is newer than --time-limit=...
707+
if time_limit:
708+
mtime = int(bin_dbapi.aux_get(cpv, ["_mtime_"])[0])
709+
if mtime >= time_limit:
713710
continue
714-
keep_binpkgs[cpv_key] = cpv
715711

716-
# Exclude if binpkg exists in the porttree and not --deep
717-
if not destructive and port_dbapi.cpv_exists(cpv):
718-
if not options["changed-deps"]:
719-
continue
712+
# Exclude if binpkg has exact same USEs
713+
if not destructive and options["unique-use"]:
714+
keys = ("EAPI", "USE")
715+
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
716+
cpv_key = f"{cpv}_{'_'.join(binpkg_metadata[key] for key in keys)}"
717+
if cpv_key in keep_binpkgs:
718+
old_cpv = keep_binpkgs[cpv_key]
719+
# compare BUILD_TIME, keep the new one
720+
old_time = int(bin_dbapi.aux_get(old_cpv, ["BUILD_TIME"])[0])
721+
new_time = int(bin_dbapi.aux_get(cpv, ["BUILD_TIME"])[0])
722+
drop_cpv = old_cpv if new_time >= old_time else cpv
723+
724+
binpkg_key = mk_binpkg_key(drop_cpv)
725+
binpkg_path = bin_dbapi.bintree.getname(drop_cpv)
726+
debuginfo_path = _find_debuginfo_tarball(drop_cpv, cp)
727+
dead_binpkgs.setdefault(location, {})[binpkg_key] = (binpkg_path, debuginfo_path)
728+
729+
if new_time < old_time:
730+
continue
731+
keep_binpkgs[cpv_key] = cpv
732+
733+
# Exclude if binpkg exists in the porttree and not --deep
734+
if not destructive and port_dbapi.cpv_exists(cpv):
735+
if not options["changed-deps"]:
736+
continue
720737

721-
dep_keys = ("RDEPEND", "PDEPEND")
722-
keys = ("EAPI", "USE") + dep_keys
723-
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
724-
ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys)))
725-
726-
deps_binpkg = " ".join(binpkg_metadata[key] for key in dep_keys)
727-
deps_ebuild = " ".join(ebuild_metadata[key] for key in dep_keys)
728-
if _deps_equal(
729-
deps_binpkg,
730-
binpkg_metadata["EAPI"],
731-
deps_ebuild,
732-
ebuild_metadata["EAPI"],
733-
libc_deps,
734-
frozenset(binpkg_metadata["USE"].split()),
735-
cpv,
736-
):
737-
continue
738+
dep_keys = ("RDEPEND", "PDEPEND")
739+
keys = ("EAPI", "USE") + dep_keys
740+
binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
741+
ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys)))
742+
743+
deps_binpkg = " ".join(binpkg_metadata[key] for key in dep_keys)
744+
deps_ebuild = " ".join(ebuild_metadata[key] for key in dep_keys)
745+
if _deps_equal(
746+
deps_binpkg,
747+
binpkg_metadata["EAPI"],
748+
deps_ebuild,
749+
ebuild_metadata["EAPI"],
750+
libc_deps,
751+
frozenset(binpkg_metadata["USE"].split()),
752+
cpv,
753+
):
754+
continue
738755

739-
if destructive and var_dbapi.cpv_exists(cpv):
740-
# Exclude if an instance of the package is installed due to
741-
# the --package-names option.
742-
if cp in installed and port_dbapi.cpv_exists(cpv):
743-
continue
756+
if destructive and var_dbapi.cpv_exists(cpv):
757+
# Exclude if an instance of the package is installed due to
758+
# the --package-names option.
759+
if cp in installed and port_dbapi.cpv_exists(cpv):
760+
continue
744761

745-
# Exclude if BUILD_TIME of binpkg is same as vartree
746-
buildtime = var_dbapi.aux_get(cpv, ["BUILD_TIME"])[0]
747-
if buildtime == bin_dbapi.aux_get(cpv, ["BUILD_TIME"])[0]:
748-
continue
762+
# Exclude if BUILD_TIME of binpkg is same as vartree
763+
buildtime = var_dbapi.aux_get(cpv, ["BUILD_TIME"])[0]
764+
if buildtime == bin_dbapi.aux_get(cpv, ["BUILD_TIME"])[0]:
765+
continue
749766

750-
if not destructive and options["unique-use"]:
751-
del keep_binpkgs[cpv_key]
767+
if not destructive and options["unique-use"]:
768+
del keep_binpkgs[cpv_key]
752769

753-
binpkg_path = bin_dbapi.bintree.getname(cpv)
754-
debuginfo_path = _find_debuginfo_tarball(cpv, cp)
755-
dead_binpkgs[binpkg_key] = (binpkg_path, debuginfo_path)
756-
try:
757-
invalid_paths = bin_dbapi.bintree.invalid_paths
758-
except AttributeError:
759-
invalid_paths = bin_dbapi.bintree.invalids
770+
binpkg_path = bin_dbapi.bintree.getname(cpv)
771+
debuginfo_path = _find_debuginfo_tarball(cpv, cp)
772+
dead_binpkgs.setdefault(location, {})[binpkg_key] = (binpkg_path, debuginfo_path)
773+
774+
try:
775+
for f, paths in bin_dbapi.bintree.invalid_paths.items():
776+
if f in invalid_paths:
777+
invalid_paths[f].extend(paths)
778+
else:
779+
invalid_paths[f] = paths
780+
except AttributeError:
781+
# if bintree.invalid_paths was not initialized, this is a
782+
# hard error and we can just return here
783+
return {}, bin_dbapi.bintree.invalids
760784

761785
return dead_binpkgs, invalid_paths
762786

0 commit comments

Comments
 (0)