1 |
Author: grobian |
2 |
Date: 2008-10-15 20:33:21 +0000 (Wed, 15 Oct 2008) |
3 |
New Revision: 11694 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/bin/ebuild.sh |
7 |
main/branches/prefix/bin/repoman |
8 |
main/branches/prefix/pym/_emerge/__init__.py |
9 |
main/branches/prefix/pym/portage/__init__.py |
10 |
main/branches/prefix/pym/portage/dbapi/bintree.py |
11 |
main/branches/prefix/pym/portage/dbapi/porttree.py |
12 |
main/branches/prefix/pym/portage/dbapi/vartree.py |
13 |
main/branches/prefix/pym/portage/elog/__init__.py |
14 |
Log: |
15 |
Merged from trunk -r11675:11692 |
16 |
|
17 |
| 11676 | Bug #241204 - Fix dbapi.invalidentry() calls inside | |
18 |
| zmedico | vardbapi.cpv_all() to correctly join the path via | |
19 |
| | self.getpath(). | |
20 |
|
21 |
| 11677 | When warning about package categories that haven't been | |
22 |
| zmedico | configured via /etc/portage/categories, join the path with | |
23 |
| | PORTAGE_CONFIGROOT. Thanks to Ned Ludd <solar@g.o> for | |
24 |
| | reporting. | |
25 |
|
26 |
| 11678 | In EbuildFetcher._start(), in order to ensure that a new log | |
27 |
| zmedico | is created when appropriate, clean up PORTAGE_BUILDDIR if | |
28 |
| | appropriate. | |
29 |
|
30 |
| 11679 | Make the Scheduler class treat failed fetches the same as | |
31 |
| zmedico | other failed packages, and don't bail out due to a failure | |
32 |
| | when in --fetchonly mode. This fixes an issue with | |
33 |
| | --fetchonly bailing out instead of continuing to fetch. | |
34 |
|
35 |
| 11680 | Buge #241100 - Make EbuildFetcher use a pty when | |
36 |
| zmedico | appropriate, so that fetcher progress bars, like wget has, | |
37 |
| | will work properly. | |
38 |
|
39 |
| 11681 | Remove the prefetch logic in EbuildFetcher._pipe() since | |
40 |
| zmedico | prefetchers are always in the background anyway. | |
41 |
|
42 |
| 11682 | Now that only prefetch (parallel-fetch) output goes to the | |
43 |
| zmedico | global fetch log, update code to remove inappropriate | |
44 |
| | references to this log. | |
45 |
|
46 |
| 11683 | Inside fetch(), don't call pkg_nofetch when in | |
47 |
| zmedico | parallel-fetch mode since it will get call again later | |
48 |
| | anyway. | |
49 |
|
50 |
| 11684 | Add an explicit note about bug #239560 in the relevant code. | |
51 |
| zmedico | | |
52 |
|
53 |
| 11685 | Bug #241118 - Re-enable pkg_nofetch for emerge --pretend | |
54 |
| zmedico | --fetch, but direct output to stderr. This requires | |
55 |
| | PORTAGE_BUILDDIR locking for bug #239560 and also for elog | |
56 |
| | message storage. | |
57 |
|
58 |
| 11686 | Bug #234301 - When fetch fails, include the path of the log | |
59 |
| zmedico | file in the eerror message that's generated. This way it's | |
60 |
| | easy for the user to find the output from the fetcher or | |
61 |
| | from the pkg_nofetch phase. | |
62 |
|
63 |
| 11687 | Don't return from fetch() due to fetch restriction when in | |
64 |
| zmedico | "listonly" mode. | |
65 |
|
66 |
| 11688 | Make fetch() fetch as many files as possible, even if some | |
67 |
| zmedico | fail, when in fetchonly mode. | |
68 |
|
69 |
| 11689 | Make sure the pkg_nofetch phase is only called once when in | |
70 |
| zmedico | fetchonly mode. | |
71 |
|
72 |
| 11690 | When emerge --keep-going bails due to missing dependencies, | |
73 |
| zmedico | show the error message after the mod_echo output since | |
74 |
| | otherwise the mod_echo output can sweep the error message | |
75 |
| | out of view. Thanks to Donnie Berkholz <dberkholz@g.o> for | |
76 |
| | reporting. | |
77 |
|
78 |
| 11691 | Bug #241366 - Only suggest to run `emaint --check world` | |
79 |
| zmedico | when the atom is a direct member of the world set (rather | |
80 |
| | than from a nested set). | |
81 |
|
82 |
| 11692 | Bug #229033 - When a Manifest is added automatically by | |
83 |
| zmedico | repoman, it's in the "mynew" list, so move manifest paths | |
84 |
| | from that list to the "mymanifests" list when necessary. | |
85 |
|
86 |
|
87 |
Modified: main/branches/prefix/bin/ebuild.sh |
88 |
=================================================================== |
89 |
--- main/branches/prefix/bin/ebuild.sh 2008-10-15 19:39:42 UTC (rev 11693) |
90 |
+++ main/branches/prefix/bin/ebuild.sh 2008-10-15 20:33:21 UTC (rev 11694) |
91 |
@@ -272,7 +272,9 @@ |
92 |
export EBUILD_DEATH_HOOKS="${EBUILD_DEATH_HOOKS} $*" |
93 |
} |
94 |
|
95 |
-# Ensure that $PWD is sane whenever possible. |
96 |
+# Ensure that $PWD is sane whenever possible, to protect against |
97 |
+# exploitation of insecure search path for python -c in ebuilds. |
98 |
+# See bug #239560. |
99 |
if ! hasq "$EBUILD_PHASE" clean depend help ; then |
100 |
cd "$PORTAGE_BUILDDIR" || \ |
101 |
die "PORTAGE_BUILDDIR does not exist: '$PORTAGE_BUILDDIR'" |
102 |
|
103 |
Modified: main/branches/prefix/bin/repoman |
104 |
=================================================================== |
105 |
--- main/branches/prefix/bin/repoman 2008-10-15 19:39:42 UTC (rev 11693) |
106 |
+++ main/branches/prefix/bin/repoman 2008-10-15 20:33:21 UTC (rev 11694) |
107 |
@@ -1738,8 +1738,23 @@ |
108 |
|
109 |
# Manifests need to be regenerated after all other commits, so don't commit |
110 |
# them now even if they have changed. |
111 |
- mymanifests = [f for f in mychanged if "Manifest" == os.path.basename(f)] |
112 |
- mychanged = [f for f in mychanged if "Manifest" != os.path.basename(f)] |
113 |
+ mymanifests = set() |
114 |
+ changed_set = set() |
115 |
+ new_set = set() |
116 |
+ for f in mychanged: |
117 |
+ if "Manifest" == os.path.basename(f): |
118 |
+ mymanifests.add(f) |
119 |
+ else: |
120 |
+ changed_set.add(f) |
121 |
+ for f in mynew: |
122 |
+ if "Manifest" == os.path.basename(f): |
123 |
+ mymanifests.add(f) |
124 |
+ else: |
125 |
+ new_set.add(f) |
126 |
+ mychanged = list(changed_set) |
127 |
+ mynew = list(new_set) |
128 |
+ mymanifests = list(mymanifests) |
129 |
+ del changed_set, new_set |
130 |
myupdates = mychanged + mynew |
131 |
myheaders = [] |
132 |
mydirty = [] |
133 |
|
134 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
135 |
=================================================================== |
136 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-10-15 19:39:42 UTC (rev 11693) |
137 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-10-15 20:33:21 UTC (rev 11694) |
138 |
@@ -1615,6 +1615,13 @@ |
139 |
__slots__ = ("fetch_all", "pkg", "settings") |
140 |
|
141 |
def execute(self): |
142 |
+ # To spawn pkg_nofetch requires PORTAGE_BUILDDIR for |
143 |
+ # ensuring sane $PWD (bug #239560) and storing elog |
144 |
+ # messages. |
145 |
+ build_dir = EbuildBuildDir(pkg=self.pkg, settings=self.settings) |
146 |
+ build_dir.lock() |
147 |
+ build_dir.clean() |
148 |
+ portage.prepare_build_dirs(self.pkg.root, self.settings, 0) |
149 |
portdb = self.pkg.root_config.trees["porttree"].dbapi |
150 |
ebuild_path = portdb.findname(self.pkg.cpv) |
151 |
debug = self.settings.get("PORTAGE_DEBUG") == "1" |
152 |
@@ -1623,6 +1630,10 @@ |
153 |
self.settings["ROOT"], self.settings, debug=debug, |
154 |
listonly=1, fetchonly=1, fetchall=self.fetch_all, |
155 |
mydbapi=portdb, tree="porttree") |
156 |
+ |
157 |
+ portage.elog.elog_process(self.pkg.cpv, self.settings) |
158 |
+ build_dir.clean() |
159 |
+ build_dir.unlock() |
160 |
return retval |
161 |
|
162 |
class AsynchronousTask(SlotObject): |
163 |
@@ -2275,6 +2286,8 @@ |
164 |
settings = self.config_pool.allocate() |
165 |
self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings) |
166 |
self._build_dir.lock() |
167 |
+ self._build_dir.clean() |
168 |
+ portage.prepare_build_dirs(self.pkg.root, self._build_dir.settings, 0) |
169 |
if self.logfile is None: |
170 |
self.logfile = settings.get("PORTAGE_LOG_FILE") |
171 |
|
172 |
@@ -2304,6 +2317,18 @@ |
173 |
self.env = fetch_env |
174 |
SpawnProcess._start(self) |
175 |
|
176 |
+ def _pipe(self, fd_pipes): |
177 |
+ """When appropriate, use a pty so that fetcher progress bars, |
178 |
+ like wget has, will work properly.""" |
179 |
+ if self.background or not sys.stdout.isatty(): |
180 |
+ # When the output only goes to a log file, |
181 |
+ # there's no point in creating a pty. |
182 |
+ return os.pipe() |
183 |
+ stdout_pipe = fd_pipes.get(1) |
184 |
+ got_pty, master_fd, slave_fd = \ |
185 |
+ portage._create_pty_or_pipe(copy_term_size=stdout_pipe) |
186 |
+ return (master_fd, slave_fd) |
187 |
+ |
188 |
def _set_returncode(self, wait_retval): |
189 |
SpawnProcess._set_returncode(self, wait_retval) |
190 |
# Collect elog messages that might have been |
191 |
@@ -2315,21 +2340,20 @@ |
192 |
if self.logfile is not None: |
193 |
if self.background: |
194 |
elog_out = open(self.logfile, 'a') |
195 |
- eerror("Fetch failed for '%s'" % self.pkg.cpv, |
196 |
- phase="unpack", key=self.pkg.cpv, out=elog_out) |
197 |
+ msg = "Fetch failed for '%s'" % (self.pkg.cpv,) |
198 |
+ if self.logfile is not None: |
199 |
+ msg += ", Log file:" |
200 |
+ eerror(msg, phase="unpack", key=self.pkg.cpv, out=elog_out) |
201 |
+ if self.logfile is not None: |
202 |
+ eerror(" '%s'" % (self.logfile,), |
203 |
+ phase="unpack", key=self.pkg.cpv, out=elog_out) |
204 |
if elog_out is not None: |
205 |
elog_out.close() |
206 |
if not self.prefetch: |
207 |
portage.elog.elog_process(self.pkg.cpv, self._build_dir.settings) |
208 |
features = self._build_dir.settings.features |
209 |
- if (self.fetchonly or self.returncode == os.EX_OK) and \ |
210 |
- not ("keepwork" in features or "keeptemp" in features): |
211 |
- try: |
212 |
- shutil.rmtree(self._build_dir.settings["PORTAGE_BUILDDIR"]) |
213 |
- except EnvironmentError, e: |
214 |
- if e.errno != errno.ENOENT: |
215 |
- raise |
216 |
- del e |
217 |
+ if self.returncode == os.EX_OK: |
218 |
+ self._build_dir.clean() |
219 |
self._build_dir.unlock() |
220 |
self.config_pool.deallocate(self._build_dir.settings) |
221 |
self._build_dir = None |
222 |
@@ -2365,7 +2389,6 @@ |
223 |
portage.doebuild_environment(ebuild_path, "setup", root_config.root, |
224 |
self.settings, debug, use_cache, portdb) |
225 |
dir_path = self.settings["PORTAGE_BUILDDIR"] |
226 |
- portage.prepare_build_dirs(self.pkg.root, self.settings, 0) |
227 |
|
228 |
catdir = os.path.dirname(dir_path) |
229 |
self._catdir = catdir |
230 |
@@ -2385,6 +2408,19 @@ |
231 |
if catdir_lock is not None: |
232 |
portage.locks.unlockdir(catdir_lock) |
233 |
|
234 |
+ def clean(self): |
235 |
+ """Uses shutil.rmtree() rather than spawning a 'clean' phase. Disabled |
236 |
+ by keepwork or keeptemp in FEATURES.""" |
237 |
+ settings = self.settings |
238 |
+ features = settings.features |
239 |
+ if not ("keepwork" in features or "keeptemp" in features): |
240 |
+ try: |
241 |
+ shutil.rmtree(settings["PORTAGE_BUILDDIR"]) |
242 |
+ except EnvironmentError, e: |
243 |
+ if e.errno != errno.ENOENT: |
244 |
+ raise |
245 |
+ del e |
246 |
+ |
247 |
def unlock(self): |
248 |
if self._lock_obj is None: |
249 |
return |
250 |
@@ -3504,7 +3540,7 @@ |
251 |
|
252 |
__slots__ = ("args_set", |
253 |
"binpkg_opts", "build_opts", "config_pool", "emerge_opts", |
254 |
- "failed_fetches", "find_blockers", "logger", "mtimedb", "pkg", |
255 |
+ "find_blockers", "logger", "mtimedb", "pkg", |
256 |
"pkg_count", "pkg_to_replace", "prefetcher", |
257 |
"settings", "statusMessage", "world_atom") + \ |
258 |
("_install_task",) |
259 |
@@ -3564,7 +3600,7 @@ |
260 |
settings=settings, world_atom=world_atom) |
261 |
|
262 |
self._install_task = build |
263 |
- self._start_task(build, self._ebuild_exit) |
264 |
+ self._start_task(build, self._default_final_exit) |
265 |
return |
266 |
|
267 |
elif pkg.type_name == "binary": |
268 |
@@ -3580,12 +3616,6 @@ |
269 |
self._start_task(binpkg, self._default_final_exit) |
270 |
return |
271 |
|
272 |
- def _ebuild_exit(self, build): |
273 |
- if self._final_exit(build) != os.EX_OK: |
274 |
- if self.build_opts.fetchonly: |
275 |
- self.failed_fetches.append(self.pkg.cpv) |
276 |
- self.wait() |
277 |
- |
278 |
def _poll(self): |
279 |
self._install_task.poll() |
280 |
return self.returncode |
281 |
@@ -3598,7 +3628,6 @@ |
282 |
|
283 |
pkg = self.pkg |
284 |
build_opts = self.build_opts |
285 |
- failed_fetches = self.failed_fetches |
286 |
find_blockers = self.find_blockers |
287 |
logger = self.logger |
288 |
mtimedb = self.mtimedb |
289 |
@@ -7567,8 +7596,11 @@ |
290 |
if self._missing_args: |
291 |
world_problems = False |
292 |
if "world" in self._sets: |
293 |
+ # Filter out indirect members of world (from nested sets) |
294 |
+ # since only direct members of world are desired here. |
295 |
+ world_set = self.roots[self.target_root].sets["world"] |
296 |
for arg, atom in self._missing_args: |
297 |
- if arg.name == "world": |
298 |
+ if arg.name == "world" and atom in world_set: |
299 |
world_problems = True |
300 |
break |
301 |
|
302 |
@@ -9022,8 +9054,7 @@ |
303 |
emergelog(self.xterm_titles, *pargs, **kwargs) |
304 |
|
305 |
class _failed_pkg(SlotObject): |
306 |
- __slots__ = ("build_dir", "build_log", |
307 |
- "fetch_log", "pkg", "returncode") |
308 |
+ __slots__ = ("build_dir", "build_log", "pkg", "returncode") |
309 |
|
310 |
class _ConfigPool(object): |
311 |
"""Interface for a task to temporarily allocate a config |
312 |
@@ -9116,7 +9147,7 @@ |
313 |
self._failed_pkgs = [] |
314 |
self._failed_pkgs_all = [] |
315 |
self._failed_pkgs_die_msgs = [] |
316 |
- self._failed_fetches = [] |
317 |
+ self._post_mod_echo_msgs = [] |
318 |
self._parallel_fetch = False |
319 |
merge_count = len([x for x in mergelist \ |
320 |
if isinstance(x, Package) and x.operation == "merge"]) |
321 |
@@ -9156,7 +9187,7 @@ |
322 |
elif len(mergelist) > 1: |
323 |
self._parallel_fetch = True |
324 |
|
325 |
- if background or self._parallel_fetch: |
326 |
+ if self._parallel_fetch: |
327 |
# clear out existing fetch log if it exists |
328 |
try: |
329 |
open(self._fetch_log, 'w') |
330 |
@@ -9475,34 +9506,6 @@ |
331 |
|
332 |
return prefetcher |
333 |
|
334 |
- def _show_failed_fetches(self): |
335 |
- failed_fetches = self._failed_fetches |
336 |
- if not failed_fetches or not \ |
337 |
- ("--fetchonly" in self.myopts or \ |
338 |
- "--fetch-all-uri" in self.myopts): |
339 |
- return |
340 |
- |
341 |
- if self._background: |
342 |
- msg = "Some fetch errors were " + \ |
343 |
- "encountered. Please see %s for details." % \ |
344 |
- self._fetch_log |
345 |
- else: |
346 |
- msg = "Some fetch errors were " + \ |
347 |
- "encountered. Please see above for details." |
348 |
- |
349 |
- prefix = bad(" * ") |
350 |
- msg = "".join("%s%s\n" % (prefix, line) \ |
351 |
- for line in textwrap.wrap(msg, 70)) |
352 |
- writemsg_level(msg, level=logging.ERROR, noiselevel=-1) |
353 |
- |
354 |
- msg = [] |
355 |
- msg.append("") |
356 |
- for cpv in failed_fetches: |
357 |
- msg.append(" %s" % cpv) |
358 |
- msg.append("") |
359 |
- writemsg_level("".join("%s%s\n" % (prefix, line) \ |
360 |
- for line in msg), level=logging.ERROR, noiselevel=-1) |
361 |
- |
362 |
def _is_restart_scheduled(self): |
363 |
""" |
364 |
Check if the merge list contains a replacement |
365 |
@@ -9602,15 +9605,13 @@ |
366 |
return rval |
367 |
|
368 |
keep_going = "--keep-going" in self.myopts |
369 |
+ fetchonly = self._build_opts.fetchonly |
370 |
mtimedb = self._mtimedb |
371 |
failed_pkgs = self._failed_pkgs |
372 |
|
373 |
while True: |
374 |
rval = self._merge() |
375 |
- self._show_failed_fetches() |
376 |
- del self._failed_fetches[:] |
377 |
- |
378 |
- if rval == os.EX_OK or not keep_going: |
379 |
+ if rval == os.EX_OK or fetchonly or not keep_going: |
380 |
break |
381 |
if "resume" not in mtimedb: |
382 |
break |
383 |
@@ -9630,29 +9631,13 @@ |
384 |
if not mergelist: |
385 |
break |
386 |
|
387 |
- dropped_tasks = self._calc_resume_list() |
388 |
- if dropped_tasks is None: |
389 |
+ if not self._calc_resume_list(): |
390 |
break |
391 |
|
392 |
clear_caches(self.trees) |
393 |
if not self._mergelist: |
394 |
break |
395 |
|
396 |
- if dropped_tasks: |
397 |
- |
398 |
- def _eerror(lines): |
399 |
- for l in lines: |
400 |
- eerror(l, phase="other", key=failed_pkg.pkg.cpv) |
401 |
- |
402 |
- msg = [] |
403 |
- msg.append("One or more packages have been " + \ |
404 |
- "dropped due to unsatisfied dependencies:") |
405 |
- msg.append("") |
406 |
- msg.extend(" " + str(task) for task in dropped_tasks) |
407 |
- msg.append("") |
408 |
- _eerror(msg) |
409 |
- del _eerror, msg |
410 |
- del dropped_tasks |
411 |
self._save_resume_list() |
412 |
self._pkg_count.curval = 0 |
413 |
self._pkg_count.maxval = len([x for x in self._mergelist \ |
414 |
@@ -9691,10 +9676,15 @@ |
415 |
log_file.close() |
416 |
failure_log_shown = True |
417 |
|
418 |
+ # Dump mod_echo output now since it tends to flood the terminal. |
419 |
+ # This allows us to avoid having more important output, generated |
420 |
+ # later, from being swept away by the mod_echo output. |
421 |
+ mod_echo_output = _flush_elog_mod_echo() |
422 |
+ |
423 |
if background and not failure_log_shown and \ |
424 |
self._failed_pkgs_all and \ |
425 |
self._failed_pkgs_die_msgs and \ |
426 |
- not _flush_elog_mod_echo(): |
427 |
+ not mod_echo_output: |
428 |
|
429 |
printer = portage.output.EOutput() |
430 |
for mysettings, key, logentries in self._failed_pkgs_die_msgs: |
431 |
@@ -9714,8 +9704,11 @@ |
432 |
for line in msgcontent: |
433 |
printer.eerror(line.strip("\n")) |
434 |
|
435 |
+ if self._post_mod_echo_msgs: |
436 |
+ for msg in self._post_mod_echo_msgs: |
437 |
+ msg() |
438 |
+ |
439 |
if len(self._failed_pkgs_all) > 1: |
440 |
- _flush_elog_mod_echo() |
441 |
msg = "The following packages have " + \ |
442 |
"failed to build or install:" |
443 |
prefix = bad(" * ") |
444 |
@@ -9745,9 +9738,6 @@ |
445 |
|
446 |
log_paths = [failed_pkg.build_log] |
447 |
|
448 |
- if not (build_dir and os.path.isdir(build_dir)): |
449 |
- log_paths.append(failed_pkg.fetch_log) |
450 |
- |
451 |
for log_path in log_paths: |
452 |
if not log_path: |
453 |
continue |
454 |
@@ -9787,11 +9777,10 @@ |
455 |
settings = merge.merge.settings |
456 |
build_dir = settings.get("PORTAGE_BUILDDIR") |
457 |
build_log = settings.get("PORTAGE_LOG_FILE") |
458 |
- fetch_log = self._fetch_log |
459 |
|
460 |
self._failed_pkgs.append(self._failed_pkg( |
461 |
build_dir=build_dir, build_log=build_log, |
462 |
- fetch_log=fetch_log, pkg=pkg, |
463 |
+ pkg=pkg, |
464 |
returncode=merge.returncode)) |
465 |
self._failed_pkg_msg(self._failed_pkgs[-1], "install", "to") |
466 |
|
467 |
@@ -9831,12 +9820,11 @@ |
468 |
else: |
469 |
settings = build.settings |
470 |
build_dir = settings.get("PORTAGE_BUILDDIR") |
471 |
- fetch_log = self._fetch_log |
472 |
build_log = settings.get("PORTAGE_LOG_FILE") |
473 |
|
474 |
self._failed_pkgs.append(self._failed_pkg( |
475 |
build_dir=build_dir, build_log=build_log, |
476 |
- fetch_log=fetch_log, pkg=build.pkg, |
477 |
+ pkg=build.pkg, |
478 |
returncode=build.returncode)) |
479 |
self._failed_pkg_msg(self._failed_pkgs[-1], "emerge", "for") |
480 |
|
481 |
@@ -9998,6 +9986,10 @@ |
482 |
if self._poll_event_handlers: |
483 |
self._poll_loop() |
484 |
|
485 |
+ def _keep_scheduling(self): |
486 |
+ return bool(self._pkg_queue and \ |
487 |
+ not (self._failed_pkgs and not self._build_opts.fetchonly)) |
488 |
+ |
489 |
def _schedule_tasks(self): |
490 |
self._schedule_tasks_imp() |
491 |
self._status_display.display() |
492 |
@@ -10009,7 +10001,7 @@ |
493 |
|
494 |
# Cancel prefetchers if they're the only reason |
495 |
# the main poll loop is still running. |
496 |
- if self._failed_pkgs and \ |
497 |
+ if self._failed_pkgs and not self._build_opts.fetchonly and \ |
498 |
not (self._jobs or self._task_queues.merge) and \ |
499 |
self._task_queues.fetch: |
500 |
self._task_queues.fetch.clear() |
501 |
@@ -10019,7 +10011,7 @@ |
502 |
self._schedule_tasks_imp() |
503 |
self._status_display.display() |
504 |
|
505 |
- return bool(self._pkg_queue and not self._failed_pkgs) |
506 |
+ return self._keep_scheduling() |
507 |
|
508 |
def _job_delay(self): |
509 |
""" |
510 |
@@ -10049,7 +10041,7 @@ |
511 |
|
512 |
while True: |
513 |
|
514 |
- if not self._pkg_queue or self._failed_pkgs: |
515 |
+ if not self._keep_scheduling(): |
516 |
return bool(state_change) |
517 |
|
518 |
if self._choose_pkg_return_early or \ |
519 |
@@ -10106,7 +10098,6 @@ |
520 |
config_pool=self._ConfigPool(pkg.root, |
521 |
self._allocate_config, self._deallocate_config), |
522 |
emerge_opts=self.myopts, |
523 |
- failed_fetches=self._failed_fetches, |
524 |
find_blockers=self._find_blockers(pkg), logger=self._logger, |
525 |
mtimedb=self._mtimedb, pkg=pkg, pkg_count=self._pkg_count.copy(), |
526 |
pkg_to_replace=pkg_to_replace, |
527 |
@@ -10165,9 +10156,8 @@ |
528 |
""" |
529 |
Use the current resume list to calculate a new one, |
530 |
dropping any packages with unsatisfied deps. |
531 |
- @rtype: set |
532 |
- @returns: a possibly empty set of dropped tasks, or |
533 |
- None if an error occurs. |
534 |
+ @rtype: bool |
535 |
+ @returns: True if successful, False otherwise. |
536 |
""" |
537 |
print colorize("GOOD", "*** Resuming merge...") |
538 |
|
539 |
@@ -10203,42 +10193,50 @@ |
540 |
print "\b\b... done!" |
541 |
|
542 |
if e is not None: |
543 |
- mydepgraph.display_problems() |
544 |
- out = portage.output.EOutput() |
545 |
- out.eerror("One or more packages are either masked or " + \ |
546 |
- "have missing dependencies:") |
547 |
- out.eerror("") |
548 |
- indent = " " |
549 |
- for dep in e.value: |
550 |
- if dep.atom is None: |
551 |
- out.eerror(indent + "Masked package:") |
552 |
- out.eerror(2 * indent + str(dep.parent)) |
553 |
- out.eerror("") |
554 |
- else: |
555 |
- out.eerror(indent + str(dep.atom) + " pulled in by:") |
556 |
- out.eerror(2 * indent + str(dep.parent)) |
557 |
- out.eerror("") |
558 |
- msg = "The resume list contains packages " + \ |
559 |
- "that are either masked or have " + \ |
560 |
- "unsatisfied dependencies. " + \ |
561 |
- "Please restart/continue " + \ |
562 |
- "the operation manually, or use --skipfirst " + \ |
563 |
- "to skip the first package in the list and " + \ |
564 |
- "any other packages that may be " + \ |
565 |
- "masked or have missing dependencies." |
566 |
- for line in textwrap.wrap(msg, 72): |
567 |
- out.eerror(line) |
568 |
- return None |
569 |
+ def unsatisfied_resume_dep_msg(): |
570 |
+ mydepgraph.display_problems() |
571 |
+ out = portage.output.EOutput() |
572 |
+ out.eerror("One or more packages are either masked or " + \ |
573 |
+ "have missing dependencies:") |
574 |
+ out.eerror("") |
575 |
+ indent = " " |
576 |
+ show_parents = set() |
577 |
+ for dep in e.value: |
578 |
+ if dep.parent in show_parents: |
579 |
+ continue |
580 |
+ show_parents.add(dep.parent) |
581 |
+ if dep.atom is None: |
582 |
+ out.eerror(indent + "Masked package:") |
583 |
+ out.eerror(2 * indent + str(dep.parent)) |
584 |
+ out.eerror("") |
585 |
+ else: |
586 |
+ out.eerror(indent + str(dep.atom) + " pulled in by:") |
587 |
+ out.eerror(2 * indent + str(dep.parent)) |
588 |
+ out.eerror("") |
589 |
+ msg = "The resume list contains packages " + \ |
590 |
+ "that are either masked or have " + \ |
591 |
+ "unsatisfied dependencies. " + \ |
592 |
+ "Please restart/continue " + \ |
593 |
+ "the operation manually, or use --skipfirst " + \ |
594 |
+ "to skip the first package in the list and " + \ |
595 |
+ "any other packages that may be " + \ |
596 |
+ "masked or have missing dependencies." |
597 |
+ for line in textwrap.wrap(msg, 72): |
598 |
+ out.eerror(line) |
599 |
+ self._post_mod_echo_msgs.append(unsatisfied_resume_dep_msg) |
600 |
+ return False |
601 |
|
602 |
- if self._show_list(): |
603 |
+ if success and self._show_list(): |
604 |
mylist = mydepgraph.altlist() |
605 |
- if "--tree" in self.myopts: |
606 |
- mylist.reverse() |
607 |
- mydepgraph.display(mylist, favorites=self._favorites) |
608 |
+ if mylist: |
609 |
+ if "--tree" in self.myopts: |
610 |
+ mylist.reverse() |
611 |
+ mydepgraph.display(mylist, favorites=self._favorites) |
612 |
|
613 |
+ if not success: |
614 |
+ self._post_mod_echo_msgs.append(mydepgraph.display_problems) |
615 |
+ return False |
616 |
mydepgraph.display_problems() |
617 |
- if not success: |
618 |
- return None |
619 |
|
620 |
mylist = mydepgraph.altlist() |
621 |
mydepgraph.break_refs(mylist) |
622 |
@@ -10247,8 +10245,28 @@ |
623 |
|
624 |
self._mergelist = mylist |
625 |
self._set_digraph(mydepgraph.digraph) |
626 |
- return dropped_tasks |
627 |
|
628 |
+ msg_width = 75 |
629 |
+ for task in dropped_tasks: |
630 |
+ if not (isinstance(task, Package) and task.operation == "merge"): |
631 |
+ continue |
632 |
+ pkg = task |
633 |
+ msg = "emerge --keep-going:" + \ |
634 |
+ " %s" % (pkg.cpv,) |
635 |
+ if pkg.root != "/": |
636 |
+ msg += " for %s" % (pkg.root,) |
637 |
+ msg += " dropped due to unsatisfied dependency." |
638 |
+ for line in textwrap.wrap(msg, msg_width): |
639 |
+ eerror(line, phase="other", key=pkg.cpv) |
640 |
+ settings = mydepgraph.pkgsettings[pkg.root] |
641 |
+ # Ensure that log collection from $T is disabled inside |
642 |
+ # elog_process(), since any logs that might exist are |
643 |
+ # not valid here. |
644 |
+ settings.pop("T", None) |
645 |
+ portage.elog.elog_process(pkg.cpv, settings) |
646 |
+ |
647 |
+ return True |
648 |
+ |
649 |
def _show_list(self): |
650 |
myopts = self.myopts |
651 |
if "--quiet" not in myopts and \ |
652 |
|
653 |
Modified: main/branches/prefix/pym/portage/__init__.py |
654 |
=================================================================== |
655 |
--- main/branches/prefix/pym/portage/__init__.py 2008-10-15 19:39:42 UTC (rev 11693) |
656 |
+++ main/branches/prefix/pym/portage/__init__.py 2008-10-15 20:33:21 UTC (rev 11694) |
657 |
@@ -3643,6 +3643,7 @@ |
658 |
del distlocks_subdir |
659 |
|
660 |
distdir_writable = can_fetch and not fetch_to_ro |
661 |
+ failed_files = set() |
662 |
|
663 |
for myfile in filedict: |
664 |
""" |
665 |
@@ -4080,31 +4081,57 @@ |
666 |
|
667 |
if listonly: |
668 |
writemsg_stdout("\n", noiselevel=-1) |
669 |
- elif fetched != 2: |
670 |
+ if fetched != 2: |
671 |
if restrict_fetch: |
672 |
- print "\n!!!", mysettings["CATEGORY"] + "/" + \ |
673 |
- mysettings["PF"], "has fetch restriction turned on." |
674 |
- print "!!! This probably means that this " + \ |
675 |
- "ebuild's files must be downloaded" |
676 |
- print "!!! manually. See the comments in" + \ |
677 |
- " the ebuild for more information.\n" |
678 |
- ebuild_phase = mysettings.get("EBUILD_PHASE") |
679 |
- try: |
680 |
- mysettings["EBUILD_PHASE"] = "nofetch" |
681 |
- spawn(_shell_quote(EBUILD_SH_BINARY) + \ |
682 |
- " nofetch", mysettings) |
683 |
- finally: |
684 |
- if ebuild_phase is None: |
685 |
- mysettings.pop("EBUILD_PHASE", None) |
686 |
- else: |
687 |
- mysettings["EBUILD_PHASE"] = ebuild_phase |
688 |
+ msg = ("\n!!! %s/%s" + \ |
689 |
+ " has fetch restriction turned on.\n" + \ |
690 |
+ "!!! This probably means that this " + \ |
691 |
+ "ebuild's files must be downloaded\n" + \ |
692 |
+ "!!! manually. See the comments in" + \ |
693 |
+ " the ebuild for more information.\n\n") % \ |
694 |
+ (mysettings["CATEGORY"], mysettings["PF"]) |
695 |
+ portage.util.writemsg_level(msg, |
696 |
+ level=logging.ERROR, noiselevel=-1) |
697 |
+ if not parallel_fetchonly: |
698 |
+ # To spawn pkg_nofetch requires PORTAGE_BUILDDIR for |
699 |
+ # ensuring sane $PWD (bug #239560) and storing elog |
700 |
+ # messages. Therefore, calling code needs to ensure that |
701 |
+ # PORTAGE_BUILDDIR is already clean and locked here. |
702 |
+ |
703 |
+ # All the pkg_nofetch goes to stderr since it's considered |
704 |
+ # to be an error message. |
705 |
+ fd_pipes = { |
706 |
+ 0 : sys.stdin.fileno(), |
707 |
+ 1 : sys.stderr.fileno(), |
708 |
+ 2 : sys.stderr.fileno(), |
709 |
+ } |
710 |
+ |
711 |
+ ebuild_phase = mysettings.get("EBUILD_PHASE") |
712 |
+ try: |
713 |
+ mysettings["EBUILD_PHASE"] = "nofetch" |
714 |
+ spawn(_shell_quote(EBUILD_SH_BINARY) + \ |
715 |
+ " nofetch", mysettings, fd_pipes=fd_pipes) |
716 |
+ finally: |
717 |
+ if ebuild_phase is None: |
718 |
+ mysettings.pop("EBUILD_PHASE", None) |
719 |
+ else: |
720 |
+ mysettings["EBUILD_PHASE"] = ebuild_phase |
721 |
+ if listonly: |
722 |
+ continue |
723 |
+ elif listonly: |
724 |
+ continue |
725 |
elif not filedict[myfile]: |
726 |
writemsg("Warning: No mirrors available for file" + \ |
727 |
" '%s'\n" % (myfile), noiselevel=-1) |
728 |
else: |
729 |
writemsg("!!! Couldn't download '%s'. Aborting.\n" % myfile, |
730 |
noiselevel=-1) |
731 |
+ if fetchonly and not restrict_fetch: |
732 |
+ failed_files.add(myfile) |
733 |
+ continue |
734 |
return 0 |
735 |
+ if failed_files: |
736 |
+ return 0 |
737 |
return 1 |
738 |
|
739 |
def digestgen(myarchives, mysettings, overwrite=1, manifestonly=0, myportdb=None): |
740 |
@@ -5479,8 +5506,7 @@ |
741 |
|
742 |
# Build directory creation isn't required for any of these. |
743 |
have_build_dirs = False |
744 |
- if not (mydo in ("digest", "help", "manifest") or \ |
745 |
- (mydo == "fetch" and listonly)): |
746 |
+ if not mydo in ("digest", "help", "manifest"): |
747 |
mystatus = prepare_build_dirs(myroot, mysettings, cleanup) |
748 |
if mystatus: |
749 |
return mystatus |
750 |
|
751 |
Modified: main/branches/prefix/pym/portage/dbapi/bintree.py |
752 |
=================================================================== |
753 |
--- main/branches/prefix/pym/portage/dbapi/bintree.py 2008-10-15 19:39:42 UTC (rev 11693) |
754 |
+++ main/branches/prefix/pym/portage/dbapi/bintree.py 2008-10-15 20:33:21 UTC (rev 11694) |
755 |
@@ -555,7 +555,8 @@ |
756 |
"unrecognized category: '%s'\n") % full_path, |
757 |
noiselevel=-1) |
758 |
writemsg(("!!! '%s' has a category that is not" + \ |
759 |
- " listed in /etc/portage/categories\n") % mycpv, |
760 |
+ " listed in %setc/portage/categories\n") % \ |
761 |
+ (mycpv, self.settings["PORTAGE_CONFIGROOT"]), |
762 |
noiselevel=-1) |
763 |
continue |
764 |
pkg_paths[mycpv] = mypath |
765 |
@@ -723,7 +724,8 @@ |
766 |
"unrecognized category: '%s'\n") % fullpkg, |
767 |
noiselevel=-1) |
768 |
writemsg(("!!! '%s' has a category that is not" + \ |
769 |
- " listed in /etc/portage/categories\n") % fullpkg, |
770 |
+ " listed in %setc/portage/categories\n") % \ |
771 |
+ (fullpkg, self.settings["PORTAGE_CONFIGROOT"]), |
772 |
noiselevel=-1) |
773 |
continue |
774 |
mykey = dep_getkey(fullpkg) |
775 |
|
776 |
Modified: main/branches/prefix/pym/portage/dbapi/porttree.py |
777 |
=================================================================== |
778 |
--- main/branches/prefix/pym/portage/dbapi/porttree.py 2008-10-15 19:39:42 UTC (rev 11693) |
779 |
+++ main/branches/prefix/pym/portage/dbapi/porttree.py 2008-10-15 20:33:21 UTC (rev 11694) |
780 |
@@ -728,7 +728,8 @@ |
781 |
d[mysplit[0]+"/"+pf] = None |
782 |
if invalid_category and d: |
783 |
writemsg(("\n!!! '%s' has a category that is not listed in " + \ |
784 |
- "/etc/portage/categories\n") % mycp, noiselevel=-1) |
785 |
+ "%setc/portage/categories\n") % \ |
786 |
+ (mycp, self.mysettings["PORTAGE_CONFIGROOT"]), noiselevel=-1) |
787 |
mylist = [] |
788 |
else: |
789 |
mylist = d.keys() |
790 |
|
791 |
Modified: main/branches/prefix/pym/portage/dbapi/vartree.py |
792 |
=================================================================== |
793 |
--- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-10-15 19:39:42 UTC (rev 11693) |
794 |
+++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-10-15 20:33:21 UTC (rev 11694) |
795 |
@@ -1295,10 +1295,10 @@ |
796 |
# -MERGING- should never be a cpv, nor should files. |
797 |
try: |
798 |
if catpkgsplit(subpath) is None: |
799 |
- self.invalidentry(os.path.join(self.root, subpath)) |
800 |
+ self.invalidentry(self.getpath(subpath)) |
801 |
continue |
802 |
except InvalidData: |
803 |
- self.invalidentry(os.path.join(self.root, subpath)) |
804 |
+ self.invalidentry(self.getpath(subpath)) |
805 |
continue |
806 |
returnme.append(subpath) |
807 |
return returnme |
808 |
|
809 |
Modified: main/branches/prefix/pym/portage/elog/__init__.py |
810 |
=================================================================== |
811 |
--- main/branches/prefix/pym/portage/elog/__init__.py 2008-10-15 19:39:42 UTC (rev 11693) |
812 |
+++ main/branches/prefix/pym/portage/elog/__init__.py 2008-10-15 20:33:21 UTC (rev 11694) |
813 |
@@ -72,7 +72,13 @@ |
814 |
except ImportError: |
815 |
pass |
816 |
|
817 |
- ebuild_logentries = collect_ebuild_messages(os.path.join(mysettings["T"], "logging")) |
818 |
+ if "T" in mysettings: |
819 |
+ ebuild_logentries = collect_ebuild_messages( |
820 |
+ os.path.join(mysettings["T"], "logging")) |
821 |
+ else: |
822 |
+ # A build dir isn't necessarily required since the messages.e* |
823 |
+ # functions allow messages to be generated in-memory. |
824 |
+ ebuild_logentries = {} |
825 |
all_logentries = collect_messages() |
826 |
if cpv in all_logentries: |
827 |
all_logentries[cpv] = _merge_logentries(ebuild_logentries, all_logentries[cpv]) |