Created
January 30, 2021 14:16
-
-
Save naota/fbaabdaea3b95668ad5857a0296b027e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
import argparse | |
import os.path | |
from portage.dep import paren_reduce | |
from gentoolkit.atom import Atom | |
from gentoolkit.dependencies import Dependencies | |
from gentoolkit.flag import get_flags | |
from gentoolkit.query import Query | |
def myparser(deps, use_conditional=[], depth=0): | |
result = [] | |
if depth == 0: | |
deps = paren_reduce(deps) | |
for tok in deps: | |
if tok == '||': | |
continue | |
if tok[-1] == '?': | |
use_conditional.append((tok[:-1], depth)) | |
continue | |
if isinstance(tok, list): | |
sub_r = myparser(tok, use_conditional, depth=depth+1) | |
result.extend(sub_r) | |
if use_conditional and use_conditional[-1][1] == depth: | |
use_conditional.pop() | |
continue | |
if tok[0] == '!': | |
# We're not interested in blockers | |
continue | |
# skip it if it's empty | |
if tok and tok != '': | |
atom = Atom(tok) | |
conds = [x for (x, i) in use_conditional] | |
if conds: | |
atom.use_conditional = ' '.join(conds) | |
result.append(atom) | |
else: | |
sys.exit(1) | |
return result | |
def dump_deps(rootpkg, tgt_python): | |
python_uses = frozenset(["python_single_target_%s" % tgt_python, "python_targets_%s" % tgt_python]) | |
use_file = open("/etc/portage/package.use/"+tgt_python, mode="a") | |
pkg = Query(rootpkg).find_best() | |
enabled = [] | |
iuse = get_flags(pkg.cpv) | |
for u in python_uses: | |
if u in iuse: | |
enabled.append(u) | |
tovisit = [(rootpkg, frozenset(enabled))] | |
finished = set() | |
use_printed = set() | |
while tovisit: | |
patom, myuse = tovisit.pop(0) | |
if patom in finished: | |
continue | |
finished.add(patom) | |
pkg = Query(patom).find_best() | |
iuse, final_use = get_flags(pkg.cpv, final_setting=True) | |
iuse = frozenset(iuse) | |
final_use = set(final_use) | (myuse & iuse) | |
depuse = [] | |
enabled = [] | |
for u in python_uses & final_use: | |
if u == "python_single_target_%s" % tgt_python: | |
depuse.append("PYTHON_SINGLE_TARGET: %s" % tgt_python) | |
if u == "python_targets_%s" % tgt_python: | |
depuse.append("PYTHON_TARGETS: %s" % tgt_python) | |
if not depuse: | |
continue | |
if pkg.cp not in use_printed: | |
print("%s %s" % (pkg.cp, ' '.join(depuse)), file=use_file) | |
use_printed.add(pkg.cp) | |
deps = Dependencies(pkg.cpv, parser=myparser) | |
for d in deps.get_all_depends(): | |
if d.use_conditional is None: | |
will_depend = True | |
elif frozenset(d.use_conditional.split()) <= final_use: | |
will_depend = True | |
else: | |
will_depend = False | |
#print("%s -> %s %s" % (pkg, d.use_conditional, d)) | |
if not will_depend: | |
continue | |
if d.use is None: | |
enabled = frozenset() | |
else: | |
enabled = set(d.use.enabled) | |
if d.use.conditional: | |
enabled |= d.use.conditional.enabled | |
enabled = frozenset(enabled) | |
tovisit.append((d.atom, enabled)) | |
print("", file=use_file) | |
use_file.close() | |
def best_use(prefix, iuse): | |
xs = [u[len(prefix):] for u in iuse if u.startswith(prefix)] | |
if "pypy3" in xs: | |
xs.remove("pypy3") | |
if not xs: | |
return None | |
xs.sort() | |
return xs[-1] | |
def target_variant(pname): | |
single_prefix = "python_single_target_" | |
multi_prefix = "python_targets_" | |
pkg = Query(pname).find_best() | |
if pkg is None: | |
return None | |
iuse = get_flags(pkg.cpv) | |
best_single = best_use(single_prefix, iuse) | |
best_multi = best_use(multi_prefix, iuse) | |
if best_single and best_multi and best_single != best_multi: | |
print("SINGLE %s vs MULTI %s" % (best_single, best_multi)) | |
sys.exit(1) | |
return best_single or best_multi | |
def collect_group_packages(groups): | |
dir = "/etc/portage/sets/gm" | |
res = [] | |
for x in groups: | |
with open(os.path.join(dir, x)) as f: | |
res.extend(f.readlines()) | |
return res | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("-s", "--single", required=True) | |
parser.add_argument("-m", "--multi", required=True) | |
parser.add_argument("-g", "--groups", default="") | |
parser.add_argument("-e", "--extras", default="") | |
args = parser.parse_args() | |
single = args.single | |
multi = args.multi | |
groups = args.groups.split() | |
extras = args.extras.split() | |
pkgs = collect_group_packages(groups) | |
pkgs.extend(extras) | |
for p in pkgs: | |
tgt = target_variant(p) | |
if not tgt: | |
continue | |
if tgt != single: | |
dump_deps(p, tgt) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment