summaryrefslogtreecommitdiffstats
path: root/pym/_emerge
diff options
context:
space:
mode:
authorDavid James <davidjames@chromium.org>2011-08-22 16:29:13 -0700
committerZac Medico <zmedico@gentoo.org>2011-08-26 11:05:01 -0700
commit2f253bcc364bd75c9b103133a17ea9887a3de15d (patch)
tree7186b4673f0630b6154f576b6a415cc0a92ba5d2 /pym/_emerge
parent1dc7ac4b48ca0a5a8b607bbadf759fa209b49e9c (diff)
downloadportage-2f253bcc364bd75c9b103133a17ea9887a3de15d.tar.gz
portage-2f253bcc364bd75c9b103133a17ea9887a3de15d.tar.bz2
portage-2f253bcc364bd75c9b103133a17ea9887a3de15d.zip
Update --rebuild-if-* flags to rebuild when build dependencies are changed.
Right now, the --rebuild-if-* flags only rebuild packages that are used at both run-time and build-time. This doesn't help for packages that are used only at build-time (for example, static libaries). Rebuilding packages whenever a build-time dependency is changed is easier to understand and explain, and it handles all cases correctly. BUG=chromium-os:15517 TEST=Run emerge test suite. Change-Id: Iae8dab24e8acb6625bc1a0ce41862e90b232eb84
Diffstat (limited to 'pym/_emerge')
-rw-r--r--pym/_emerge/depgraph.py150
-rw-r--r--pym/_emerge/help.py18
2 files changed, 69 insertions, 99 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 8b6125d84..42cc659df 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -174,7 +174,7 @@ class _rebuild_config(object):
rebuild_exclude = self._frozen_config.rebuild_exclude
rebuild_ignore = self._frozen_config.rebuild_ignore
if (self.rebuild and isinstance(parent, Package) and
- parent.built and (priority.buildtime or priority.runtime) and
+ parent.built and priority.buildtime and
isinstance(dep_pkg, Package) and
not rebuild_exclude.findAtomForPackage(parent) and
not rebuild_ignore.findAtomForPackage(dep_pkg)):
@@ -209,66 +209,63 @@ class _rebuild_config(object):
return True
- def _trigger_rebuild(self, parent, build_deps, runtime_deps):
+ def _trigger_rebuild(self, parent, build_deps):
root_slot = (parent.root, parent.slot_atom)
if root_slot in self.rebuild_list:
return False
trees = self._frozen_config.trees
- children = set(build_deps).intersection(runtime_deps)
reinstall = False
- for slot_atom in children:
- kids = set([build_deps[slot_atom], runtime_deps[slot_atom]])
- for dep_pkg in kids:
- dep_root_slot = (dep_pkg.root, slot_atom)
- if self._needs_rebuild(dep_pkg):
+ for slot_atom, dep_pkg in build_deps.items():
+ dep_root_slot = (dep_pkg.root, slot_atom)
+ if self._needs_rebuild(dep_pkg):
+ self.rebuild_list.add(root_slot)
+ return True
+ elif ("--usepkg" in self._frozen_config.myopts and
+ (dep_root_slot in self.reinstall_list or
+ dep_root_slot in self.rebuild_list or
+ not dep_pkg.installed)):
+
+ # A direct rebuild dependency is being installed. We
+ # should update the parent as well to the latest binary,
+ # if that binary is valid.
+ #
+ # To validate the binary, we check whether all of the
+ # rebuild dependencies are present on the same binhost.
+ #
+ # 1) If parent is present on the binhost, but one of its
+ # rebuild dependencies is not, then the parent should
+ # be rebuilt from source.
+ # 2) Otherwise, the parent binary is assumed to be valid,
+ # because all of its rebuild dependencies are
+ # consistent.
+ bintree = trees[parent.root]["bintree"]
+ 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.
self.rebuild_list.add(root_slot)
return True
- elif ("--usepkg" in self._frozen_config.myopts and
- (dep_root_slot in self.reinstall_list or
- dep_root_slot in self.rebuild_list or
- not dep_pkg.installed)):
-
- # A direct rebuild dependency is being installed. We
- # should update the parent as well to the latest binary,
- # if that binary is valid.
- #
- # To validate the binary, we check whether all of the
- # rebuild dependencies are present on the same binhost.
- #
- # 1) If parent is present on the binhost, but one of its
- # rebuild dependencies is not, then the parent should
- # be rebuilt from source.
- # 2) Otherwise, the parent binary is assumed to be valid,
- # because all of its rebuild dependencies are
- # consistent.
- bintree = trees[parent.root]["bintree"]
- 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.
- self.rebuild_list.add(root_slot)
- return True
- elif (parent.installed and
- root_slot not in self.reinstall_list):
- inst_build_time = parent.metadata.get("BUILD_TIME")
- try:
- bin_build_time, = bindb.aux_get(parent.cpv,
- ["BUILD_TIME"])
- except KeyError:
- continue
- if bin_build_time != inst_build_time:
- # 2) Remote binary package is valid, and local package
- # is not up to date. Force reinstall.
- reinstall = True
+ elif (parent.installed and
+ root_slot not in self.reinstall_list):
+ inst_build_time = parent.metadata.get("BUILD_TIME")
+ try:
+ bin_build_time, = bindb.aux_get(parent.cpv,
+ ["BUILD_TIME"])
+ except KeyError:
+ continue
+ if bin_build_time != inst_build_time:
+ # 2) Remote binary package is valid, and local package
+ # is not up to date. Force reinstall.
+ reinstall = True
if reinstall:
self.reinstall_list.add(root_slot)
return reinstall
@@ -282,31 +279,15 @@ class _rebuild_config(object):
need_restart = False
graph = self._graph
build_deps = {}
- runtime_deps = {}
- leaf_nodes = deque(graph.leaf_nodes())
-
- def ignore_non_runtime(priority):
- return not priority.runtime
- def ignore_non_buildtime(priority):
- return not priority.buildtime
+ leaf_nodes = deque(graph.leaf_nodes())
# Trigger rebuilds bottom-up (starting with the leaves) so that parents
# will always know which children are being rebuilt.
while graph:
if not leaf_nodes:
- # We're interested in intersection of buildtime and runtime,
- # so ignore edges that do not contain both.
- leaf_nodes.extend(graph.leaf_nodes(
- ignore_priority=ignore_non_runtime))
- if not leaf_nodes:
- leaf_nodes.extend(graph.leaf_nodes(
- ignore_priority=ignore_non_buildtime))
- if not leaf_nodes:
- # We'll have to drop an edge that is both
- # buildtime and runtime. This should be
- # quite rare.
- leaf_nodes.append(graph.order[-1])
+ # We'll have to drop an edge. This should be quite rare.
+ leaf_nodes.append(graph.order[-1])
node = leaf_nodes.popleft()
if node not in graph:
@@ -315,32 +296,23 @@ class _rebuild_config(object):
slot_atom = node.slot_atom
# Remove our leaf node from the graph, keeping track of deps.
- parents = graph.nodes[node][1].items()
+ parents = graph.parent_nodes(node)
graph.remove(node)
node_build_deps = build_deps.get(node, {})
- node_runtime_deps = runtime_deps.get(node, {})
- for parent, priorities in parents:
+ for parent in parents:
if parent == node:
# Ignore a direct cycle.
continue
parent_bdeps = build_deps.setdefault(parent, {})
- parent_rdeps = runtime_deps.setdefault(parent, {})
- for priority in priorities:
- if priority.buildtime:
- parent_bdeps[slot_atom] = node
- if priority.runtime:
- parent_rdeps[slot_atom] = node
- if slot_atom in parent_bdeps and slot_atom in parent_rdeps:
- parent_rdeps.update(node_runtime_deps)
+ parent_bdeps[slot_atom] = node
if not graph.child_nodes(parent):
leaf_nodes.append(parent)
# Trigger rebuilds for our leaf node. Because all of our children
- # have been processed, build_deps and runtime_deps will be
- # completely filled in, and self.rebuild_list / self.reinstall_list
- # will tell us whether any of our children need to be rebuilt or
- # reinstalled.
- if self._trigger_rebuild(node, node_build_deps, node_runtime_deps):
+ # have been processed, the build_deps will be completely filled in,
+ # and self.rebuild_list / self.reinstall_list will tell us whether
+ # any of our children need to be rebuilt or reinstalled.
+ if self._trigger_rebuild(node, node_build_deps):
need_restart = True
return need_restart
diff --git a/pym/_emerge/help.py b/pym/_emerge/help.py
index c978ce255..57b376d55 100644
--- a/pym/_emerge/help.py
+++ b/pym/_emerge/help.py
@@ -641,26 +641,24 @@ def help(myopts, havecolor=1):
print()
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 built, " + \
- "if the dependency is not already installed with the " + \
- "same version and revision."
+ desc = "Rebuild packages when build-time dependencies are built " + \
+ "from source, 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."
+ desc = "Rebuild packages when build-time dependencies are built " + \
+ "from source, 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."
+ desc = "Rebuild packages when build-time dependencies are built " + \
+ "from source"
for line in wrap(desc, desc_width):
print(desc_indent + line)
print()