Skip to content

Instantly share code, notes, and snippets.

@naota
Created January 30, 2021 14:16
Show Gist options
  • Save naota/fbaabdaea3b95668ad5857a0296b027e to your computer and use it in GitHub Desktop.
Save naota/fbaabdaea3b95668ad5857a0296b027e to your computer and use it in GitHub Desktop.
#!/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