1 |
Author: grobian |
2 |
Date: 2008-07-01 16:48:46 +0000 (Tue, 01 Jul 2008) |
3 |
New Revision: 10876 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/NEWS |
7 |
main/branches/prefix/man/emerge.1 |
8 |
main/branches/prefix/pym/_emerge/__init__.py |
9 |
main/branches/prefix/pym/_emerge/help.py |
10 |
Log: |
11 |
Merged from trunk 10816:10824 |
12 |
|
13 |
| 10817 | Generate and log eerror messages for any packages that need | |
14 |
| zmedico | to be dropped due to unsatisfied dependencies when | |
15 |
| | --keep-going is enabled. | |
16 |
|
17 |
| 10818 | Add documentation for the new --keep-going option. | |
18 |
| zmedico | | |
19 |
|
20 |
| 10819 | Fix typo. | |
21 |
| zmedico | | |
22 |
|
23 |
| 10820 | Pass the digraph into the MergeTask constructor. It's | |
24 |
| zmedico | currently unused but it will be useful for parallel | |
25 |
| | scheduling. | |
26 |
|
27 |
| 10821 | Break references from Package instances in the digraph | |
28 |
| zmedico | before passing it into the MergeTask constructor. | |
29 |
|
30 |
| 10822 | Remove the MergeTask._blocker_db attribute since it can just | |
31 |
| zmedico | be a local variable. | |
32 |
|
33 |
| 10823 | Fix depgraph.break_refs() to work with DependencyArg | |
34 |
| zmedico | instances (or anything else that may have a "root_config" | |
35 |
| | attribute). | |
36 |
|
37 |
| 10824 | Bug #226307 - Copy come code from | |
38 |
| zmedico | depgraph._iter_atoms_for_pkg() that was used to solve bug | |
39 |
| | #218854, and use it inside unmerge() when matching sets to | |
40 |
| | packages. | |
41 |
|
42 |
|
43 |
Modified: main/branches/prefix/NEWS |
44 |
=================================================================== |
45 |
--- main/branches/prefix/NEWS 2008-07-01 12:55:49 UTC (rev 10875) |
46 |
+++ main/branches/prefix/NEWS 2008-07-01 16:48:46 UTC (rev 10876) |
47 |
@@ -3,6 +3,11 @@ |
48 |
portage-2.2 |
49 |
------------- |
50 |
|
51 |
+* Add emerge --keep-going option to continue as much as possible after |
52 |
+ an error. When an error occurs, dependencies are recalculated for |
53 |
+ remaining packages and any with unsatisfied dependencies are |
54 |
+ automatically dropped. The --skipfirst option automatically drops |
55 |
+ packages in the same way, and also drops any masked packages. |
56 |
* Add subversion support for repoman. |
57 |
* It is now possible to use `emerge <file>` to reinstall the package that |
58 |
installed a particular file. Package contents entries are indexed to |
59 |
|
60 |
Modified: main/branches/prefix/man/emerge.1 |
61 |
=================================================================== |
62 |
--- main/branches/prefix/man/emerge.1 2008-07-01 12:55:49 UTC (rev 10875) |
63 |
+++ main/branches/prefix/man/emerge.1 2008-07-01 16:48:46 UTC (rev 10876) |
64 |
@@ -321,6 +321,12 @@ |
65 |
.BR "\-\-ignore-default-opts" |
66 |
Causes \fIEMERGE_DEFAULT_OPTS\fR (see \fBmake.conf\fR(5)) to be ignored. |
67 |
.TP |
68 |
+.BR "\-\-keep\-going" |
69 |
+Continue as much as possible after an error. When an error occurs, |
70 |
+dependencies are recalculated for remaining packages and any with |
71 |
+unsatisfied dependencies are automatically dropped. Also see |
72 |
+the related \fB\-\-skipfirst\fR option. |
73 |
+.TP |
74 |
.BR "\-\-newuse " (\fB\-N\fR) |
75 |
Tells emerge to include installed packages where USE flags have changed since |
76 |
compilation. USE flag changes include: |
77 |
@@ -399,9 +405,10 @@ |
78 |
.TP |
79 |
.BR "\-\-skipfirst" |
80 |
This option is only valid when used with \fB\-\-resume\fR. It removes the |
81 |
-first package in the resume list so that a merge may continue in the presence |
82 |
-of an uncorrectable or inconsequential error. This should only be used in |
83 |
-cases where skipping the package will not result in failed dependencies. |
84 |
+first package in the resume list. Dependencies are recalculated for |
85 |
+remaining packages and any that have unsatisfied dependencies or are |
86 |
+masked will be automatically dropped. Also see the related |
87 |
+\fB\-\-keep\-going\fR option. |
88 |
.TP |
89 |
.BR "\-\-tree " (\fB\-t\fR) |
90 |
Shows the dependency tree for the given target by indenting dependencies. |
91 |
|
92 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
93 |
=================================================================== |
94 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-07-01 12:55:49 UTC (rev 10875) |
95 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-07-01 16:48:46 UTC (rev 10876) |
96 |
@@ -67,6 +67,7 @@ |
97 |
import portage.exception |
98 |
from portage.const import EPREFIX, BPREFIX |
99 |
from portage.data import secpass |
100 |
+from portage.elog.messages import eerror |
101 |
from portage.util import normalize_path as normpath |
102 |
from portage.util import writemsg |
103 |
from portage.sets import load_default_config, SETPREFIX |
104 |
@@ -3892,26 +3893,24 @@ |
105 |
retlist.reverse() |
106 |
return retlist |
107 |
|
108 |
- def break_refs(self, mergelist): |
109 |
+ def break_refs(self, nodes): |
110 |
""" |
111 |
Take a mergelist like that returned from self.altlist() and |
112 |
break any references that lead back to the depgraph. This is |
113 |
useful if you want to hold references to packages without |
114 |
also holding the depgraph on the heap. |
115 |
""" |
116 |
- for node in mergelist: |
117 |
- if not isinstance(node, Package): |
118 |
- continue |
119 |
+ for node in nodes: |
120 |
+ if hasattr(node, "root_config"): |
121 |
+ # The FakeVartree references the _package_cache which |
122 |
+ # references the depgraph. So that Package instances don't |
123 |
+ # hold the depgraph and FakeVartree on the heap, replace |
124 |
+ # the RootConfig that references the FakeVartree with the |
125 |
+ # original RootConfig instance which references the actual |
126 |
+ # vartree. |
127 |
+ node.root_config = \ |
128 |
+ self._trees_orig[node.root_config.root]["root_config"] |
129 |
|
130 |
- # The FakeVartree references the _package_cache which |
131 |
- # references the depgraph. So that Package instances don't |
132 |
- # hold the depgraph and FakeVartree on the heap, replace |
133 |
- # the RootConfig that references the FakeVartree with the |
134 |
- # original RootConfig instance which references the actual |
135 |
- # vartree. |
136 |
- node.root_config = \ |
137 |
- self._trees_orig[node.root]["root_config"] |
138 |
- |
139 |
def _resolve_conflicts(self): |
140 |
if not self._complete_graph(): |
141 |
raise self._unknown_internal_error() |
142 |
@@ -5914,7 +5913,7 @@ |
143 |
"--nodeps", "--pretend"]) |
144 |
|
145 |
def __init__(self, settings, trees, mtimedb, myopts, |
146 |
- spinner, mergelist, favorites): |
147 |
+ spinner, mergelist, favorites, digraph): |
148 |
self.settings = settings |
149 |
self.target_root = settings["ROOT"] |
150 |
self.trees = trees |
151 |
@@ -5927,11 +5926,9 @@ |
152 |
if settings.get("PORTAGE_DEBUG", "") == "1": |
153 |
self.edebug = 1 |
154 |
self.pkgsettings = {} |
155 |
- self._blocker_db = {} |
156 |
for root in trees: |
157 |
self.pkgsettings[root] = portage.config( |
158 |
clone=trees[root]["vartree"].settings) |
159 |
- self._blocker_db[root] = BlockerDB(trees[root]["root_config"]) |
160 |
self.curval = 0 |
161 |
self._spawned_pids = [] |
162 |
|
163 |
@@ -5954,10 +5951,11 @@ |
164 |
import gc |
165 |
gc.collect() |
166 |
|
167 |
+ blocker_db = BlockerDB(self.trees[new_pkg.root]["root_config"]) |
168 |
+ |
169 |
blocker_dblinks = [] |
170 |
- for blocking_pkg in self._blocker_db[ |
171 |
- new_pkg.root].findInstalledBlockers(new_pkg, |
172 |
- acquire_lock=acquire_lock): |
173 |
+ for blocking_pkg in blocker_db.findInstalledBlockers( |
174 |
+ new_pkg, acquire_lock=acquire_lock): |
175 |
if new_pkg.slot_atom == blocking_pkg.slot_atom: |
176 |
continue |
177 |
if new_pkg.cpv == blocking_pkg.cpv: |
178 |
@@ -5999,15 +5997,40 @@ |
179 |
break |
180 |
if mergelist[0][-1] != "merge": |
181 |
break |
182 |
+ |
183 |
# Skip the first one because it failed to build or install. |
184 |
+ pkg_key = tuple(mergelist[0]) |
185 |
del mergelist[0] |
186 |
+ failed_pkg = None |
187 |
+ for task in self._mergelist: |
188 |
+ if task == pkg_key: |
189 |
+ failed_pkg = task |
190 |
+ break |
191 |
+ if failed_pkg is None: |
192 |
+ break |
193 |
if not mergelist: |
194 |
break |
195 |
- mylist = self._calc_resume_list() |
196 |
+ |
197 |
+ mylist, dropped_tasks = self._calc_resume_list() |
198 |
clear_caches(self.trees) |
199 |
if not mylist: |
200 |
break |
201 |
- self.curval += 1 |
202 |
+ |
203 |
+ if dropped_tasks: |
204 |
+ |
205 |
+ def _eerror(lines): |
206 |
+ for l in lines: |
207 |
+ eerror(l, phase="other", key=failed_pkg.cpv) |
208 |
+ |
209 |
+ msg = [] |
210 |
+ msg.append("One or more packages have been " + \ |
211 |
+ "dropped due to unsatisfied dependencies:") |
212 |
+ msg.append("") |
213 |
+ msg.extend(" " + str(task) for task in dropped_tasks) |
214 |
+ msg.append("") |
215 |
+ _eerror(msg) |
216 |
+ del _eerror, msg |
217 |
+ del dropped_tasks |
218 |
self._mergelist = mylist |
219 |
|
220 |
return rval |
221 |
@@ -6035,20 +6058,12 @@ |
222 |
|
223 |
if not success: |
224 |
mydepgraph.display_problems() |
225 |
- return None |
226 |
+ return (None, None) |
227 |
|
228 |
- if dropped_tasks: |
229 |
- portage.writemsg("!!! One or more packages have been " + \ |
230 |
- "dropped due to\n" + \ |
231 |
- "!!! masking or unsatisfied dependencies:\n\n", |
232 |
- noiselevel=-1) |
233 |
- for task in dropped_tasks: |
234 |
- portage.writemsg(" " + str(task) + "\n", noiselevel=-1) |
235 |
- portage.writemsg("\n", noiselevel=-1) |
236 |
- |
237 |
mylist = mydepgraph.altlist() |
238 |
mydepgraph.break_refs(mylist) |
239 |
- return mylist |
240 |
+ mydepgraph.break_refs(dropped_tasks) |
241 |
+ return (mylist, dropped_tasks) |
242 |
|
243 |
def _poll_child_processes(self): |
244 |
""" |
245 |
@@ -6562,6 +6577,19 @@ |
246 |
global_unmerge=0 |
247 |
xterm_titles = "notitles" not in settings.features |
248 |
|
249 |
+ pkg_cache = {} |
250 |
+ |
251 |
+ def _pkg(cpv): |
252 |
+ pkg = pkg_cache.get(cpv) |
253 |
+ if pkg is None: |
254 |
+ pkg = Package(cpv=cpv, installed=True, |
255 |
+ metadata=izip(Package.metadata_keys, |
256 |
+ vartree.dbapi.aux_get(cpv, Package.metadata_keys)), |
257 |
+ root_config=root_config, |
258 |
+ type_name="installed") |
259 |
+ pkg_cache[cpv] = pkg |
260 |
+ return pkg |
261 |
+ |
262 |
vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH) |
263 |
try: |
264 |
# At least the parent needs to exist for the lock file. |
265 |
@@ -6804,6 +6832,12 @@ |
266 |
# relevant package sets. |
267 |
for cp in xrange(len(pkgmap)): |
268 |
for cpv in pkgmap[cp]["selected"].copy(): |
269 |
+ try: |
270 |
+ pkg = _pkg(cpv) |
271 |
+ except KeyError: |
272 |
+ # It could have been uninstalled |
273 |
+ # by a concurrent process. |
274 |
+ continue |
275 |
parents = [] |
276 |
for s in installed_sets: |
277 |
# skip sets that the user requested to unmerge, and skip world |
278 |
@@ -6814,9 +6848,34 @@ |
279 |
# only check instances of EditablePackageSet as other classes are generally used for |
280 |
# special purposes and can be ignored here (and are usually generated dynamically, so the |
281 |
# user can't do much about them anyway) |
282 |
- elif sets[s].containsCPV(cpv) \ |
283 |
- and isinstance(sets[s], EditablePackageSet): |
284 |
- parents.append(s) |
285 |
+ if isinstance(sets[s], EditablePackageSet): |
286 |
+ |
287 |
+ # This is derived from a snippet of code in the |
288 |
+ # depgraph._iter_atoms_for_pkg() method. |
289 |
+ for atom in sets[s].iterAtomsForPackage(pkg): |
290 |
+ inst_matches = vartree.dbapi.match(atom) |
291 |
+ inst_matches.reverse() # descending order |
292 |
+ higher_slot = None |
293 |
+ for inst_cpv in inst_matches: |
294 |
+ try: |
295 |
+ inst_pkg = _pkg(inst_cpv) |
296 |
+ except KeyError: |
297 |
+ # It could have been uninstalled |
298 |
+ # by a concurrent process. |
299 |
+ continue |
300 |
+ |
301 |
+ if inst_pkg.cp != atom.cp: |
302 |
+ continue |
303 |
+ if pkg >= inst_pkg: |
304 |
+ # This is descending order, and we're not |
305 |
+ # interested in any versions <= pkg given. |
306 |
+ break |
307 |
+ if pkg.slot_atom != inst_pkg.slot_atom: |
308 |
+ higher_slot = inst_pkg |
309 |
+ break |
310 |
+ if higher_slot is None: |
311 |
+ parents.append(s) |
312 |
+ break |
313 |
if parents: |
314 |
#print colorize("WARN", "Package %s is going to be unmerged," % cpv) |
315 |
#print colorize("WARN", "but still listed in the following package sets:") |
316 |
@@ -8981,11 +9040,12 @@ |
317 |
time.sleep(3) # allow the parent to have first fetch |
318 |
mymergelist = mydepgraph.altlist() |
319 |
mydepgraph.break_refs(mymergelist) |
320 |
+ mydepgraph.break_refs(mydepgraph.digraph.order) |
321 |
+ mergetask = MergeTask(settings, trees, mtimedb, myopts, |
322 |
+ spinner, mymergelist, favorites, mydepgraph.digraph) |
323 |
del mydepgraph |
324 |
clear_caches(trees) |
325 |
|
326 |
- mergetask = MergeTask(settings, trees, mtimedb, myopts, |
327 |
- spinner, mymergelist, favorites) |
328 |
retval = mergetask.merge() |
329 |
merge_count = mergetask.curval |
330 |
else: |
331 |
@@ -9027,11 +9087,12 @@ |
332 |
pkglist = mydepgraph.altlist() |
333 |
mydepgraph.saveNomergeFavorites() |
334 |
mydepgraph.break_refs(pkglist) |
335 |
+ mydepgraph.break_refs(mydepgraph.digraph.order) |
336 |
+ mergetask = MergeTask(settings, trees, mtimedb, myopts, |
337 |
+ spinner, pkglist, favorites, mydepgraph.digraph) |
338 |
del mydepgraph |
339 |
clear_caches(trees) |
340 |
|
341 |
- mergetask = MergeTask(settings, trees, mtimedb, myopts, |
342 |
- spinner, pkglist, favorites) |
343 |
retval = mergetask.merge() |
344 |
merge_count = mergetask.curval |
345 |
|
346 |
|
347 |
Modified: main/branches/prefix/pym/_emerge/help.py |
348 |
=================================================================== |
349 |
--- main/branches/prefix/pym/_emerge/help.py 2008-07-01 12:55:49 UTC (rev 10875) |
350 |
+++ main/branches/prefix/pym/_emerge/help.py 2008-07-01 16:48:46 UTC (rev 10876) |
351 |
@@ -15,8 +15,8 @@ |
352 |
print " "+turquoise("emerge")+" "+turquoise("--resume")+" [ "+green("--pretend")+" | "+green("--ask")+" | "+green("--skipfirst")+" ]" |
353 |
print " "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("world")+" | "+green("--sync")+" ] " |
354 |
print bold("Options:")+" "+green("-")+"["+green("abBcCdDefgGhkKlnNoOpqPsStuvV")+"]" |
355 |
- print " [ "+green("--columns")+" ] [ "+green("--deep")+" ] [ "+green("--newuse")+" ]" |
356 |
- print " [ "+green("--noconfmem")+" ] [ "+green("--nospinner")+" ] [ "+green("--oneshot")+" ]" |
357 |
+ print " [ "+green("--columns")+" ] [ "+green("--deep")+" ] [ "+green("--keep-going")+" ] [ "+green("--newuse")+" ]" |
358 |
+ print " [ "+green("--noconfmem")+" ] [ "+green("--nospinner")+" ] [ "+green("--oneshot")+" ]" |
359 |
print " [ " + green("--color")+" < " + turquoise("y") + " | "+ turquoise("n")+" > ] [ "+green("--complete-graph")+" ]" |
360 |
print " [ "+green("--reinstall ")+turquoise("changed-use")+" ] [ " + green("--with-bdeps")+" < " + turquoise("y") + " | "+ turquoise("n")+" > ]" |
361 |
print bold("Actions:")+" [ "+green("--clean")+" | "+green("--depclean")+" | "+green("--prune")+" | "+green("--regen")+" | "+green("--search")+" | "+green("--unmerge")+" ]" |
362 |
@@ -292,6 +292,17 @@ |
363 |
print " downloaded from the remote server without consulting packages" |
364 |
print " existing in the packages directory." |
365 |
print |
366 |
+ print " "+green("--keep-going") |
367 |
+ desc = "Continue as much as possible after " + \ |
368 |
+ "an error. When an error occurs, " + \ |
369 |
+ "dependencies are recalculated for " + \ |
370 |
+ "remaining packages and any with " + \ |
371 |
+ "unsatisfied dependencies are " + \ |
372 |
+ "automatically dropped. Also see " + \ |
373 |
+ "the related --skipfirst option." |
374 |
+ for line in wrap(desc, desc_width): |
375 |
+ print desc_indent + line |
376 |
+ print |
377 |
print " "+green("--newuse")+" ("+green("-N")+" short option)" |
378 |
print " Tells emerge to include installed packages where USE flags have " |
379 |
print " changed since installation." |
380 |
@@ -349,11 +360,17 @@ |
381 |
print " enabled are added or removed." |
382 |
print |
383 |
print " "+green("--skipfirst") |
384 |
- print " This option is only valid in a resume situation. It removes the" |
385 |
- print " first package in the resume list so that a merge may continue in" |
386 |
- print " the presence of an uncorrectable or inconsequential error. This" |
387 |
- print " should only be used in cases where skipping the package will not" |
388 |
- print " result in failed dependencies." |
389 |
+ desc = "This option is only valid when " + \ |
390 |
+ "used with --resume. It removes the " + \ |
391 |
+ "first package in the resume list. " + \ |
392 |
+ "Dependencies are recalculated for " + \ |
393 |
+ "remaining packages and any that " + \ |
394 |
+ "have unsatisfied dependencies or are " + \ |
395 |
+ "masked will be automatically dropped. " + \ |
396 |
+ "Also see the related " + \ |
397 |
+ "--keep-going option." |
398 |
+ for line in wrap(desc, desc_width): |
399 |
+ print desc_indent + line |
400 |
print |
401 |
print " "+green("--tree")+" ("+green("-t")+" short option)" |
402 |
print " Shows the dependency tree using indentation for dependencies." |
403 |
|
404 |
-- |
405 |
gentoo-commits@l.g.o mailing list |