emerge: replace --rebuild with finer grained opts
authorDavid James <davidjames@chromium.org>
Wed, 4 May 2011 06:32:05 +0000 (23:32 -0700)
committerZac Medico <zmedico@gentoo.org>
Wed, 4 May 2011 17:02:14 +0000 (10:02 -0700)
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
pym/_emerge/create_depgraph_params.py
pym/_emerge/depgraph.py
pym/_emerge/help.py
pym/_emerge/main.py
pym/portage/tests/resolver/test_rebuild.py

index 2e27e48e36383b08049ce0722eb67f57a59e4bb0..907bb4f184a9bdde1bb84b1bb297349d1aa7460f 100644 (file)
@@ -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
index ae7a8aed62b91ee9b920443bc6bd98fc769452cd..44dceda37d703a0dfcdd87980cd88bad41c069d2 100644 (file)
@@ -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
index b0b4b070ad428e9809116692674be5a8f20bd455..ebfbdd498a921f604f79ad28d7036ff4559daea0 100644 (file)
@@ -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.
index 35008c4ba3bf8f927178bef99540c5d0743a1eda..de50b7517e9bd0fe6069ab2924058a76e447901a 100644 (file)
@@ -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()
index 1e06ec15709862d45fa048c7c7f05fe40e7d7f8b..92db36ec40b6edbb821eb1be1836e993c87d3ee5 100644 (file)
@@ -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
index da2888c1e3098cd28edb221881115c5e6e97cb14..1f4b6ae24ce80eadd2e0b6201ad6ca7170ced96b 100644 (file)
@@ -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,