aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2020-02-24 07:50:35 +0100
committerMichał Górny <mgorny@gentoo.org>2020-02-24 07:50:50 +0100
commit4a844cb64e720583b2043701e15b5cd77bcad597 (patch)
tree4b9bb41b6571b5d18074783c7e59733cd1adfac2
parentgenrdeps: Fix randomly skipping nested deps (diff)
downloadqa-scripts-4a844cb64e720583b2043701e15b5cd77bcad597.tar.gz
qa-scripts-4a844cb64e720583b2043701e15b5cd77bcad597.tar.bz2
qa-scripts-4a844cb64e720583b2043701e15b5cd77bcad597.zip
Add new genrdeps-index script using pkgcore
Signed-off-by: Michał Górny <mgorny@gentoo.org>
-rwxr-xr-xgenrdeps-index.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/genrdeps-index.py b/genrdeps-index.py
new file mode 100755
index 0000000..d0d6a31
--- /dev/null
+++ b/genrdeps-index.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# Rewrite of genrdeps-index to stop using horrible Portage API.
+# (c) 2020 Michał Górny
+# 2-clause BSD license
+
+import argparse
+import collections
+import errno
+import os
+import os.path
+import shutil
+import sys
+
+import pkgcore.config
+from pkgcore.ebuild.atom import atom
+from pkgcore.restrictions.boolean import AndRestriction, OrRestriction
+from pkgcore.restrictions.packages import Conditional
+
+
+DepTuple = collections.namedtuple('DepTuple', ('cpv', 'blocks', 'use'))
+
+
+GROUPS = (
+ ('bdepend', 'bindex'),
+ ('depend', 'dindex'),
+ ('pdepend', 'pindex'),
+ ('rdepend', 'rindex'),
+)
+
+
+def process_deps(deps, useflags=()):
+ for d in deps:
+ if isinstance(d, atom):
+ yield DepTuple(d.key, d.blocks, useflags)
+ elif isinstance(d, OrRestriction) or isinstance(d, AndRestriction):
+ # || deps and nested () blocks
+ for sd in process_deps(d, useflags):
+ yield sd
+ elif isinstance(d, Conditional):
+ # foo? deps
+ assert d.attr == 'use'
+ assert len(d.restriction.vals) == 1
+ r = next(iter(d.restriction.vals))
+ if d.restriction.negate:
+ r = '!' + r
+ for sd in process_deps(d, useflags + (r,)):
+ yield sd
+ else:
+ raise AssertionError("Unknown dep type: " + d.__class__)
+
+
+def rmtree_ignore_enoent(func, path, exc_info):
+ if not isinstance(exc_info[1], FileNotFoundError):
+ raise
+
+
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('outputdir',
+ help='Directory to create rdep index in')
+ args = argp.parse_args()
+
+ c = pkgcore.config.load_config()
+ repo = c.repo['gentoo']
+
+ rindex = {}
+ for g, gi in GROUPS:
+ rindex[g] = collections.defaultdict(set)
+
+ for p in repo:
+ for g, gi in GROUPS:
+ deps = frozenset(process_deps(getattr(p, g)))
+ for dep, blocks, flags in deps:
+ rindex[g][dep].add(DepTuple(p.cpvstr, blocks, flags))
+
+ for g, gi in GROUPS:
+ outdir = os.path.join(args.outputdir, '.' + gi + '.new')
+ shutil.rmtree(outdir, onerror=rmtree_ignore_enoent)
+
+ for p, revdeps in rindex[g].items():
+ outpath = os.path.join(outdir, p)
+ os.makedirs(os.path.dirname(outpath), exist_ok=True)
+ with open(outpath, 'w') as f:
+ for dep, blocks, flags in sorted(revdeps):
+ if blocks:
+ dep = '[B]' + dep
+ if flags:
+ dep += ':' + '+'.join(flags)
+ f.write(dep + '\n')
+
+ for g, gi in GROUPS:
+ outdir = os.path.join(args.outputdir, gi)
+ olddir = os.path.join(args.outputdir, '.' + gi + '.old')
+ newdir = os.path.join(args.outputdir, '.' + gi + '.new')
+
+ shutil.rmtree(olddir, onerror=rmtree_ignore_enoent)
+ try:
+ os.rename(outdir, olddir)
+ except FileNotFoundError as e:
+ pass
+ os.rename(newdir, outdir)
+ shutil.rmtree(olddir, onerror=rmtree_ignore_enoent)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())