Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r12713 - main/trunk/pym/_emerge
Date: Thu, 26 Feb 2009 04:26:11
Message-Id: E1LcXp2-0002be-My@stork.gentoo.org
1 Author: zmedico
2 Date: 2009-02-26 04:26:07 +0000 (Thu, 26 Feb 2009)
3 New Revision: 12713
4
5 Modified:
6 main/trunk/pym/_emerge/__init__.py
7 Log:
8 Bug #259954 - Do not spawn parallel build when the system is in a fragile
9 state due to a system package having an unsatisfied runtime dependency
10 (such as sys-libs/pam having an unsatisfied PDEPEND on sys-auth/pambase).
11
12
13 Modified: main/trunk/pym/_emerge/__init__.py
14 ===================================================================
15 --- main/trunk/pym/_emerge/__init__.py 2009-02-26 04:03:10 UTC (rev 12712)
16 +++ main/trunk/pym/_emerge/__init__.py 2009-02-26 04:26:07 UTC (rev 12713)
17 @@ -1819,8 +1819,8 @@
18 """
19 Start an asynchronous task and then return as soon as possible.
20 """
21 + self._start_hook()
22 self._start()
23 - self._start_hook()
24
25 def _start(self):
26 raise NotImplementedError(self)
27 @@ -10020,6 +10020,13 @@
28 # when no other packages are building.
29 self._deep_system_deps = set()
30
31 + # Holds packages to merge which will satisfy currently unsatisfied
32 + # deep runtime dependencies of system packages. If this is not empty
33 + # then no parallel builds will be spawned until it is empty. This
34 + # minimizes the possibility that a build will fail due to the system
35 + # being in a fragile state. For example, see bug #259954.
36 + self._unsatisfied_system_deps = set()
37 +
38 self._status_display = JobStatusDisplay()
39 self._max_load = myopts.get("--load-average")
40 max_jobs = myopts.get("--jobs")
41 @@ -10768,6 +10775,59 @@
42 elif isinstance(pkg, Blocker):
43 pass
44
45 + def _system_merge_started(self, merge):
46 + """
47 + Add any unsatisfied runtime deps to self._unsatisfied_system_deps.
48 + """
49 + graph = self._digraph
50 + if graph is None:
51 + return
52 + pkg = merge.merge.pkg
53 + completed_tasks = self._completed_tasks
54 + unsatisfied = self._unsatisfied_system_deps
55 +
56 + def ignore_non_runtime(priority):
57 + """
58 + Ignore non-runtime priorities
59 + """
60 + if isinstance(priority, DepPriority) and \
61 + (priority.runtime or priority.runtime_post):
62 + return False
63 + return True
64 +
65 + def ignore_satisfied_runtime(priority):
66 + """
67 + Ignore non-runtime and satisfied runtime priorities.
68 + """
69 + if isinstance(priority, DepPriority) and \
70 + not priority.satisfied and \
71 + (priority.runtime or priority.runtime_post):
72 + return False
73 + return True
74 +
75 + traversed = set()
76 + dep_stack = [pkg]
77 + while dep_stack:
78 + node = dep_stack.pop()
79 + if node in traversed:
80 + continue
81 + traversed.add(node)
82 +
83 + unsatisfied_runtime = set(graph.child_nodes(node,
84 + ignore_priority=ignore_satisfied_runtime))
85 + for child in graph.child_nodes(node,
86 + ignore_priority=ignore_non_runtime):
87 + if not isinstance(child, Package) or \
88 + child.operation == 'uninstall':
89 + continue
90 + if child is pkg:
91 + continue
92 + dep_stack.append(child)
93 + if child.operation == 'merge' and \
94 + child not in completed_tasks and \
95 + child in unsatisfied_runtime:
96 + unsatisfied.add(child)
97 +
98 def _merge_wait_exit_handler(self, task):
99 self._merge_wait_scheduled.remove(task)
100 self._merge_exit(task)
101 @@ -10829,6 +10889,7 @@
102 # Since dependencies on system packages are frequently
103 # unspecified, merge them only when no builds are executing.
104 self._merge_wait_queue.append(merge)
105 + merge.addStartListener(self._system_merge_started)
106 else:
107 merge.addExitListener(self._merge_exit)
108 self._task_queues.merge.add(merge)
109 @@ -10855,6 +10916,7 @@
110
111 def _task_complete(self, pkg):
112 self._completed_tasks.add(pkg)
113 + self._unsatisfied_system_deps.discard(pkg)
114 self._choose_pkg_return_early = False
115
116 def _merge(self):
117 @@ -10882,6 +10944,7 @@
118 del self._pkg_queue[:]
119 self._completed_tasks.clear()
120 self._deep_system_deps.clear()
121 + self._unsatisfied_system_deps.clear()
122 self._choose_pkg_return_early = False
123 self._status_display.reset()
124 self._digraph = None
125 @@ -11076,6 +11139,7 @@
126
127 if self._choose_pkg_return_early or \
128 self._merge_wait_scheduled or \
129 + (self._jobs and self._unsatisfied_system_deps) or \
130 not self._can_add_job() or \
131 self._job_delay():
132 return bool(state_change)