From e4297ca1075342ec89e089802cd25ae0817f3d5b Mon Sep 17 00:00:00 2001 From: David James Date: Tue, 3 May 2011 23:32:05 -0700 Subject: [PATCH] emerge: replace --rebuild with finer grained opts Replace --rebuild option with --rebuild-if-* options. --rebuild-if-new-rev [ y | n ] Rebuild packages when dependencies that are used at both build-time and run-time are built, if the dependency is not already installed with the same version and revision. --rebuild-if-new-ver [ y | n ] Rebuild packages when dependencies that are used at both build-time and run-time are built, if the dependency is not already installed with the same version. Revision numbers are ignored. --rebuild-if-unbuilt [ y | n ] Rebuild packages when dependencies that are used at both build-time and run-time are built. Change-Id: Ia50c1702bfe1b98a8d1891740e7bbb045921a905 Review URL: http://gerrit.chromium.org/gerrit/280 --- man/emerge.1 | 14 +++++- pym/_emerge/create_depgraph_params.py | 3 +- pym/_emerge/depgraph.py | 54 +++++++++++++++++++--- pym/_emerge/help.py | 24 ++++++++-- pym/_emerge/main.py | 47 ++++++++++++++++--- pym/portage/tests/resolver/test_rebuild.py | 39 ++++++++++++++-- 6 files changed, 157 insertions(+), 24 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index 2e27e48e3..907bb4f18 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -546,9 +546,19 @@ Disable the warning message that's shown prior to to be set in the \fBmake.conf\fR(5) \fBEMERGE_DEFAULT_OPTS\fR variable. .TP -.BR "\-\-rebuild [ y | n ]" +.BR "\-\-rebuild\-if\-new\-rev [ y | n ]" Rebuild packages when dependencies that are used at both build\-time and -run\-time are upgraded. +run\-time are built, if the dependency is not already installed with the +same version and revision. +.TP +.BR "\-\-rebuild\-if\-new\-ver [ y | n ]" +Rebuild packages when dependencies that are used at both build\-time and +run\-time are built, if the dependency is not already installed with the +same version. Revision numbers are ignored. +.TP +.BR "\-\-rebuild\-if\-unbuilt [ y | n ]" +Rebuild packages when dependencies that are used at both build\-time and +run\-time are built. .TP .BR "\-\-rebuilt\-binaries [ y | n ]" Replace installed packages with binary packages that have diff --git a/pym/_emerge/create_depgraph_params.py b/pym/_emerge/create_depgraph_params.py index ae7a8aed6..44dceda37 100644 --- a/pym/_emerge/create_depgraph_params.py +++ b/pym/_emerge/create_depgraph_params.py @@ -37,7 +37,8 @@ def create_depgraph_params(myopts, myaction): deep = myopts.get("--deep") if deep is not None and deep != 0: myparams["deep"] = deep - if "--complete-graph" in myopts or "--rebuild" in myopts: + if ("--complete-graph" in myopts or "--rebuild-if-new-rev" in myopts or + "--rebuild-if-new-ver" in myopts or "--rebuild-if-unbuilt" in myopts): myparams["complete"] = True if "--emptytree" in myopts: myparams["empty"] = True diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index b0b4b070a..ebfbdd498 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -30,6 +30,7 @@ from portage._sets.base import InternalPackageSet from portage.util import cmp_sort_key, writemsg, writemsg_stdout from portage.util import writemsg_level from portage.util.digraph import digraph +from portage.versions import catpkgsplit from _emerge.AtomArg import AtomArg from _emerge.Blocker import Blocker @@ -133,7 +134,9 @@ class _frozen_depgraph_config(object): atoms = ' '.join(myopts.get("--rebuild-ignore", [])).split() self.rebuild_ignore = _wildcard_set(atoms) - self.rebuild = "--rebuild" in myopts + self.rebuild_if_new_rev = "--rebuild-if-new-rev" in myopts + self.rebuild_if_new_ver = "--rebuild-if-new-ver" in myopts + self.rebuild_if_unbuilt = "--rebuild-if-unbuilt" in myopts class _depgraph_sets(object): def __init__(self): @@ -153,19 +156,53 @@ class _rebuild_config(object): self.rebuild_list = backtrack_parameters.rebuild_list.copy() self.orig_rebuild_list = self.rebuild_list.copy() self.reinstall_list = backtrack_parameters.reinstall_list.copy() + self.rebuild_if_new_rev = frozen_config.rebuild_if_new_rev + self.rebuild_if_new_ver = frozen_config.rebuild_if_new_ver + self.rebuild_if_unbuilt = frozen_config.rebuild_if_unbuilt + self.rebuild = (self.rebuild_if_new_rev or self.rebuild_if_new_ver or + self.rebuild_if_unbuilt) def add(self, dep_pkg, dep): parent = dep.collapsed_parent priority = dep.collapsed_priority rebuild_exclude = self._frozen_config.rebuild_exclude rebuild_ignore = self._frozen_config.rebuild_ignore - if (self._frozen_config.rebuild and isinstance(parent, Package) and + if (self.rebuild and isinstance(parent, Package) and parent.built and (priority.buildtime or priority.runtime) and isinstance(dep_pkg, Package) and not rebuild_exclude.findAtomForPackage(parent) and not rebuild_ignore.findAtomForPackage(dep_pkg)): self._graph.add(dep_pkg, parent, priority) + def _needs_rebuild(self, dep_pkg): + """Check whether packages that depend on dep_pkg need to be rebuilt.""" + dep_root_slot = (dep_pkg.root, dep_pkg.slot_atom) + if dep_pkg.built or dep_root_slot in self.orig_rebuild_list: + return False + + if self.rebuild_if_unbuilt: + # dep_pkg is being installed from source, so binary + # packages for parents are invalid. Force rebuild + return True + + trees = self._frozen_config.trees + vardb = trees[dep_pkg.root]["vartree"].dbapi + if self.rebuild_if_new_rev: + # Parent packages are valid if a package with the same + # cpv is already installed. + return dep_pkg.cpv not in vardb.match(dep_pkg.slot_atom) + + # Otherwise, parent packages are valid if a package with the same + # version (excluding revision) is already installed. + assert self.rebuild_if_new_ver + cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1] + for inst_cpv in vardb.match(dep_pkg.slot_atom): + inst_cpv_norev = catpkgsplit(inst_cpv)[:-1] + if inst_cpv_norev == cpv_norev: + return False + + return True + def _trigger_rebuild(self, parent, build_deps, runtime_deps): root_slot = (parent.root, parent.slot_atom) if root_slot in self.rebuild_list: @@ -177,10 +214,7 @@ class _rebuild_config(object): kids = set([build_deps[slot_atom], runtime_deps[slot_atom]]) for dep_pkg in kids: dep_root_slot = (dep_pkg.root, slot_atom) - if (not dep_pkg.built and - dep_root_slot not in self.orig_rebuild_list): - # There's no binary package for dep_pkg, so any binary - # package for this parent would be invalid. Force rebuild. + if self._needs_rebuild(dep_pkg): self.rebuild_list.add(root_slot) return True elif ("--usepkg" in self._frozen_config.myopts and @@ -205,7 +239,13 @@ class _rebuild_config(object): uri = bintree.get_pkgindex_uri(parent.cpv) dep_uri = bintree.get_pkgindex_uri(dep_pkg.cpv) bindb = bintree.dbapi - + if self.rebuild_if_new_ver and uri and uri != dep_uri: + cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1] + for cpv in bindb.match(dep_pkg.slot_atom): + if cpv_norev == catpkgsplit(cpv)[:-1]: + dep_uri = bintree.get_pkgindex_uri(cpv) + if uri == dep_uri: + break if uri and uri != dep_uri: # 1) Remote binary package is invalid because it was # built without dep_pkg. Force rebuild. diff --git a/pym/_emerge/help.py b/pym/_emerge/help.py index 35008c4ba..de50b7517 100644 --- a/pym/_emerge/help.py +++ b/pym/_emerge/help.py @@ -629,10 +629,28 @@ def help(myopts, havecolor=1): for line in wrap(desc, desc_width): print(desc_indent + line) print() - print(" " + green("--rebuild") + " [ %s | %s ]" % \ + print(" " + green("--rebuild-if-new-rev") + " [ %s | %s ]" % \ (turquoise("y"), turquoise("n"))) - desc = "Rebuild packages when dependencies that are used " + \ - "at both build-time and run-time are upgraded." + desc = "Rebuild packages when dependencies that are " + \ + "used at both build-time and run-time are built, " + \ + "if the dependency is not already installed with the " + \ + "same version and revision." + for line in wrap(desc, desc_width): + print(desc_indent + line) + print() + print(" " + green("--rebuild-if-new-ver") + " [ %s | %s ]" % \ + (turquoise("y"), turquoise("n"))) + desc = "Rebuild packages when dependencies that are " + \ + "used at both build-time and run-time are built, " + \ + "if the dependency is not already installed with the " + \ + "same version. Revision numbers are ignored." + for line in wrap(desc, desc_width): + print(desc_indent + line) + print() + print(" " + green("--rebuild-if-unbuilt") + " [ %s | %s ]" % \ + (turquoise("y"), turquoise("n"))) + desc = "Rebuild packages when dependencies that are " + \ + "used at both build-time and run-time are built." for line in wrap(desc, desc_width): print(desc_indent + line) print() diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py index 1e06ec157..92db36ec4 100644 --- a/pym/_emerge/main.py +++ b/pym/_emerge/main.py @@ -440,7 +440,9 @@ def insert_optional_args(args): '--package-moves' : y_or_n, '--quiet' : y_or_n, '--quiet-build' : y_or_n, - '--rebuild' : y_or_n, + '--rebuild-if-new-rev' : y_or_n, + '--rebuild-if-new-ver' : y_or_n, + '--rebuild-if-unbuilt' : y_or_n, '--rebuilt-binaries' : y_or_n, '--root-deps' : ('rdeps',), '--select' : y_or_n, @@ -777,9 +779,27 @@ def parse_opts(tmpcmdline, silent=False): "choices" : true_y_or_n }, - "--rebuild": { + "--rebuild-if-new-rev": { "help" : "Rebuild packages when dependencies that are " + \ - "used at both build-time and run-time are upgraded.", + "used at both build-time and run-time are built, " + \ + "if the dependency is not already installed with the " + \ + "same version and revision.", + "type" : "choice", + "choices" : true_y_or_n + }, + + "--rebuild-if-new-ver": { + "help" : "Rebuild packages when dependencies that are " + \ + "used at both build-time and run-time are built, " + \ + "if the dependency is not already installed with the " + \ + "same version. Revision numbers are ignored.", + "type" : "choice", + "choices" : true_y_or_n + }, + + "--rebuild-if-unbuilt": { + "help" : "Rebuild packages when dependencies that are " + \ + "used at both build-time and run-time are built.", "type" : "choice", "choices" : true_y_or_n }, @@ -913,7 +933,7 @@ def parse_opts(tmpcmdline, silent=False): else: myoptions.binpkg_respect_use = None - if myoptions.complete_graph in true_y or myoptions.rebuild in true_y: + if myoptions.complete_graph in true_y: myoptions.complete_graph = True else: myoptions.complete_graph = None @@ -989,10 +1009,23 @@ def parse_opts(tmpcmdline, silent=False): else: myoptions.quiet_build = None - if myoptions.rebuild in true_y: - myoptions.rebuild = True + if myoptions.rebuild_if_new_ver in true_y: + myoptions.rebuild_if_new_ver = True + else: + myoptions.rebuild_if_new_ver = None + + if myoptions.rebuild_if_new_rev in true_y: + myoptions.rebuild_if_new_rev = True + myoptions.rebuild_if_new_ver = None + else: + myoptions.rebuild_if_new_rev = None + + if myoptions.rebuild_if_unbuilt in true_y: + myoptions.rebuild_if_unbuilt = True + myoptions.rebuild_if_new_rev = None + myoptions.rebuild_if_new_ver = None else: - myoptions.rebuild = None + myoptions.rebuild_if_unbuilt = None if myoptions.rebuilt_binaries in true_y: myoptions.rebuilt_binaries = True diff --git a/pym/portage/tests/resolver/test_rebuild.py b/pym/portage/tests/resolver/test_rebuild.py index da2888c1e..1f4b6ae24 100644 --- a/pym/portage/tests/resolver/test_rebuild.py +++ b/pym/portage/tests/resolver/test_rebuild.py @@ -15,6 +15,7 @@ class RebuildTestCase(TestCase): ebuilds = { "sys-libs/x-1": { }, + "sys-libs/x-1-r1": { }, "sys-libs/x-2": { }, "sys-apps/a-1": { "DEPEND" : "sys-libs/x", "RDEPEND" : "sys-libs/x"}, "sys-apps/a-2": { "DEPEND" : "sys-libs/x", "RDEPEND" : "sys-libs/x"}, @@ -48,7 +49,7 @@ class RebuildTestCase(TestCase): test_cases = ( ResolverPlaygroundTestCase( ["sys-libs/x"], - options = {"--rebuild" : True, + options = {"--rebuild-if-unbuilt" : True, "--rebuild-exclude" : ["sys-apps/b"]}, mergelist = ['sys-libs/x-2', 'sys-apps/a-2', 'sys-apps/e-2'], ignore_mergelist_order = True, @@ -56,7 +57,7 @@ class RebuildTestCase(TestCase): ResolverPlaygroundTestCase( ["sys-libs/x"], - options = {"--rebuild" : True}, + options = {"--rebuild-if-unbuilt" : True}, mergelist = ['sys-libs/x-2', 'sys-apps/a-2', 'sys-apps/b-2', 'sys-apps/e-2', 'sys-apps/g-2'], ignore_mergelist_order = True, @@ -64,7 +65,7 @@ class RebuildTestCase(TestCase): ResolverPlaygroundTestCase( ["sys-libs/x"], - options = {"--rebuild" : True, + options = {"--rebuild-if-unbuilt" : True, "--rebuild-ignore" : ["sys-libs/x"]}, mergelist = ['sys-libs/x-2'], ignore_mergelist_order = True, @@ -72,13 +73,43 @@ class RebuildTestCase(TestCase): ResolverPlaygroundTestCase( ["sys-libs/x"], - options = {"--rebuild" : True, + options = {"--rebuild-if-unbuilt" : True, "--rebuild-ignore" : ["sys-apps/b"]}, mergelist = ['sys-libs/x-2', 'sys-apps/a-2', 'sys-apps/b-2', 'sys-apps/e-2'], ignore_mergelist_order = True, success = True), + ResolverPlaygroundTestCase( + ["=sys-libs/x-1-r1"], + options = {"--rebuild-if-unbuilt" : True}, + mergelist = ['sys-libs/x-1-r1', 'sys-apps/a-2', + 'sys-apps/b-2', 'sys-apps/e-2', 'sys-apps/g-2'], + ignore_mergelist_order = True, + success = True), + + ResolverPlaygroundTestCase( + ["=sys-libs/x-1-r1"], + options = {"--rebuild-if-new-rev" : True}, + mergelist = ['sys-libs/x-1-r1', 'sys-apps/a-2', + 'sys-apps/b-2', 'sys-apps/e-2', 'sys-apps/g-2'], + ignore_mergelist_order = True, + success = True), + + ResolverPlaygroundTestCase( + ["=sys-libs/x-1-r1"], + options = {"--rebuild-if-new-ver" : True}, + mergelist = ['sys-libs/x-1-r1'], + ignore_mergelist_order = True, + success = True), + + ResolverPlaygroundTestCase( + ["sys-libs/x"], + options = {"--rebuild-if-new-ver" : True}, + mergelist = ['sys-libs/x-2', 'sys-apps/a-2', + 'sys-apps/b-2', 'sys-apps/e-2', 'sys-apps/g-2'], + ignore_mergelist_order = True, + success = True), ) playground = ResolverPlayground(ebuilds=ebuilds, -- 2.26.2