Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11674 - in main/branches/prefix: bin pym/_emerge pym/portage pym/portage/sets
Date: Sat, 11 Oct 2008 15:44:15
Message-Id: E1KogdX-0003Rl-Mi@stork.gentoo.org
1 Author: grobian
2 Date: 2008-10-11 15:44:10 +0000 (Sat, 11 Oct 2008)
3 New Revision: 11674
4
5 Modified:
6 main/branches/prefix/bin/repoman
7 main/branches/prefix/pym/_emerge/__init__.py
8 main/branches/prefix/pym/portage/__init__.py
9 main/branches/prefix/pym/portage/sets/__init__.py
10 Log:
11 Merged from trunk -r11635:11654
12
13 | 11636 | Bug #240022 - Avoid duplicate output for the same library |
14 | zmedico | (due to symlinks) in display_preserved_libs() by using |
15 | | os.path.realpath() to group duplicate references together. |
16 | | Thanks to Fabian Groffen <grobian@g.o> for the initial |
17 | | patch. |
18
19 | 11637 | Fix KeyError raised from display_preserved_libs() when the |
20 | zmedico | realpath is used as a key in consumer_map instead of the |
21 | | orignal path that was returned from the |
22 | | PreservedLibsRegistry. |
23
24 | 11642 | In order to avoid "waiting for lock" messages at the |
25 | zmedico | beginning, which annoy users, never spawn a prefetcher for |
26 | | the first package. |
27
28 | 11643 | In doebuild(), don't create build dirs when "listonly" fetch |
29 | zmedico | mode. |
30
31 | 11644 | In fetch(), never call the pkg_nofetch phase when in |
32 | zmedico | "listonly" mode. |
33
34 | 11645 | Bug #234301 - Add support to EbuildFetcher to collect elog |
35 | zmedico | messages that might be generated during the pkg_nofetch |
36 | | phase. This involves maintaining a lock on PORTAGE_BUILDDIR |
37 | | where the elog messages are collected, and cleaning up |
38 | | PORTAGE_BUILDDIR before releasing the lock. |
39
40 | 11646 | Fix EbuildFetcher._wait_hook() so it can be called more than |
41 | zmedico | once without throwing an AttributeError. |
42
43 | 11647 | Make EbuildFetcher direct fetch output to the normal build |
44 | zmedico | log. By keeping the output in the build log instead of the |
45 | | global emerge-fetch.log file, output from a possible fetch |
46 | | failure can be recovered and displayed later. TODO: Convert |
47 | | failed fetch to elog message as suggested in bug #234301. |
48
49 | 11648 | Make EbuildFetcher clean up the build dir after failures in |
50 | zmedico | fetchonly mode since the log is in emerge-fetch.log anyway. |
51
52 | 11649 | When EbuildBuild encounters a failed fetch, propagee the log |
53 | zmedico | path so that it can be properly displayed in the status |
54 | | display. |
55
56 | 11650 | Make HOMEPAGE.missing fatal again since, in cases when |
57 | zmedico | homepages are no longer available, we can use a link to some |
58 | | site like packages.gentoo.org or |
59 | | www.unmaintained-free-software.org. |
60
61 | 11651 | Change the "qawarnings" variable from a list to a set. |
62 | zmedico | |
63
64 | 11652 | Make "qawarnings" a normal set since the missingvars code |
65 | zmedico | might modify it. |
66
67 | 11653 | Instead of using inheritance, reference the ConfigParser |
68 | zmedico | part of SetConfig as an attribute in case we want to swap |
69 | | out the ConfigParser implemention and no longer want to |
70 | | implement the whole interface. |
71
72 | 11654 | Generate elog messages for failed fetches. This restores |
73 | zmedico | some functionality that was removed in r11645. |
74
75
76 Modified: main/branches/prefix/bin/repoman
77 ===================================================================
78 --- main/branches/prefix/bin/repoman 2008-10-10 22:02:15 UTC (rev 11673)
79 +++ main/branches/prefix/bin/repoman 2008-10-11 15:44:10 UTC (rev 11674)
80 @@ -320,7 +320,7 @@
81 qacats = qahelp.keys()
82 qacats.sort()
83
84 -qawarnings=[
85 +qawarnings = set((
86 "changelog.ebuildadded",
87 "changelog.missing",
88 "changelog.notadded",
89 @@ -337,7 +337,6 @@
90 "KEYWORDS.dropped",
91 "KEYWORDS.stupid",
92 "KEYWORDS.missing",
93 -"HOMEPAGE.missing",
94 "IUSE.invalid",
95 "IUSE.undefined",
96 "RDEPEND.suspect",
97 @@ -356,7 +355,7 @@
98 "virtual.unavailable",
99 "usage.obsolete",
100 "LIVEVCS.stable"
101 -]
102 +))
103
104 missingvars=["KEYWORDS","LICENSE","DESCRIPTION","HOMEPAGE","SLOT"]
105 allvars = set(x for x in portage.auxdbkeys if not x.startswith("UNUSED_"))
106 @@ -369,7 +368,7 @@
107 if x not in qacats:
108 logging.warn('* missingvars values need to be added to qahelp ("%s")' % x)
109 qacats.append(x)
110 - qawarnings.append(x)
111 + qawarnings.add(x)
112
113 valid_restrict = frozenset(["binchecks", "bindist",
114 "fetch", "installsources", "mirror",
115
116 Modified: main/branches/prefix/pym/_emerge/__init__.py
117 ===================================================================
118 --- main/branches/prefix/pym/_emerge/__init__.py 2008-10-10 22:02:15 UTC (rev 11673)
119 +++ main/branches/prefix/pym/_emerge/__init__.py 2008-10-11 15:44:10 UTC (rev 11674)
120 @@ -2265,14 +2265,20 @@
121
122 class EbuildFetcher(SpawnProcess):
123
124 - __slots__ = ("fetchonly", "fetchall", "pkg",)
125 + __slots__ = ("config_pool", "fetchonly", "fetchall", "pkg", "prefetch") + \
126 + ("_build_dir",)
127
128 def _start(self):
129
130 root_config = self.pkg.root_config
131 portdb = root_config.trees["porttree"].dbapi
132 ebuild_path = portdb.findname(self.pkg.cpv)
133 - settings = root_config.settings
134 + settings = self.config_pool.allocate()
135 + self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings)
136 + self._build_dir.lock()
137 + if self.logfile is None:
138 + self.logfile = settings.get("PORTAGE_LOG_FILE")
139 +
140 phase = "fetch"
141 if self.fetchall:
142 phase = "fetchall"
143 @@ -2284,7 +2290,7 @@
144 fetch_env = os.environ.copy()
145
146 fetch_env["PORTAGE_NICENESS"] = "0"
147 - if self.fetchonly:
148 + if self.prefetch:
149 fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1"
150
151 ebuild_binary = os.path.join(
152 @@ -2299,6 +2305,34 @@
153 self.env = fetch_env
154 SpawnProcess._start(self)
155
156 + def _set_returncode(self, wait_retval):
157 + SpawnProcess._set_returncode(self, wait_retval)
158 + # Collect elog messages that might have been
159 + # created by the pkg_nofetch phase.
160 + if self._build_dir is not None:
161 + # Skip elog messages for prefetch, in order to avoid duplicates.
162 + if not self.prefetch and self.returncode != os.EX_OK:
163 + elog_out = None
164 + if self.logfile is not None:
165 + if self.background:
166 + elog_out = open(self.logfile, 'a')
167 + eerror("Fetch failed for '%s'" % self.pkg.cpv,
168 + phase="unpack", key=self.pkg.cpv, out=elog_out)
169 + if elog_out is not None:
170 + elog_out.close()
171 + if not self.prefetch:
172 + portage.elog.elog_process(self.pkg.cpv, self._build_dir.settings)
173 + if self.fetchonly or self.returncode == os.EX_OK:
174 + try:
175 + shutil.rmtree(self._build_dir.settings["PORTAGE_BUILDDIR"])
176 + except EnvironmentError, e:
177 + if e.errno != errno.ENOENT:
178 + raise
179 + del e
180 + self._build_dir.unlock()
181 + self.config_pool.deallocate(self._build_dir.settings)
182 + self._build_dir = None
183 +
184 class EbuildBuildDir(SlotObject):
185
186 __slots__ = ("dir_path", "pkg", "settings",
187 @@ -2324,11 +2358,13 @@
188 portdb = root_config.trees["porttree"].dbapi
189 ebuild_path = portdb.findname(self.pkg.cpv)
190 settings = self.settings
191 + settings.setcpv(self.pkg)
192 debug = settings.get("PORTAGE_DEBUG") == "1"
193 use_cache = 1 # always true
194 portage.doebuild_environment(ebuild_path, "setup", root_config.root,
195 self.settings, debug, use_cache, portdb)
196 dir_path = self.settings["PORTAGE_BUILDDIR"]
197 + portage.prepare_build_dirs(self.pkg.root, self.settings, 0)
198
199 catdir = os.path.dirname(dir_path)
200 self._catdir = catdir
201 @@ -2376,7 +2412,7 @@
202
203 class EbuildBuild(CompositeTask):
204
205 - __slots__ = ("args_set", "background", "find_blockers",
206 + __slots__ = ("args_set", "config_pool", "find_blockers",
207 "ldpath_mtimes", "logger", "opts", "pkg", "pkg_count",
208 "prefetcher", "settings", "world_atom") + \
209 ("_build_dir", "_buildpkg", "_ebuild_path", "_issyspkg", "_tree")
210 @@ -2439,10 +2475,9 @@
211 return
212
213 fetch_log = None
214 - if self.background:
215 - fetch_log = self.scheduler.fetch.log_file
216
217 - fetcher = EbuildFetcher(fetchall=opts.fetch_all_uri,
218 + fetcher = EbuildFetcher(config_pool=self.config_pool,
219 + fetchall=opts.fetch_all_uri,
220 fetchonly=opts.fetchonly,
221 background=self.background, logfile=fetch_log,
222 pkg=pkg, scheduler=self.scheduler)
223 @@ -2455,19 +2490,20 @@
224 self._start_task(fetcher, self._fetch_exit)
225
226 def _fetch_exit(self, fetcher):
227 -
228 opts = self.opts
229 pkg = self.pkg
230
231 + fetch_failed = False
232 if opts.fetchonly:
233 - if self._final_exit(fetcher) != os.EX_OK:
234 - if not self.background:
235 - eerror("Fetch for %s failed, continuing..." % pkg.cpv,
236 - phase="unpack", key=pkg.cpv)
237 - self.wait()
238 - return
239 + fetch_failed = self._final_exit(fetcher) != os.EX_OK
240 + else:
241 + fetch_failed = self._default_exit(fetcher) != os.EX_OK
242
243 - if self._default_exit(fetcher) != os.EX_OK:
244 + if fetch_failed and fetcher.logfile is not None and \
245 + os.path.exists(fetcher.logfile):
246 + self.settings["PORTAGE_LOG_FILE"] = fetcher.logfile
247 +
248 + if fetch_failed or opts.fetchonly:
249 self.wait()
250 return
251
252 @@ -3466,7 +3502,7 @@
253 """
254
255 __slots__ = ("args_set",
256 - "binpkg_opts", "build_opts", "emerge_opts",
257 + "binpkg_opts", "build_opts", "config_pool", "emerge_opts",
258 "failed_fetches", "find_blockers", "logger", "mtimedb", "pkg",
259 "pkg_count", "pkg_to_replace", "prefetcher",
260 "settings", "statusMessage", "world_atom") + \
261 @@ -3519,6 +3555,7 @@
262
263 build = EbuildBuild(args_set=args_set,
264 background=self.background,
265 + config_pool=self.config_pool,
266 find_blockers=find_blockers,
267 ldpath_mtimes=ldpath_mtimes, logger=logger,
268 opts=build_opts, pkg=pkg, pkg_count=pkg_count,
269 @@ -8990,6 +9027,21 @@
270 __slots__ = ("build_dir", "build_log",
271 "fetch_log", "pkg", "returncode")
272
273 + class _ConfigPool(object):
274 + """Interface for a task to temporarily allocate a config
275 + instance from a pool. This allows a task to be constructed
276 + long before the config instance actually becomes needed, like
277 + when prefetchers are constructed for the whole merge list."""
278 + __slots__ = ("_root", "_allocate", "_deallocate")
279 + def __init__(self, root, allocate, deallocate):
280 + self._root = root
281 + self._allocate = allocate
282 + self._deallocate = deallocate
283 + def allocate(self):
284 + return self._allocate(self._root)
285 + def deallocate(self, settings):
286 + self._deallocate(settings)
287 +
288 def __init__(self, settings, trees, mtimedb, myopts,
289 spinner, mergelist, favorites, digraph):
290 PollScheduler.__init__(self)
291 @@ -9389,7 +9441,10 @@
292 prefetchers = self._prefetchers
293 getbinpkg = "--getbinpkg" in self.myopts
294
295 - for pkg in self._mergelist:
296 + # In order to avoid "waiting for lock" messages
297 + # at the beginning, which annoy users, never
298 + # spawn a prefetcher for the first package.
299 + for pkg in self._mergelist[1:]:
300 prefetcher = self._create_prefetcher(pkg)
301 if prefetcher is not None:
302 self._task_queues.fetch.add(prefetcher)
303 @@ -9407,8 +9462,10 @@
304 elif pkg.type_name == "ebuild":
305
306 prefetcher = EbuildFetcher(background=True,
307 + config_pool=self._ConfigPool(pkg.root,
308 + self._allocate_config, self._deallocate_config),
309 fetchonly=1, logfile=self._fetch_log,
310 - pkg=pkg, scheduler=self._sched_iface)
311 + pkg=pkg, prefetch=True, scheduler=self._sched_iface)
312
313 elif pkg.type_name == "binary" and \
314 "--getbinpkg" in self.myopts and \
315 @@ -10044,6 +10101,8 @@
316 task = MergeListItem(args_set=self._args_set,
317 background=self._background, binpkg_opts=self._binpkg_opts,
318 build_opts=self._build_opts,
319 + config_pool=self._ConfigPool(pkg.root,
320 + self._allocate_config, self._deallocate_config),
321 emerge_opts=self.myopts,
322 failed_fetches=self._failed_fetches,
323 find_blockers=self._find_blockers(pkg), logger=self._logger,
324 @@ -11000,8 +11059,20 @@
325
326 for cpv in plibdata:
327 print colorize("WARN", ">>>") + " package: %s" % cpv
328 + samefile_map = {}
329 for f in plibdata[cpv]:
330 - print colorize("WARN", " * ") + " - %s" % f
331 + real_path = os.path.realpath(f)
332 + alt_paths = samefile_map.get(real_path)
333 + if alt_paths is None:
334 + alt_paths = set()
335 + samefile_map[real_path] = alt_paths
336 + alt_paths.add(f)
337 +
338 + for alt_paths in samefile_map.itervalues():
339 + alt_paths = sorted(alt_paths)
340 + for p in alt_paths:
341 + print colorize("WARN", " * ") + " - %s" % (p,)
342 + f = alt_paths[0]
343 consumers = consumer_map[f]
344 for c in consumers[:MAX_DISPLAY]:
345 print colorize("WARN", " * ") + " used by %s (%s)" % \
346
347 Modified: main/branches/prefix/pym/portage/__init__.py
348 ===================================================================
349 --- main/branches/prefix/pym/portage/__init__.py 2008-10-10 22:02:15 UTC (rev 11673)
350 +++ main/branches/prefix/pym/portage/__init__.py 2008-10-11 15:44:10 UTC (rev 11674)
351 @@ -4077,7 +4077,7 @@
352
353 if listonly:
354 writemsg_stdout("\n", noiselevel=-1)
355 - if fetched != 2:
356 + elif fetched != 2:
357 if restrict_fetch:
358 print "\n!!!", mysettings["CATEGORY"] + "/" + \
359 mysettings["PF"], "has fetch restriction turned on."
360 @@ -4095,8 +4095,6 @@
361 mysettings.pop("EBUILD_PHASE", None)
362 else:
363 mysettings["EBUILD_PHASE"] = ebuild_phase
364 - elif listonly:
365 - continue
366 elif not filedict[myfile]:
367 writemsg("Warning: No mirrors available for file" + \
368 " '%s'\n" % (myfile), noiselevel=-1)
369 @@ -5478,7 +5476,8 @@
370
371 # Build directory creation isn't required for any of these.
372 have_build_dirs = False
373 - if mydo not in ("digest", "help", "manifest"):
374 + if not (mydo in ("digest", "help", "manifest") or \
375 + (mydo == "fetch" and listonly)):
376 mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
377 if mystatus:
378 return mystatus
379 @@ -5671,16 +5670,6 @@
380 if not emerge_skip_distfiles and \
381 need_distfiles and not fetch(
382 fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
383 - if have_build_dirs:
384 - # Create an elog message for this fetch failure since the
385 - # mod_echo module might push the original message off of the
386 - # top of the terminal and prevent the user from being able to
387 - # see it.
388 - from portage.elog.messages import eerror
389 - eerror("Fetch failed for '%s'" % mycpv,
390 - phase="unpack", key=mycpv)
391 - from portage.elog import elog_process
392 - elog_process(mysettings.mycpv, mysettings)
393 return 1
394
395 if mydo == "fetch" and listonly:
396
397 Modified: main/branches/prefix/pym/portage/sets/__init__.py
398 ===================================================================
399 --- main/branches/prefix/pym/portage/sets/__init__.py 2008-10-10 22:02:15 UTC (rev 11673)
400 +++ main/branches/prefix/pym/portage/sets/__init__.py 2008-10-11 15:44:10 UTC (rev 11674)
401 @@ -22,10 +22,10 @@
402 class SetConfigError(Exception):
403 pass
404
405 -class SetConfig(SafeConfigParser):
406 +class SetConfig(object):
407 def __init__(self, paths, settings, trees):
408 - SafeConfigParser.__init__(self)
409 - self.read(paths)
410 + self._parser = SafeConfigParser()
411 + self._parser.read(paths)
412 self.errors = []
413 self.psets = {}
414 self.trees = trees
415 @@ -34,6 +34,7 @@
416 self.active = []
417
418 def update(self, setname, options):
419 + parser = self._parser
420 self.errors = []
421 if not setname in self.psets:
422 options["name"] = setname
423 @@ -41,30 +42,32 @@
424
425 # for the unlikely case that there is already a section with the requested setname
426 import random
427 - while setname in self.sections():
428 + while setname in parser.sections():
429 setname = "%08d" % random.randint(0, 10**10)
430
431 - self.add_section(setname)
432 + parser.add_section(setname)
433 for k, v in options.items():
434 - self.set(setname, k, v)
435 + parser.set(setname, k, v)
436 else:
437 section = self.psets[setname].creator
438 - if self.has_option(section, "multiset") and self.getboolean(section, "multiset"):
439 + if parser.has_option(section, "multiset") and \
440 + parser.getboolean(section, "multiset"):
441 self.errors.append("Invalid request to reconfigure set '%s' generated by multiset section '%s'" % (setname, section))
442 return
443 for k, v in options.items():
444 - self.set(section, k, v)
445 + parser.set(section, k, v)
446 self._parse(update=True)
447
448 def _parse(self, update=False):
449 if self._parsed and not update:
450 return
451 - for sname in self.sections():
452 + parser = self._parser
453 + for sname in parser.sections():
454 # find classname for current section, default to file based sets
455 - if not self.has_option(sname, "class"):
456 + if not parser.has_option(sname, "class"):
457 classname = "portage.sets.files.StaticFileSet"
458 else:
459 - classname = self.get(sname, "class")
460 + classname = parser.get(sname, "class")
461
462 # try to import the specified class
463 try:
464 @@ -77,11 +80,12 @@
465 continue
466 # prepare option dict for the current section
467 optdict = {}
468 - for oname in self.options(sname):
469 - optdict[oname] = self.get(sname, oname)
470 + for oname in parser.options(sname):
471 + optdict[oname] = parser.get(sname, oname)
472
473 # create single or multiple instances of the given class depending on configuration
474 - if self.has_option(sname, "multiset") and self.getboolean(sname, "multiset"):
475 + if parser.has_option(sname, "multiset") and \
476 + parser.getboolean(sname, "multiset"):
477 if hasattr(setclass, "multiBuilder"):
478 newsets = {}
479 try:
480 @@ -93,7 +97,8 @@
481 if x in self.psets and not update:
482 self.errors.append("Redefinition of set '%s' (sections: '%s', '%s')" % (x, self.psets[x].creator, sname))
483 newsets[x].creator = sname
484 - if self.has_option(sname, "world-candidate") and not self.getboolean(sname, "world-candidate"):
485 + if parser.has_option(sname, "world-candidate") and \
486 + not parser.getboolean(sname, "world-candidate"):
487 newsets[x].world_candidate = False
488 self.psets.update(newsets)
489 else:
490 @@ -101,7 +106,7 @@
491 continue
492 else:
493 try:
494 - setname = self.get(sname, "name")
495 + setname = parser.get(sname, "name")
496 except NoOptionError:
497 setname = sname
498 if setname in self.psets and not update:
499 @@ -110,7 +115,8 @@
500 try:
501 self.psets[setname] = setclass.singleBuilder(optdict, self.settings, self.trees)
502 self.psets[setname].creator = sname
503 - if self.has_option(sname, "world-candidate") and not self.getboolean(sname, "world-candidate"):
504 + if parser.has_option(sname, "world-candidate") and \
505 + not parser.getboolean(sname, "world-candidate"):
506 self.psets[setname].world_candidate = False
507 except SetConfigError, e:
508 self.errors.append("Configuration error in section '%s': %s" % (sname, str(e)))
509 @@ -127,7 +133,7 @@
510 def getSetAtoms(self, setname, ignorelist=None):
511 myset = self.getSets()[setname]
512 myatoms = myset.getAtoms()
513 -
514 + parser = self._parser
515 extend = set()
516 remove = set()
517 intersect = set()
518 @@ -135,12 +141,12 @@
519 if ignorelist is None:
520 ignorelist = set()
521 if not setname in ignorelist:
522 - if self.has_option(myset.creator, "extend"):
523 - extend.update(self.get(myset.creator, "extend").split())
524 - if self.has_option(myset.creator, "remove"):
525 - remove.update(self.get(myset.creator, "remove").split())
526 - if self.has_option(myset.creator, "intersect"):
527 - intersect.update(self.get(myset.creator, "intersect").split())
528 + if parser.has_option(myset.creator, "extend"):
529 + extend.update(parser.get(myset.creator, "extend").split())
530 + if parser.has_option(myset.creator, "remove"):
531 + remove.update(parser.get(myset.creator, "remove").split())
532 + if parser.has_option(myset.creator, "intersect"):
533 + intersect.update(parser.get(myset.creator, "intersect").split())
534
535 ignorelist.add(setname)
536 for n in myset.getNonAtoms():