1 |
Author: grobian |
2 |
Date: 2008-07-03 06:49:48 +0000 (Thu, 03 Jul 2008) |
3 |
New Revision: 10904 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/pym/_emerge/__init__.py |
7 |
main/branches/prefix/pym/portage/__init__.py |
8 |
main/branches/prefix/pym/portage/output.py |
9 |
main/branches/prefix/pym/portage_compat_namespace.py |
10 |
Log: |
11 |
Merged from trunk 10893:10903 |
12 |
|
13 |
| 10894 | Handle missing select.poll on interix by using select() to | |
14 |
| zmedico | emulate a poll object. | |
15 |
|
16 |
| 10895 | Fix EbuildBuildDir so that it works properly with binary | |
17 |
| zmedico | packages. | |
18 |
|
19 |
| 10896 | Fix broken except statement. Thanks to hawking. | |
20 |
| zmedico | | |
21 |
|
22 |
| 10897 | Use stdout.write() instead of "print", for py3k compat. | |
23 |
| zmedico | | |
24 |
|
25 |
| 10898 | Split out a SpawnProcess base class out of | |
26 |
| zmedico | EbuildFetcherAsync. | |
27 |
|
28 |
| 10899 | Move post ebuild phase code (originally from spawnebuild) | |
29 |
| zmedico | from EbuildExecuter.execute() to | |
30 |
| | EbuildPhase._set_returncode(). | |
31 |
|
32 |
| 10900 | Add missing BinpkgFetcherAsync.registered attribute. | |
33 |
| zmedico | | |
34 |
|
35 |
| 10901 | Make BinpkgFetcherAsync inherit from SpawnProcess. | |
36 |
| zmedico | | |
37 |
|
38 |
| 10902 | Implement asynchronous binary package extraction, so that | |
39 |
| zmedico | the scheduler can run while a package is extracting in the | |
40 |
| | background. | |
41 |
|
42 |
| 10903 | Split out a new _check_manifests() method from | |
43 |
| zmedico | Scheduler._merge() since this method is not useful for | |
44 |
| | parallel scheduling and any useful code needs to be | |
45 |
| | relocated. | |
46 |
|
47 |
|
48 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
49 |
=================================================================== |
50 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-07-03 06:39:20 UTC (rev 10903) |
51 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-07-03 06:49:48 UTC (rev 10904) |
52 |
@@ -24,6 +24,7 @@ |
53 |
import fcntl |
54 |
import select |
55 |
import shlex |
56 |
+import shutil |
57 |
import urlparse |
58 |
import weakref |
59 |
import gc |
60 |
@@ -1522,13 +1523,22 @@ |
61 |
|
62 |
self.returncode = retval |
63 |
|
64 |
-class EbuildFetcherAsync(SubProcess): |
65 |
+class SpawnProcess(SubProcess): |
66 |
|
67 |
- __slots__ = ("log_file", "fd_pipes", "pkg", |
68 |
- "register", "unregister", |
69 |
- "files") |
70 |
+ """ |
71 |
+ Constructor keyword args are passed into portage.process.spawn(). |
72 |
+ The required "args" keyword argument will be passed as the first |
73 |
+ spawn() argument. |
74 |
+ """ |
75 |
|
76 |
- _file_names = ("fetcher", "out") |
77 |
+ _spawn_kwarg_names = ("env", "opt_name", "fd_pipes", |
78 |
+ "uid", "gid", "groups", "umask", "logfile", |
79 |
+ "path_lookup", "pre_exec") |
80 |
+ |
81 |
+ __slots__ = ("args", "files", "register", "unregister", "registered") + \ |
82 |
+ _spawn_kwarg_names |
83 |
+ |
84 |
+ _file_names = ("process", "out") |
85 |
_files_dict = slot_dict_class(_file_names, prefix="") |
86 |
_bufsize = 4096 |
87 |
|
88 |
@@ -1546,27 +1556,26 @@ |
89 |
2 : sys.stderr.fileno(), |
90 |
} |
91 |
|
92 |
- log_file = self.log_file |
93 |
+ logfile = self.logfile |
94 |
self.files = self._files_dict() |
95 |
files = self.files |
96 |
|
97 |
- if log_file is not None: |
98 |
- files.out = open(log_file, "a") |
99 |
- portage.util.apply_secpass_permissions(log_file, |
100 |
+ if logfile is not None: |
101 |
+ files.out = open(logfile, "a") |
102 |
+ portage.util.apply_secpass_permissions(logfile, |
103 |
uid=portage.portage_uid, gid=portage.portage_gid, |
104 |
mode=0660) |
105 |
else: |
106 |
+ fd_pipes.setdefault(1, sys.stdout.fileno()) |
107 |
for fd in fd_pipes.itervalues(): |
108 |
if fd == sys.stdout.fileno(): |
109 |
sys.stdout.flush() |
110 |
if fd == sys.stderr.fileno(): |
111 |
sys.stderr.flush() |
112 |
- |
113 |
files.out = os.fdopen(os.dup(fd_pipes[1]), 'w') |
114 |
|
115 |
master_fd, slave_fd = os.pipe() |
116 |
|
117 |
- import fcntl |
118 |
fcntl.fcntl(master_fd, fcntl.F_SETFL, |
119 |
fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK) |
120 |
|
121 |
@@ -1576,52 +1585,74 @@ |
122 |
fd_pipes[1] = slave_fd |
123 |
fd_pipes[2] = slave_fd |
124 |
|
125 |
- root_config = self.pkg.root_config |
126 |
- portdb = root_config.trees["porttree"].dbapi |
127 |
- ebuild_path = portdb.findname(self.pkg.cpv) |
128 |
- settings = root_config.settings |
129 |
+ kwargs = {} |
130 |
+ for k in self._spawn_kwarg_names: |
131 |
+ v = getattr(self, k) |
132 |
+ if v is not None: |
133 |
+ kwargs[k] = v |
134 |
|
135 |
- fetch_env = dict((k, settings[k]) for k in settings) |
136 |
- fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs" |
137 |
- fetch_env["PORTAGE_NICENESS"] = "0" |
138 |
- fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1" |
139 |
+ kwargs["fd_pipes"] = fd_pipes |
140 |
+ kwargs["returnpid"] = True |
141 |
+ kwargs.pop("logfile", None) |
142 |
|
143 |
- ebuild_binary = os.path.join( |
144 |
- settings["EBUILD_BIN_PATH"], "ebuild") |
145 |
+ retval = portage.process.spawn(self.args, **kwargs) |
146 |
|
147 |
- fetch_args = [ebuild_binary, ebuild_path, "fetch"] |
148 |
- debug = settings.get("PORTAGE_DEBUG") == "1" |
149 |
- if debug: |
150 |
- fetch_args.append("--debug") |
151 |
- |
152 |
- retval = portage.process.spawn(fetch_args, env=fetch_env, |
153 |
- fd_pipes=fd_pipes, returnpid=True) |
154 |
- |
155 |
self.pid = retval[0] |
156 |
|
157 |
os.close(slave_fd) |
158 |
- files.fetcher = os.fdopen(master_fd, 'r') |
159 |
- self.register(files.fetcher.fileno(), |
160 |
+ files.process = os.fdopen(master_fd, 'r') |
161 |
+ self.registered = True |
162 |
+ self.register(files.process.fileno(), |
163 |
select.POLLIN, self._output_handler) |
164 |
|
165 |
def _output_handler(self, fd, event): |
166 |
files = self.files |
167 |
buf = array.array('B') |
168 |
try: |
169 |
- buf.fromfile(files.fetcher, self._bufsize) |
170 |
+ buf.fromfile(files.process, self._bufsize) |
171 |
except EOFError: |
172 |
pass |
173 |
if buf: |
174 |
buf.tofile(files.out) |
175 |
files.out.flush() |
176 |
else: |
177 |
- self.unregister(files.fetcher.fileno()) |
178 |
+ fd = files.process.fileno() |
179 |
for f in files.values(): |
180 |
+ f.flush() |
181 |
f.close() |
182 |
+ self.registered = False |
183 |
+ self.unregister(fd) |
184 |
|
185 |
+class EbuildFetcherAsync(SpawnProcess): |
186 |
+ |
187 |
+ __slots__ = ("pkg",) |
188 |
+ |
189 |
+ def start(self): |
190 |
+ |
191 |
+ root_config = self.pkg.root_config |
192 |
+ portdb = root_config.trees["porttree"].dbapi |
193 |
+ ebuild_path = portdb.findname(self.pkg.cpv) |
194 |
+ settings = root_config.settings |
195 |
+ |
196 |
+ fetch_env = settings.environ() |
197 |
+ fetch_env["PORTAGE_NICENESS"] = "0" |
198 |
+ fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1" |
199 |
+ |
200 |
+ ebuild_binary = os.path.join( |
201 |
+ settings["EBUILD_BIN_PATH"], "ebuild") |
202 |
+ |
203 |
+ fetch_args = [ebuild_binary, ebuild_path, "fetch"] |
204 |
+ debug = settings.get("PORTAGE_DEBUG") == "1" |
205 |
+ if debug: |
206 |
+ fetch_args.append("--debug") |
207 |
+ |
208 |
+ self.args = fetch_args |
209 |
+ self.env = fetch_env |
210 |
+ SpawnProcess.start(self) |
211 |
+ |
212 |
class EbuildBuildDir(SlotObject): |
213 |
|
214 |
- __slots__ = ("pkg", "settings", |
215 |
+ __slots__ = ("dir_path", "pkg", "settings", |
216 |
"locked", "_catdir", "_lock_obj") |
217 |
|
218 |
def __init__(self, **kwargs): |
219 |
@@ -1638,17 +1669,21 @@ |
220 |
if self._lock_obj is not None: |
221 |
raise self.AlreadyLocked((self._lock_obj,)) |
222 |
|
223 |
- root_config = self.pkg.root_config |
224 |
- portdb = root_config.trees["porttree"].dbapi |
225 |
- ebuild_path = portdb.findname(self.pkg.cpv) |
226 |
- settings = self.settings |
227 |
- debug = settings.get("PORTAGE_DEBUG") == "1" |
228 |
- use_cache = 1 # always true |
229 |
+ dir_path = self.dir_path |
230 |
+ if dir_path is None: |
231 |
+ root_config = self.pkg.root_config |
232 |
+ portdb = root_config.trees["porttree"].dbapi |
233 |
+ ebuild_path = portdb.findname(self.pkg.cpv) |
234 |
+ settings = self.settings |
235 |
+ debug = settings.get("PORTAGE_DEBUG") == "1" |
236 |
+ use_cache = 1 # always true |
237 |
+ portage.doebuild_environment(ebuild_path, "setup", root_config.root, |
238 |
+ self.settings, debug, use_cache, portdb) |
239 |
+ dir_path = self.settings["PORTAGE_BUILDDIR"] |
240 |
|
241 |
- portage.doebuild_environment(ebuild_path, "setup", root_config.root, |
242 |
- self.settings, debug, use_cache, portdb) |
243 |
- catdir = os.path.dirname(settings["PORTAGE_BUILDDIR"]) |
244 |
+ catdir = os.path.dirname(dir_path) |
245 |
self._catdir = catdir |
246 |
+ |
247 |
portage.util.ensure_dirs(os.path.dirname(catdir), |
248 |
uid=portage.portage_uid, gid=portage.portage_gid, |
249 |
mode=070, mask=0) |
250 |
@@ -1658,8 +1693,7 @@ |
251 |
portage.util.ensure_dirs(catdir, |
252 |
gid=portage.portage_gid, |
253 |
mode=070, mask=0) |
254 |
- self._lock_obj = portage.locks.lockdir( |
255 |
- self.settings["PORTAGE_BUILDDIR"]) |
256 |
+ self._lock_obj = portage.locks.lockdir(dir_path) |
257 |
finally: |
258 |
self.locked = self._lock_obj is not None |
259 |
if catdir_lock is not None: |
260 |
@@ -1857,12 +1891,6 @@ |
261 |
self.schedule() |
262 |
retval = ebuild_phase.poll() |
263 |
|
264 |
- portage._post_phase_userpriv_perms(settings) |
265 |
- if mydo == "install": |
266 |
- portage._check_build_log(settings) |
267 |
- if retval == os.EX_OK: |
268 |
- retval = portage._post_src_install_checks(settings) |
269 |
- |
270 |
if retval != os.EX_OK: |
271 |
return retval |
272 |
|
273 |
@@ -1872,7 +1900,7 @@ |
274 |
|
275 |
__slots__ = ("fd_pipes", "phase", "pkg", |
276 |
"register", "settings", "unregister", |
277 |
- "files") |
278 |
+ "files", "registered") |
279 |
|
280 |
_file_names = ("log", "stdout", "ebuild") |
281 |
_files_dict = slot_dict_class(_file_names, prefix="") |
282 |
@@ -1953,6 +1981,7 @@ |
283 |
files.log = open(logfile, 'a') |
284 |
files.stdout = os.fdopen(os.dup(fd_pipes_orig[1]), 'w') |
285 |
files.ebuild = os.fdopen(master_fd, 'r') |
286 |
+ self.registered = True |
287 |
self.register(files.ebuild.fileno(), |
288 |
select.POLLIN, self._output_handler) |
289 |
|
290 |
@@ -1969,9 +1998,11 @@ |
291 |
buf.tofile(files.log) |
292 |
files.log.flush() |
293 |
else: |
294 |
- self.unregister(files.ebuild.fileno()) |
295 |
+ fd = files.ebuild.fileno() |
296 |
for f in files.values(): |
297 |
f.close() |
298 |
+ self.registered = False |
299 |
+ self.unregister(fd) |
300 |
|
301 |
def _set_returncode(self, wait_retval): |
302 |
SubProcess._set_returncode(self, wait_retval) |
303 |
@@ -1984,6 +2015,14 @@ |
304 |
for l in wrap(msg, 72): |
305 |
eerror(l, phase=self.phase, key=self.pkg.cpv) |
306 |
|
307 |
+ returncode = self.returncode |
308 |
+ settings = self.settings |
309 |
+ portage._post_phase_userpriv_perms(settings) |
310 |
+ if self.phase == "install": |
311 |
+ portage._check_build_log(settings) |
312 |
+ if returncode == os.EX_OK: |
313 |
+ returncode = portage._post_src_install_checks(settings) |
314 |
+ |
315 |
class EbuildBinpkg(Task): |
316 |
""" |
317 |
This assumes that src_install() has successfully completed. |
318 |
@@ -2093,6 +2132,8 @@ |
319 |
pkg_count = self.pkg_count |
320 |
scheduler = self.scheduler |
321 |
settings = self.settings |
322 |
+ settings.setcpv(pkg) |
323 |
+ debug = settings.get("PORTAGE_DEBUG") == "1" |
324 |
|
325 |
# The prefetcher has already completed or it |
326 |
# could be running now. If it's running now, |
327 |
@@ -2152,16 +2193,126 @@ |
328 |
(pkg_count.curval, pkg_count.maxval, pkg.cpv) |
329 |
logger.log(msg, short_msg=short_msg) |
330 |
|
331 |
- build_dir = EbuildBuildDir(pkg=pkg, settings=settings) |
332 |
+ dir_path = os.path.join(settings["PORTAGE_TMPDIR"], |
333 |
+ "portage", pkg.category, pkg.pf) |
334 |
+ build_dir = EbuildBuildDir(dir_path=dir_path, |
335 |
+ pkg=pkg, settings=settings) |
336 |
+ image_dir = os.path.join(dir_path, "image") |
337 |
+ infloc = os.path.join(dir_path, "build-info") |
338 |
+ |
339 |
+ fd_pipes = { |
340 |
+ 0 : sys.stdin.fileno(), |
341 |
+ 1 : sys.stdout.fileno(), |
342 |
+ 2 : sys.stderr.fileno(), |
343 |
+ } |
344 |
+ |
345 |
try: |
346 |
build_dir.lock() |
347 |
- merge = BinpkgMerge(find_blockers=find_blockers, |
348 |
- ldpath_mtimes=ldpath_mtimes, pkg=pkg, pretend=opts.pretend, |
349 |
- pkg_path=pkg_path, settings=settings) |
350 |
+ |
351 |
+ root_config = self.pkg.root_config |
352 |
+ ebuild_path = os.path.join(infloc, pkg.pf + ".ebuild") |
353 |
+ cleanup = 1 |
354 |
+ tree = "bintree" |
355 |
+ mydbapi = root_config.trees[tree].dbapi |
356 |
+ |
357 |
+ retval = portage.doebuild(ebuild_path, "clean", |
358 |
+ root_config.root, settings, debug, cleanup=cleanup, |
359 |
+ mydbapi=mydbapi, tree=tree) |
360 |
+ if retval != os.EX_OK: |
361 |
+ return retval |
362 |
+ |
363 |
+ try: |
364 |
+ shutil.rmtree(dir_path) |
365 |
+ except (IOError, OSError), e: |
366 |
+ if e.errno != errno.ENOENT: |
367 |
+ raise |
368 |
+ del e |
369 |
+ |
370 |
+ # This initializes PORTAGE_LOG_FILE. |
371 |
+ portage.prepare_build_dirs(root_config.root, settings, cleanup) |
372 |
+ |
373 |
+ dir_mode = 0755 |
374 |
+ for mydir in (dir_path, image_dir, infloc): |
375 |
+ portage.util.ensure_dirs(mydir, uid=portage.data.portage_uid, |
376 |
+ gid=portage.data.portage_gid, mode=dir_mode) |
377 |
+ |
378 |
+ portage.writemsg_stdout(">>> Extracting info\n") |
379 |
+ |
380 |
+ pkg_xpak = portage.xpak.tbz2(pkg_path) |
381 |
+ check_missing_metadata = ("CATEGORY", "PF") |
382 |
+ missing_metadata = set() |
383 |
+ for k in check_missing_metadata: |
384 |
+ v = pkg_xpak.getfile(k) |
385 |
+ if not v: |
386 |
+ missing_metadata.add(k) |
387 |
+ |
388 |
+ pkg_xpak.unpackinfo(infloc) |
389 |
+ for k in missing_metadata: |
390 |
+ if k == "CATEGORY": |
391 |
+ v = pkg.category |
392 |
+ elif k == "PF": |
393 |
+ v = pkg.pf |
394 |
+ else: |
395 |
+ continue |
396 |
+ |
397 |
+ f = open(os.path.join(infloc, k), 'wb') |
398 |
+ try: |
399 |
+ f.write(v + "\n") |
400 |
+ finally: |
401 |
+ f.close() |
402 |
+ |
403 |
+ # Store the md5sum in the vdb. |
404 |
+ f = open(os.path.join(infloc, "BINPKGMD5"), "w") |
405 |
+ try: |
406 |
+ f.write(str(portage.checksum.perform_md5(pkg_path)) + "\n") |
407 |
+ finally: |
408 |
+ f.close() |
409 |
+ |
410 |
+ # This gives bashrc users an opportunity to do various things |
411 |
+ # such as remove binary packages after they're installed. |
412 |
+ settings["PORTAGE_BINPKG_FILE"] = pkg_path |
413 |
+ settings.backup_changes("PORTAGE_BINPKG_FILE") |
414 |
+ |
415 |
+ phase = "setup" |
416 |
+ ebuild_phase = EbuildPhase(fd_pipes=fd_pipes, |
417 |
+ pkg=pkg, phase=phase, register=scheduler.register, |
418 |
+ settings=settings, unregister=scheduler.unregister) |
419 |
+ |
420 |
+ ebuild_phase.start() |
421 |
+ retval = None |
422 |
+ while retval is None: |
423 |
+ scheduler.schedule() |
424 |
+ retval = ebuild_phase.poll() |
425 |
+ |
426 |
+ if retval != os.EX_OK: |
427 |
+ return retval |
428 |
+ |
429 |
+ extractor = BinpkgExtractorAsync(image_dir=image_dir, |
430 |
+ pkg=pkg, pkg_path=pkg_path, register=scheduler.register, |
431 |
+ unregister=scheduler.unregister) |
432 |
+ portage.writemsg_stdout(">>> Extracting %s\n" % pkg.cpv) |
433 |
+ extractor.start() |
434 |
+ retval = None |
435 |
+ while retval is None: |
436 |
+ scheduler.schedule() |
437 |
+ retval = extractor.poll() |
438 |
+ |
439 |
+ if retval != os.EX_OK: |
440 |
+ writemsg("!!! Error Extracting '%s'\n" % pkg_path, |
441 |
+ noiselevel=-1) |
442 |
+ return retval |
443 |
+ |
444 |
+ merge = EbuildMerge( |
445 |
+ find_blockers=find_blockers, |
446 |
+ ldpath_mtimes=ldpath_mtimes, |
447 |
+ pkg=pkg, settings=settings) |
448 |
+ |
449 |
retval = merge.execute() |
450 |
if retval != os.EX_OK: |
451 |
return retval |
452 |
+ |
453 |
finally: |
454 |
+ settings.pop("PORTAGE_BINPKG_FILE", None) |
455 |
build_dir.unlock() |
456 |
return os.EX_OK |
457 |
|
458 |
@@ -2224,16 +2375,11 @@ |
459 |
rval = 1 |
460 |
return rval |
461 |
|
462 |
-class BinpkgFetcherAsync(SubProcess): |
463 |
+class BinpkgFetcherAsync(SpawnProcess): |
464 |
|
465 |
- __slots__ = ("log_file", "fd_pipes", "pkg", |
466 |
- "register", "unregister", |
467 |
- "locked", "files", "pkg_path", "_lock_obj") |
468 |
+ __slots__ = ("pkg", |
469 |
+ "locked", "pkg_path", "_lock_obj") |
470 |
|
471 |
- _file_names = ("fetcher", "out") |
472 |
- _files_dict = slot_dict_class(_file_names, prefix="") |
473 |
- _bufsize = 4096 |
474 |
- |
475 |
def __init__(self, **kwargs): |
476 |
SubProcess.__init__(self, **kwargs) |
477 |
pkg = self.pkg |
478 |
@@ -2244,43 +2390,6 @@ |
479 |
if self.cancelled: |
480 |
return |
481 |
|
482 |
- fd_pipes = self.fd_pipes |
483 |
- if fd_pipes is None: |
484 |
- fd_pipes = { |
485 |
- 0 : sys.stdin.fileno(), |
486 |
- 1 : sys.stdout.fileno(), |
487 |
- 2 : sys.stderr.fileno(), |
488 |
- } |
489 |
- |
490 |
- log_file = self.log_file |
491 |
- self.files = self._files_dict() |
492 |
- files = self.files |
493 |
- |
494 |
- if log_file is not None: |
495 |
- files.out = open(log_file, "a") |
496 |
- portage.util.apply_secpass_permissions(log_file, |
497 |
- uid=portage.portage_uid, gid=portage.portage_gid, |
498 |
- mode=0660) |
499 |
- else: |
500 |
- # flush any pending output |
501 |
- for fd in fd_pipes.itervalues(): |
502 |
- if fd == sys.stdout.fileno(): |
503 |
- sys.stdout.flush() |
504 |
- if fd == sys.stderr.fileno(): |
505 |
- sys.stderr.flush() |
506 |
- |
507 |
- files.out = os.fdopen(os.dup(fd_pipes[1]), 'w') |
508 |
- |
509 |
- master_fd, slave_fd = os.pipe() |
510 |
- fcntl.fcntl(master_fd, fcntl.F_SETFL, |
511 |
- fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK) |
512 |
- |
513 |
- fd_pipes.setdefault(0, sys.stdin.fileno()) |
514 |
- fd_pipes_orig = fd_pipes.copy() |
515 |
- fd_pipes[0] = fd_pipes_orig[0] |
516 |
- fd_pipes[1] = slave_fd |
517 |
- fd_pipes[2] = slave_fd |
518 |
- |
519 |
pkg = self.pkg |
520 |
bintree = pkg.root_config.trees["bintree"] |
521 |
settings = bintree.settings |
522 |
@@ -2322,33 +2431,15 @@ |
523 |
if use_locks: |
524 |
self.lock() |
525 |
|
526 |
- retval = portage.process.spawn(fetch_args, env=fetch_env, |
527 |
- fd_pipes=fd_pipes, returnpid=True) |
528 |
+ self.args = fetch_args |
529 |
+ self.env = fetch_env |
530 |
+ SpawnProcess.start(self) |
531 |
|
532 |
- self.pid = retval[0] |
533 |
+ def _set_returncode(self, wait_retval): |
534 |
+ SpawnProcess._set_returncode(self, wait_retval) |
535 |
+ if self.locked: |
536 |
+ self.unlock() |
537 |
|
538 |
- os.close(slave_fd) |
539 |
- files.fetcher = os.fdopen(master_fd, 'r') |
540 |
- self.register(files.fetcher.fileno(), |
541 |
- select.POLLIN, self._output_handler) |
542 |
- |
543 |
- def _output_handler(self, fd, event): |
544 |
- files = self.files |
545 |
- buf = array.array('B') |
546 |
- try: |
547 |
- buf.fromfile(files.fetcher, self._bufsize) |
548 |
- except EOFError: |
549 |
- pass |
550 |
- if buf: |
551 |
- buf.tofile(files.out) |
552 |
- files.out.flush() |
553 |
- else: |
554 |
- self.unregister(files.fetcher.fileno()) |
555 |
- for f in files.values(): |
556 |
- f.close() |
557 |
- if self.locked: |
558 |
- self.unlock() |
559 |
- |
560 |
def lock(self): |
561 |
""" |
562 |
This raises an AlreadyLocked exception if lock() is called |
563 |
@@ -2373,6 +2464,21 @@ |
564 |
self._lock_obj = None |
565 |
self.locked = False |
566 |
|
567 |
+class BinpkgExtractorAsync(SpawnProcess): |
568 |
+ |
569 |
+ __slots__ = ("image_dir", "pkg", "pkg_path") |
570 |
+ |
571 |
+ _shell_binary = portage.const.BASH_BINARY |
572 |
+ |
573 |
+ def start(self): |
574 |
+ self.args = [self._shell_binary, "-c", |
575 |
+ "bzip2 -dqc -- %s | tar -xp -C %s -f -" % \ |
576 |
+ (portage._shell_quote(self.pkg_path), |
577 |
+ portage._shell_quote(self.image_dir))] |
578 |
+ |
579 |
+ self.env = self.pkg.root_config.settings.environ() |
580 |
+ SpawnProcess.start(self) |
581 |
+ |
582 |
class BinpkgMerge(Task): |
583 |
|
584 |
__slots__ = ("find_blockers", "ldpath_mtimes", |
585 |
@@ -6854,6 +6960,61 @@ |
586 |
(self.blocks - self.blocks_satisfied)) |
587 |
return "".join(myoutput) |
588 |
|
589 |
+class PollSelectFallback(object): |
590 |
+ |
591 |
+ """ |
592 |
+ Use select to emulate a poll object, for |
593 |
+ systems that don't support poll(). |
594 |
+ """ |
595 |
+ |
596 |
+ def __init__(self): |
597 |
+ self._registered = {} |
598 |
+ self._select_args = [[], [], []] |
599 |
+ |
600 |
+ def register(self, fd, *args): |
601 |
+ """ |
602 |
+ Only select.POLLIN is currently supported! |
603 |
+ """ |
604 |
+ if len(args) > 1: |
605 |
+ raise TypeError( |
606 |
+ "register expected at most 2 arguments, got " + \ |
607 |
+ repr(1 + len(args))) |
608 |
+ |
609 |
+ eventmask = select.POLLIN | select.POLLPRI | select.POLLOUT |
610 |
+ if args: |
611 |
+ eventmask = args[0] |
612 |
+ |
613 |
+ self._registered[fd] = eventmask |
614 |
+ self._select_args = None |
615 |
+ |
616 |
+ def unregister(self, fd): |
617 |
+ self._select_args = None |
618 |
+ del self._registered[fd] |
619 |
+ |
620 |
+ def poll(self, *args): |
621 |
+ if len(args) > 1: |
622 |
+ raise TypeError( |
623 |
+ "poll expected at most 2 arguments, got " + \ |
624 |
+ repr(1 + len(args))) |
625 |
+ |
626 |
+ timeout = None |
627 |
+ if args: |
628 |
+ timeout = args[0] |
629 |
+ |
630 |
+ select_args = self._select_args |
631 |
+ if select_args is None: |
632 |
+ select_args = [self._registered.keys(), [], []] |
633 |
+ |
634 |
+ if timeout is not None: |
635 |
+ select_args = select_args[:] |
636 |
+ select_args.append(timeout) |
637 |
+ |
638 |
+ select_events = select.select(*select_args) |
639 |
+ poll_events = [] |
640 |
+ for fd in select_events[0]: |
641 |
+ poll_events.append((fd, select.POLLIN)) |
642 |
+ return poll_events |
643 |
+ |
644 |
class Scheduler(object): |
645 |
|
646 |
_opts_ignore_blockers = \ |
647 |
@@ -6914,7 +7075,12 @@ |
648 |
register=self._register, schedule=self._schedule, |
649 |
unregister=self._unregister) |
650 |
self._poll_event_handlers = {} |
651 |
- self._poll = select.poll() |
652 |
+ |
653 |
+ try: |
654 |
+ self._poll = select.poll() |
655 |
+ except AttributeError: |
656 |
+ self._poll = PollSelectFallback() |
657 |
+ |
658 |
from collections import deque |
659 |
self._task_queue = deque() |
660 |
self._running_tasks = set() |
661 |
@@ -6994,12 +7160,67 @@ |
662 |
|
663 |
return blocker_dblinks |
664 |
|
665 |
+ def _check_manifests(self): |
666 |
+ # Verify all the manifests now so that the user is notified of failure |
667 |
+ # as soon as possible. |
668 |
+ if "strict" not in self.settings.features or \ |
669 |
+ "--fetchonly" in self.myopts or \ |
670 |
+ "--fetch-all-uri" in self.myopts: |
671 |
+ return os.EX_OK |
672 |
+ |
673 |
+ shown_verifying_msg = False |
674 |
+ quiet_settings = {} |
675 |
+ for myroot, pkgsettings in self.pkgsettings.iteritems(): |
676 |
+ quiet_config = portage.config(clone=pkgsettings) |
677 |
+ quiet_config["PORTAGE_QUIET"] = "1" |
678 |
+ quiet_config.backup_changes("PORTAGE_QUIET") |
679 |
+ quiet_settings[myroot] = quiet_config |
680 |
+ del quiet_config |
681 |
+ |
682 |
+ for x in self._mergelist: |
683 |
+ if x.type_name != "ebuild": |
684 |
+ continue |
685 |
+ |
686 |
+ if not shown_verifying_msg: |
687 |
+ shown_verifying_msg = True |
688 |
+ print ">>> Verifying ebuild Manifests..." |
689 |
+ |
690 |
+ root_config = x.root_config |
691 |
+ portdb = root_config.trees["porttree"].dbapi |
692 |
+ quiet_config = quiet_settings[root_config.root] |
693 |
+ quiet_config["O"] = os.path.dirname(portdb.findname(x.cpv)) |
694 |
+ if not portage.digestcheck([], quiet_config, strict=True): |
695 |
+ return 1 |
696 |
+ |
697 |
+ return os.EX_OK |
698 |
+ |
699 |
def merge(self): |
700 |
|
701 |
+ if "--resume" in self.myopts: |
702 |
+ # We're resuming. |
703 |
+ portage.writemsg_stdout( |
704 |
+ colorize("GOOD", "*** Resuming merge...\n"), noiselevel=-1) |
705 |
+ self._logger.log(" *** Resuming merge...") |
706 |
+ |
707 |
+ rval = self._check_manifests() |
708 |
+ if rval != os.EX_OK: |
709 |
+ return rval |
710 |
+ |
711 |
keep_going = "--keep-going" in self.myopts |
712 |
running_tasks = self._running_tasks |
713 |
+ mtimedb = self._mtimedb |
714 |
|
715 |
while True: |
716 |
+ |
717 |
+ # Do this before verifying the ebuild Manifests since it might |
718 |
+ # be possible for the user to use --resume --skipfirst get past |
719 |
+ # a non-essential package with a broken digest. |
720 |
+ mtimedb["resume"]["mergelist"] = [list(x) \ |
721 |
+ for x in self._mergelist \ |
722 |
+ if isinstance(x, Package) and x.operation == "merge"] |
723 |
+ |
724 |
+ mtimedb.commit() |
725 |
+ |
726 |
try: |
727 |
rval = self._merge() |
728 |
finally: |
729 |
@@ -7011,7 +7232,6 @@ |
730 |
|
731 |
if rval == os.EX_OK or not keep_going: |
732 |
break |
733 |
- mtimedb = self._mtimedb |
734 |
if "resume" not in mtimedb: |
735 |
break |
736 |
mergelist = self._mtimedb["resume"].get("mergelist") |
737 |
@@ -7120,7 +7340,7 @@ |
738 |
state_changed = False |
739 |
|
740 |
for task in list(running_tasks): |
741 |
- if task.poll() is not None: |
742 |
+ if not task.registered and task.poll() is not None: |
743 |
running_tasks.remove(task) |
744 |
state_changed = True |
745 |
|
746 |
@@ -7148,18 +7368,6 @@ |
747 |
ldpath_mtimes = mtimedb["ldpath"] |
748 |
logger = self._logger |
749 |
|
750 |
- if "--resume" in self.myopts: |
751 |
- # We're resuming. |
752 |
- print colorize("GOOD", "*** Resuming merge...") |
753 |
- self._logger.log(" *** Resuming merge...") |
754 |
- |
755 |
- # Do this before verifying the ebuild Manifests since it might |
756 |
- # be possible for the user to use --resume --skipfirst get past |
757 |
- # a non-essential package with a broken digest. |
758 |
- mtimedb["resume"]["mergelist"] = [list(x) for x in mylist \ |
759 |
- if isinstance(x, Package) and x.operation == "merge"] |
760 |
- mtimedb.commit() |
761 |
- |
762 |
prefetchers = weakref.WeakValueDictionary() |
763 |
getbinpkg = "--getbinpkg" in self.myopts |
764 |
|
765 |
@@ -7170,47 +7378,19 @@ |
766 |
continue |
767 |
if pkg.type_name == "ebuild": |
768 |
self._add_task(EbuildFetcherAsync( |
769 |
- log_file=self._fetch_log, |
770 |
+ logfile=self._fetch_log, |
771 |
pkg=pkg, register=self._register, |
772 |
unregister=self._unregister)) |
773 |
elif pkg.type_name == "binary" and getbinpkg and \ |
774 |
pkg.root_config.trees["bintree"].isremote(pkg.cpv): |
775 |
prefetcher = BinpkgFetcherAsync( |
776 |
- log_file=self._fetch_log, |
777 |
+ logfile=self._fetch_log, |
778 |
pkg=pkg, register=self._register, |
779 |
unregister=self._unregister) |
780 |
prefetchers[pkg] = prefetcher |
781 |
self._add_task(prefetcher) |
782 |
del prefetcher |
783 |
|
784 |
- # Verify all the manifests now so that the user is notified of failure |
785 |
- # as soon as possible. |
786 |
- if "--fetchonly" not in self.myopts and \ |
787 |
- "--fetch-all-uri" not in self.myopts and \ |
788 |
- "strict" in self.settings.features: |
789 |
- shown_verifying_msg = False |
790 |
- quiet_settings = {} |
791 |
- for myroot, pkgsettings in self.pkgsettings.iteritems(): |
792 |
- quiet_config = portage.config(clone=pkgsettings) |
793 |
- quiet_config["PORTAGE_QUIET"] = "1" |
794 |
- quiet_config.backup_changes("PORTAGE_QUIET") |
795 |
- quiet_settings[myroot] = quiet_config |
796 |
- del quiet_config |
797 |
- for x in mylist: |
798 |
- if x[0] != "ebuild" or x[-1] == "nomerge": |
799 |
- continue |
800 |
- if not shown_verifying_msg: |
801 |
- shown_verifying_msg = True |
802 |
- print ">>> Verifying ebuild Manifests..." |
803 |
- mytype, myroot, mycpv, mystatus = x |
804 |
- portdb = self.trees[myroot]["porttree"].dbapi |
805 |
- quiet_config = quiet_settings[myroot] |
806 |
- quiet_config["O"] = os.path.dirname(portdb.findname(mycpv)) |
807 |
- if not portage.digestcheck([], quiet_config, strict=True): |
808 |
- return 1 |
809 |
- del x, mytype, myroot, mycpv, mystatus, quiet_config |
810 |
- del shown_verifying_msg, quiet_settings |
811 |
- |
812 |
root_config = self.trees[self.target_root]["root_config"] |
813 |
mymergelist = mylist |
814 |
myfeat = self.settings.features[:] |
815 |
|
816 |
Modified: main/branches/prefix/pym/portage/__init__.py |
817 |
=================================================================== |
818 |
--- main/branches/prefix/pym/portage/__init__.py 2008-07-03 06:39:20 UTC (rev 10903) |
819 |
+++ main/branches/prefix/pym/portage/__init__.py 2008-07-03 06:49:48 UTC (rev 10904) |
820 |
@@ -4923,6 +4923,7 @@ |
821 |
noauto = "noauto" in features |
822 |
from portage.data import secpass |
823 |
|
824 |
+ clean_phases = ("clean", "cleanrm") |
825 |
validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst", |
826 |
"config","info","setup","depend","fetch","digest", |
827 |
"unpack","compile","test","install","rpm","qmerge","merge", |
828 |
@@ -4939,7 +4940,7 @@ |
829 |
writemsg("\n", noiselevel=-1) |
830 |
return 1 |
831 |
|
832 |
- if not os.path.exists(myebuild): |
833 |
+ if mydo not in clean_phases and not os.path.exists(myebuild): |
834 |
writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo), |
835 |
noiselevel=-1) |
836 |
return 1 |
837 |
@@ -5036,7 +5037,6 @@ |
838 |
doebuild_environment(myebuild, mydo, myroot, mysettings, debug, |
839 |
use_cache, mydbapi) |
840 |
|
841 |
- clean_phases = ("clean", "cleanrm") |
842 |
if mydo in clean_phases: |
843 |
retval = spawn(_shell_quote(ebuild_sh_binary) + " clean", |
844 |
mysettings, debug=debug, free=1, logfile=None) |
845 |
|
846 |
Modified: main/branches/prefix/pym/portage/output.py |
847 |
=================================================================== |
848 |
--- main/branches/prefix/pym/portage/output.py 2008-07-03 06:39:20 UTC (rev 10903) |
849 |
+++ main/branches/prefix/pym/portage/output.py 2008-07-03 06:49:48 UTC (rev 10904) |
850 |
@@ -461,8 +461,10 @@ |
851 |
self.ewarn(msg[0]) |
852 |
if self.__last_e_cmd != "ebegin": |
853 |
self.__last_e_len = 0 |
854 |
- print "%*s%s" % ((self.term_columns - self.__last_e_len - 6), "", status_brackets) |
855 |
- sys.stdout.flush() |
856 |
+ out = sys.stdout |
857 |
+ out.write("%*s%s\n" % \ |
858 |
+ ((self.term_columns - self.__last_e_len - 6), "", status_brackets)) |
859 |
+ out.flush() |
860 |
|
861 |
def ebegin(self, msg): |
862 |
""" |
863 |
@@ -501,10 +503,12 @@ |
864 |
@param msg: A very brief (shorter than one line) error message. |
865 |
@type msg: StringType |
866 |
""" |
867 |
+ out = sys.stdout |
868 |
if not self.quiet: |
869 |
- if self.__last_e_cmd == "ebegin": print |
870 |
- print colorize("BAD", " * ") + msg |
871 |
- sys.stdout.flush() |
872 |
+ if self.__last_e_cmd == "ebegin": |
873 |
+ out.write("\n") |
874 |
+ out.write(colorize("BAD", " * ") + msg + "\n") |
875 |
+ out.flush() |
876 |
self.__last_e_cmd = "eerror" |
877 |
|
878 |
def einfo(self, msg): |
879 |
@@ -514,10 +518,12 @@ |
880 |
@param msg: A very brief (shorter than one line) informative message. |
881 |
@type msg: StringType |
882 |
""" |
883 |
+ out = sys.stdout |
884 |
if not self.quiet: |
885 |
- if self.__last_e_cmd == "ebegin": print |
886 |
- print colorize("GOOD", " * ") + msg |
887 |
- sys.stdout.flush() |
888 |
+ if self.__last_e_cmd == "ebegin": |
889 |
+ out.write("\n") |
890 |
+ out.write(colorize("GOOD", " * ") + msg + "\n") |
891 |
+ out.flush() |
892 |
self.__last_e_cmd = "einfo" |
893 |
|
894 |
def einfon(self, msg): |
895 |
@@ -527,10 +533,12 @@ |
896 |
@param msg: A very brief (shorter than one line) informative message. |
897 |
@type msg: StringType |
898 |
""" |
899 |
+ out = sys.stdout |
900 |
if not self.quiet: |
901 |
- if self.__last_e_cmd == "ebegin": print |
902 |
- print colorize("GOOD", " * ") + msg , |
903 |
- sys.stdout.flush() |
904 |
+ if self.__last_e_cmd == "ebegin": |
905 |
+ out.write("\n") |
906 |
+ out.write(colorize("GOOD", " * ") + msg) |
907 |
+ out.flush() |
908 |
self.__last_e_cmd = "einfon" |
909 |
|
910 |
def ewarn(self, msg): |
911 |
@@ -540,10 +548,12 @@ |
912 |
@param msg: A very brief (shorter than one line) warning message. |
913 |
@type msg: StringType |
914 |
""" |
915 |
+ out = sys.stdout |
916 |
if not self.quiet: |
917 |
- if self.__last_e_cmd == "ebegin": print |
918 |
- print colorize("WARN", " * ") + msg |
919 |
- sys.stdout.flush() |
920 |
+ if self.__last_e_cmd == "ebegin": |
921 |
+ out.write("\n") |
922 |
+ out.write(colorize("WARN", " * ") + msg + "\n") |
923 |
+ out.flush() |
924 |
self.__last_e_cmd = "ewarn" |
925 |
|
926 |
def ewend(self, errno, *msg): |
927 |
|
928 |
Modified: main/branches/prefix/pym/portage_compat_namespace.py |
929 |
=================================================================== |
930 |
--- main/branches/prefix/pym/portage_compat_namespace.py 2008-07-03 06:39:20 UTC (rev 10903) |
931 |
+++ main/branches/prefix/pym/portage_compat_namespace.py 2008-07-03 06:49:48 UTC (rev 10904) |
932 |
@@ -28,7 +28,7 @@ |
933 |
try: |
934 |
__package = __import__(__newname, globals(), locals()) |
935 |
__realmodule = getattr(__package, __newname[8:]) |
936 |
-except ImportError, AttributeError: |
937 |
+except (ImportError, AttributeError): |
938 |
raise ImportError("No module named %s" % __oldname) |
939 |
|
940 |
def _formatwarning(message, category, filename, lineno): |
941 |
|
942 |
-- |
943 |
gentoo-commits@l.g.o mailing list |