Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r10087 - in main/branches/prefix/pym: _emerge portage portage/dbapi repoman
Date: Fri, 02 May 2008 14:37:05
Message-Id: E1JrwNh-0003Zp-6Q@stork.gentoo.org
1 Author: grobian
2 Date: 2008-05-02 14:36:59 +0000 (Fri, 02 May 2008)
3 New Revision: 10087
4
5 Modified:
6 main/branches/prefix/pym/_emerge/__init__.py
7 main/branches/prefix/pym/portage/dbapi/vartree.py
8 main/branches/prefix/pym/portage/manifest.py
9 main/branches/prefix/pym/repoman/checks.py
10 Log:
11 Merged from trunk 10000:10035
12
13 | 10001 | Bug #219369 - Enable automatic upgrage or downgrade to a |
14 | zmedico | version with visible KEYWORDS when the installed version is |
15 | | masked by KEYWORDS, but never reinstall the same exact |
16 | | version only due to a KEYWORDS mask. |
17
18 | 10003 | Never uninstall sys-apps/portage except through replacement. |
19 | zmedico | |
20
21 | 10005 | * Remove the only remaining sys.exit() calls inside the |
22 | zmedico | depgraph class. * Fix _unknown_internal_error() to work with |
23 | | zero arguments. |
24
25 | 10006 | Fix the EbuildQuote check to ignore "echo" and the elog |
26 | zmedico | functions since people might not want quotes in those cases. |
27
28 | 10007 | Bug #218854 - Fix depgraph._iter_atoms_for_pkg() so that |
29 | zmedico | argument atoms only match the highest visible slot. |
30
31 | 10008 | Add missing slot comparison when looking for higher slot in |
32 | zmedico | _iter_atoms_for_pkg(). |
33
34 | 10009 | Bug #211833 - When an ebuild removal phase fails, notify the |
35 | zmedico | user that removal of environment.bz2 file will cause the |
36 | | ebuild to be sourced and eclasses from the current portage |
37 | | tree will be used when necessary. |
38
39 | 10014 | Fix PackageVirtualDbapi.cpv_inject() to make sure packages |
40 | zmedico | with duplicate cpv or slot are handled correctly. |
41
42 | 10016 | Use write_atomic() for manifest updates. |
43 | zmedico | |
44
45 | 10018 | Try to format the elog message better for bug #211833, |
46 | zmedico | separating paragraphs for easier reading. |
47
48 | 10020 | Add comma to ("__weakref__",) so that it's a tuple instead |
49 | zmedico | of a string. Thanks to ferringb. |
50
51 | 10022 | As suggested by Chr. Schaefer in bug #211833, comment #15, |
52 | zmedico | note that removal of the environment.bz2 file is preferred |
53 | | since it may allow the removal phases to execute |
54 | | successfully. |
55
56 | 10024 | For bug #211833, be explicit that the pkg_prerm() and |
57 | zmedico | pkg_postrm() removal phases are the ones that are skipped. |
58
59 | 10026 | Add a Package.pv_split attibute to optimize version |
60 | zmedico | comparison operators. |
61
62 | 10028 | Fix spelling. |
63 | zmedico | |
64
65 | 10030 | When a package scheduled for uninstall isn't installed |
66 | zmedico | anymore, move on to the next task. |
67
68 | 10032 | Handle a potential KeyError in depgraph.display() when in |
69 | zmedico | --resume mode and a package scheduled for uninstall is no |
70 | | longer installed. |
71
72 | 10034 | Prevent some more visible downgrades from possibly being |
73 | zmedico | missed (bug #219369). |
74
75 | 10035 | Prevent some more visible downgrades from possibly being |
76 | zmedico | missed (bug #219369). |
77
78
79 Modified: main/branches/prefix/pym/_emerge/__init__.py
80 ===================================================================
81 --- main/branches/prefix/pym/_emerge/__init__.py 2008-05-02 10:46:47 UTC (rev 10086)
82 +++ main/branches/prefix/pym/_emerge/__init__.py 2008-05-02 14:36:59 UTC (rev 10087)
83 @@ -742,12 +742,13 @@
84 class RootConfig(object):
85 """This is used internally by depgraph to track information about a
86 particular $ROOT."""
87 - def __init__(self, trees, setconfig):
88 + def __init__(self, settings, trees, setconfig):
89 self.trees = trees
90 - self.settings = trees["vartree"].settings
91 + self.settings = settings
92 self.root = self.settings["ROOT"]
93 self.setconfig = setconfig
94 self.sets = self.setconfig.getSets()
95 + self.visible_pkgs = PackageVirtualDbapi(self.settings)
96
97 def create_world_atom(pkg_key, metadata, args_set, root_config):
98 """Create a new atom for the world file if one does not exist. If the
99 @@ -839,7 +840,7 @@
100 yield flag
101
102 class SlotObject(object):
103 - __slots__ = ("__weakref__")
104 + __slots__ = ("__weakref__",)
105
106 def __init__(self, **kwargs):
107 classes = [self.__class__]
108 @@ -1285,12 +1286,13 @@
109 class Package(Task):
110 __slots__ = ("built", "cpv", "depth",
111 "installed", "metadata", "root", "onlydeps", "type_name",
112 - "cp", "cpv_slot", "slot_atom")
113 + "cp", "cpv_slot", "pv_split", "slot_atom")
114 def __init__(self, **kwargs):
115 Task.__init__(self, **kwargs)
116 self.cp = portage.cpv_getkey(self.cpv)
117 self.slot_atom = "%s:%s" % (self.cp, self.metadata["SLOT"])
118 self.cpv_slot = "%s:%s" % (self.cpv, self.metadata["SLOT"])
119 + self.pv_split = portage.catpkgsplit(self.cpv)[1:]
120
121 def _get_hash_key(self):
122 hash_key = getattr(self, "_hash_key", None)
123 @@ -1303,23 +1305,33 @@
124 return self._hash_key
125
126 def __lt__(self, other):
127 - other_split = portage.catpkgsplit(other.cpv)
128 - self_split = portage.catpkgsplit(self.cpv)
129 - if other_split[:2] != self_split[:2]:
130 + if other.cp != self.cp:
131 return False
132 - if portage.pkgcmp(self_split[1:], other_split[1:]) < 0:
133 + if portage.pkgcmp(self.pv_split, other.pv_split) < 0:
134 return True
135 return False
136
137 + def __le__(self, other):
138 + if other.cp != self.cp:
139 + return False
140 + if portage.pkgcmp(self.pv_split, other.pv_split) <= 0:
141 + return True
142 + return False
143 +
144 def __gt__(self, other):
145 - other_split = portage.catpkgsplit(other.cpv)
146 - self_split = portage.catpkgsplit(self.cpv)
147 - if other_split[:2] != self_split[:2]:
148 + if other.cp != self.cp:
149 return False
150 - if portage.pkgcmp(self_split[1:], other_split[1:]) > 0:
151 + if portage.pkgcmp(self.pv_split, other.pv_split) > 0:
152 return True
153 return False
154
155 + def __ge__(self, other):
156 + if other.cp != self.cp:
157 + return False
158 + if portage.pkgcmp(self.pv_split, other.pv_split) >= 0:
159 + return True
160 + return False
161 +
162 class Uninstall(Package):
163 __slots__ = ()
164 def _get_hash_key(self):
165 @@ -1539,6 +1551,9 @@
166 return True
167 return False
168
169 + def match_pkgs(self, atom):
170 + return [self._cpv_map[cpv] for cpv in self.match(atom)]
171 +
172 def _clear_cache(self):
173 if self._categories is not None:
174 self._categories = None
175 @@ -1582,11 +1597,17 @@
176 if cp_list is None:
177 cp_list = []
178 self._cp_map[pkg.cp] = cp_list
179 + e_pkg = self._cpv_map.get(pkg.cpv)
180 + if e_pkg is not None:
181 + if e_pkg == pkg:
182 + return
183 + self.cpv_remove(e_pkg)
184 for e_pkg in cp_list:
185 if e_pkg.slot_atom == pkg.slot_atom:
186 if e_pkg == pkg:
187 return
188 self.cpv_remove(e_pkg)
189 + break
190 cp_list.append(pkg)
191 self._cpv_map[pkg.cpv] = pkg
192 self._clear_cache()
193 @@ -1646,9 +1667,15 @@
194 # to the graph.
195 self._graph_trees = {}
196 # All Package instances
197 - self._pkg_cache = {}
198 + self._pkg_cache = self._package_cache(self)
199 for myroot in trees:
200 self.trees[myroot] = {}
201 + # Create a RootConfig instance that references
202 + # the FakeVartree instead of the real one.
203 + self.roots[myroot] = RootConfig(
204 + trees[myroot]["vartree"].settings,
205 + self.trees[myroot],
206 + trees[myroot]["root_config"].setconfig)
207 for tree in ("porttree", "bintree"):
208 self.trees[myroot][tree] = trees[myroot][tree]
209 self.trees[myroot]["vartree"] = \
210 @@ -1659,10 +1686,6 @@
211 clone=self.trees[myroot]["vartree"].settings)
212 self._slot_pkg_map[myroot] = {}
213 vardb = self.trees[myroot]["vartree"].dbapi
214 - # Create a RootConfig instance that references
215 - # the FakeVartree instead of the real one.
216 - self.roots[myroot] = RootConfig(self.trees[myroot],
217 - trees[myroot]["root_config"].setconfig)
218 preload_installed_pkgs = "--nodeps" not in self.myopts and \
219 "--buildpkgonly" not in self.myopts
220 # This fakedbapi instance will model the state that the vdb will
221 @@ -2248,11 +2271,27 @@
222 if pkg.root != self.target_root:
223 return
224 atom_arg_map = self._atom_arg_map
225 + root_config = self.roots[pkg.root]
226 for atom in self._set_atoms.iterAtomsForPackage(pkg):
227 atom_cp = portage.dep_getkey(atom)
228 if atom_cp != pkg.cp and \
229 self._have_new_virt(pkg.root, atom_cp):
230 continue
231 + visible_pkgs = root_config.visible_pkgs.match_pkgs(atom)
232 + visible_pkgs.reverse() # descending order
233 + higher_slot = None
234 + for visible_pkg in visible_pkgs:
235 + if visible_pkg.cp != atom_cp:
236 + continue
237 + if pkg >= visible_pkg:
238 + # This is descending order, and we're not
239 + # interested in any versions <= pkg given.
240 + break
241 + if pkg.slot_atom != visible_pkg.slot_atom:
242 + higher_slot = visible_pkg
243 + break
244 + if higher_slot is not None:
245 + continue
246 for arg in atom_arg_map[(atom, pkg.root)]:
247 if isinstance(arg, PackageArg) and \
248 arg.package != pkg:
249 @@ -2570,14 +2609,14 @@
250 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
251 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
252 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
253 - sys.exit(1)
254 + return 0, myfavorites
255 except portage.exception.InvalidSignature, e:
256 portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
257 portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
258 portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
259 portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
260 portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
261 - sys.exit(1)
262 + return 0, myfavorites
263 except SystemExit, e:
264 raise # Needed else can't exit
265 except Exception, e:
266 @@ -2772,7 +2811,10 @@
267 # Make --noreplace take precedence over --newuse.
268 if not installed and noreplace and \
269 cpv in vardb.match(atom):
270 - break
271 + # If the installed version is masked, it may
272 + # be necessary to look at lower versions,
273 + # in case there is a visible downgrade.
274 + continue
275 reinstall_for_flags = None
276 cache_key = (pkg_type, root, cpv, pkg_status)
277 calculated_use = True
278 @@ -2820,6 +2862,26 @@
279 continue
280 except portage.exception.InvalidDependString:
281 continue
282 +
283 + # Enable upgrade or downgrade to a version
284 + # with visible KEYWORDS when the installed
285 + # version is masked by KEYWORDS, but never
286 + # reinstall the same exact version only due
287 + # to a KEYWORDS mask.
288 + if installed and matched_packages and \
289 + pkgsettings.getMissingKeywords(
290 + pkg.cpv, pkg.metadata):
291 + different_version = None
292 + for avail_pkg in matched_packages:
293 + if not portage.dep.cpvequal(
294 + pkg.cpv, avail_pkg.cpv):
295 + different_version = avail_pkg
296 + break
297 + if different_version is not None:
298 + # Only reinstall for KEYWORDS if
299 + # it's not the same version.
300 + continue
301 +
302 if not built and not calculated_use:
303 # This is avoided whenever possible because
304 # it's expensive.
305 @@ -2910,7 +2972,10 @@
306 if not reinstall_for_flags and \
307 not must_reinstall and \
308 cpv in vardb.match(atom):
309 - break
310 + # If the installed version is masked, it may
311 + # be necessary to look at lower versions,
312 + # in case there is a visible downgrade.
313 + continue
314 if not built:
315 myeb = cpv
316 matched_packages.append(pkg)
317 @@ -3558,6 +3623,10 @@
318 continue
319
320 if "/" == task.root:
321 + # Never uninstall sys-apps/portage
322 + # except through replacement.
323 + if "sys-apps/portage" == task.cp:
324 + continue
325 # For packages in the system set, don't take
326 # any chances. If the conflict can't be resolved
327 # by a normal replacement operation then abort.
328 @@ -3679,7 +3748,7 @@
329 print
330 print "!!! Note that circular dependencies can often be avoided by temporarily"
331 print "!!! disabling USE flags that trigger optional dependencies."
332 - sys.exit(1)
333 + raise self._unknown_internal_error()
334
335 # At this point, we've succeeded in selecting one or more nodes, so
336 # it's now safe to reset the prefer_asap and accept_root_node flags
337 @@ -4006,19 +4075,30 @@
338 else:
339 blockers.append(addl)
340 else:
341 - pkg = self._pkg_cache[tuple(x)]
342 - metadata = pkg.metadata
343 pkg_status = x[3]
344 pkg_merge = ordered and pkg_status == "merge"
345 if not pkg_merge and pkg_status == "merge":
346 pkg_status = "nomerge"
347 + built = pkg_type != "ebuild"
348 + installed = pkg_type == "installed"
349 + try:
350 + pkg = self._pkg_cache[tuple(x)]
351 + except KeyError:
352 + if pkg_status != "uninstall":
353 + raise
354 + # A package scheduled for uninstall apparently
355 + # isn't installed anymore. Since it's already
356 + # been uninstalled, move on to the next task.
357 + # This case should only be reachable in --resume
358 + # mode, since otherwise the package would have
359 + # been cached.
360 + continue
361 + metadata = pkg.metadata
362 ebuild_path = None
363 if pkg_type == "binary":
364 repo_name = self.roots[myroot].settings.get("PORTAGE_BINHOST")
365 else:
366 repo_name = metadata["repository"]
367 - built = pkg_type != "ebuild"
368 - installed = pkg_type == "installed"
369 if pkg_type == "ebuild":
370 ebuild_path = portdb.findname(pkg_key)
371 if not ebuild_path: # shouldn't happen
372 @@ -4684,7 +4764,11 @@
373 fakedb[myroot].cpv_inject(pkg)
374 self.spinner.update()
375
376 - class _unknown_internal_error(portage.exception.PortageException):
377 + class _internal_exception(portage.exception.PortageException):
378 + def __init__(self, value=""):
379 + portage.exception.PortageException.__init__(self, value)
380 +
381 + class _unknown_internal_error(_internal_exception):
382 """
383 Used by the depgraph internally to terminate graph creation.
384 The specific reason for the failure should have been dumped
385 @@ -4692,7 +4776,7 @@
386 may not be known.
387 """
388
389 - class _serialize_tasks_retry(portage.exception.PortageException):
390 + class _serialize_tasks_retry(_internal_exception):
391 """
392 This is raised by the _serialize_tasks() method when it needs to
393 be called again for some reason. The only case that it's currently
394 @@ -4824,6 +4908,17 @@
395 metadata = self._cpv_pkg_map[cpv].metadata
396 return [metadata.get(x, "") for x in wants]
397
398 + class _package_cache(dict):
399 + def __init__(self, depgraph):
400 + dict.__init__(self)
401 + self._depgraph = depgraph
402 +
403 + def __setitem__(self, k, v):
404 + dict.__setitem__(self, k, v)
405 + root_config = self._depgraph.roots[v.root]
406 + if visible(root_config.settings, v):
407 + root_config.visible_pkgs.cpv_inject(v)
408 +
409 class RepoDisplay(object):
410 def __init__(self, roots):
411 self._shown_repos = {}
412 @@ -5129,6 +5224,8 @@
413 myroot=x[1]
414 pkg_key = x[2]
415 pkgindex=2
416 + built = pkg_type != "ebuild"
417 + installed = pkg_type == "installed"
418 portdb = self.trees[myroot]["porttree"].dbapi
419 bindb = self.trees[myroot]["bintree"].dbapi
420 vartree = self.trees[myroot]["vartree"]
421 @@ -5151,10 +5248,16 @@
422 mydbapi = vardb
423 else:
424 raise AssertionError("Package type: '%s'" % pkg_type)
425 - metadata.update(izip(metadata_keys,
426 - mydbapi.aux_get(pkg_key, metadata_keys)))
427 - built = pkg_type != "ebuild"
428 - installed = pkg_type == "installed"
429 + try:
430 + metadata.update(izip(metadata_keys,
431 + mydbapi.aux_get(pkg_key, metadata_keys)))
432 + except KeyError:
433 + if not installed:
434 + raise
435 + # A package scheduled for uninstall apparently
436 + # isn't installed anymore. Since it's already
437 + # been uninstalled, move on to the next task.
438 + continue
439 if installed:
440 pkg_constructor = Uninstall
441 else:
442 @@ -7897,7 +8000,7 @@
443 for root, root_trees in trees.iteritems():
444 settings = root_trees["vartree"].settings
445 setconfig = load_default_config(settings, root_trees)
446 - root_trees["root_config"] = RootConfig(root_trees, setconfig)
447 + root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
448
449 settings = trees["/"]["vartree"].settings
450
451
452 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
453 ===================================================================
454 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-05-02 10:46:47 UTC (rev 10086)
455 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-05-02 14:36:59 UTC (rev 10087)
456 @@ -1317,16 +1317,40 @@
457 try:
458 if myebuildpath:
459 if retval != os.EX_OK:
460 + msg_lines = []
461 msg = ("The '%s' " % ebuild_phase) + \
462 ("phase of the '%s' package " % self.mycpv) + \
463 - ("has failed with exit value %s. " % retval) + \
464 - "The problem occurred while executing " + \
465 - ("the ebuild located at '%s'. " % myebuildpath) + \
466 - "If necessary, manually remove the ebuild " + \
467 - "in order to skip the execution of removal phases."
468 + ("has failed with exit value %s." % retval)
469 + from textwrap import wrap
470 + msg_lines.extend(wrap(msg, 72))
471 + msg_lines.append("")
472 +
473 + ebuild_name = os.path.basename(myebuildpath)
474 + ebuild_dir = os.path.dirname(myebuildpath)
475 + msg = "The problem occurred while executing " + \
476 + ("the ebuild file named '%s' " % ebuild_name) + \
477 + ("located in the '%s' directory. " \
478 + % ebuild_dir) + \
479 + "If necessary, manually remove " + \
480 + "the environment.bz2 file and/or the " + \
481 + "ebuild file located in that directory."
482 + msg_lines.extend(wrap(msg, 72))
483 + msg_lines.append("")
484 +
485 + msg = "Removal " + \
486 + "of the environment.bz2 file is " + \
487 + "preferred since it may allow the " + \
488 + "removal phases to execute successfully. " + \
489 + "The ebuild will be " + \
490 + "sourced and the eclasses " + \
491 + "from the current portage tree will be used " + \
492 + "when necessary. Removal of " + \
493 + "the ebuild file will cause the " + \
494 + "pkg_prerm() and pkg_postrm() removal " + \
495 + "phases to be skipped entirely."
496 + msg_lines.extend(wrap(msg, 72))
497 from portage.elog.messages import eerror
498 - from textwrap import wrap
499 - for l in wrap(msg, 72):
500 + for l in msg_lines:
501 eerror(l, phase=ebuild_phase, key=self.mycpv)
502
503 # process logs created during pre/postrm
504
505 Modified: main/branches/prefix/pym/portage/manifest.py
506 ===================================================================
507 --- main/branches/prefix/pym/portage/manifest.py 2008-05-02 10:46:47 UTC (rev 10086)
508 +++ main/branches/prefix/pym/portage/manifest.py 2008-05-02 14:36:59 UTC (rev 10087)
509 @@ -222,10 +222,8 @@
510 else:
511 raise
512 if update_manifest:
513 - fd = open(self.getFullname(), "w")
514 - for myentry in myentries:
515 - fd.write("%s\n" % str(myentry))
516 - fd.close()
517 + write_atomic(self.getFullname(),
518 + "".join("%s\n" % str(myentry) for myentry in myentries))
519 if sign:
520 self.sign()
521 except (IOError, OSError), e:
522
523 Modified: main/branches/prefix/pym/repoman/checks.py
524 ===================================================================
525 --- main/branches/prefix/pym/repoman/checks.py 2008-05-02 10:46:47 UTC (rev 10086)
526 +++ main/branches/prefix/pym/repoman/checks.py 2008-05-02 14:36:59 UTC (rev 10087)
527 @@ -76,7 +76,10 @@
528 """Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
529
530 repoman_check_name = 'ebuild.minorsyn'
531 - ignore_line = re.compile(r'(^$)|(^\s*#.*)|(^\s*\w+=.*)|(^\s*(local|export)\s+)')
532 + _ignored_commands = ["echo", "local", "export"]
533 + _ignored_commands += ["eerror", "einfo", "elog", "eqawarn", "ewarn"]
534 + ignore_line = re.compile(r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' + \
535 + r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
536 var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
537
538 # variables for games.eclass
539
540 --
541 gentoo-commits@l.g.o mailing list