From 46cadcc5eacedda76ccb3f5091e101a82083926e Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 4 Jul 2007 02:44:41 +0000 Subject: Record a slot atom in the world file for any atom that is precise enough to identify a specific slot. Make depclean clean unnecessary slots of system and world packages. For update and depclean, world atoms can be greedy with slots while system atoms can not. (trunk r7142) svn path=/main/branches/2.1.2/; revision=7143 --- RELEASE-NOTES | 6 ++++ bin/emerge | 96 ++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index f4baab289..f365277a0 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -12,6 +12,12 @@ portage-2.1.3 modification time or checksum differs from the file that was originally installed. The old behavior is still available by adding -unmerge-orphans to FEATURES. +* The world file now supports slot atoms such as 'sys-devel/gcc:3.4'. In some + cases, emerge --depclean may remove slots that it would not have removed + in the past. The emerge --noreplace command can be used to add an atom to the + world file and prevent matching packages from being removed. A slot atom + will be recorded in the world file for any atom that is precise enough to + identify a specific slot. portage-2.1.2 ================================== diff --git a/bin/emerge b/bin/emerge index a77004d2c..bb8f582c7 100755 --- a/bin/emerge +++ b/bin/emerge @@ -673,6 +673,35 @@ class WorldSet(AtomSet): portage_locks.unlockfile(self._lock) self._lock = None +def create_world_atom(pkg_key, metadata, args_set, world_set, portdb): + """Create a new atom for the world file if one does not exist. If the + argument atom is precise enough to identify a specific slot then a slot + atom will be returned. The system set is not used in deciding which + atoms to store since system atoms can only match one slot while world + atoms can be greedy with respect to slots.""" + arg_atom = args_set.findAtomForPackage(pkg_key, metadata) + cp = portage.dep_getkey(arg_atom) + new_world_atom = cp + if arg_atom != cp: + # If the user gave a specific atom, store it as a + # slot atom in the world file. + slot_atom = "%s:%s" % (cp, metadata["SLOT"]) + # First verify the slot is in the portage tree to avoid + # adding a bogus slot like that produced by multislot. + if portdb.match(slot_atom): + # Now verify that the argument is precise enough to identify a + # specific slot. + matches = portdb.match(arg_atom) + matched_slots = set() + for cpv in matches: + matched_slots.add(portdb.aux_get(cpv, ["SLOT"])[0]) + if len(matched_slots) == 1: + new_world_atom = slot_atom + if new_world_atom == world_set.findAtomForPackage(pkg_key, metadata): + # Both atoms would be identical, so there's nothing to add. + return None + return new_world_atom + def filter_iuse_defaults(iuse): for flag in iuse: if flag.startswith("+") or flag.startswith("-"): @@ -2389,9 +2418,12 @@ class depgraph: mykey = portage.dep_getkey(atom) if True: newlist.append(atom) - """Make sure all installed slots are updated when possible. - Do this with --emptytree also, to ensure that all slots are - remerged.""" + if mode == "world" and atom not in world_set: + # only world is greedy for slots, not system + continue + # Make sure all installed slots are updated when possible. + # Do this with --emptytree also, to ensure that all slots are + # remerged. myslots = set() for cpv in vardb.match(mykey): myslots.add(vardb.aux_get(cpv, ["SLOT"])[0]) @@ -3124,10 +3156,11 @@ class depgraph: "--oneshot", "--onlydeps", "--pretend"): if x in self.myopts: return - system_set = SystemSet(self.settings) world_set = WorldSet(self.settings) world_set.lock() world_set.load() + args_set = self._args_atoms + portdb = self.trees[self.target_root]["porttree"].dbapi added_favorites = set() for x in self._args_nodes: pkg_type, root, pkg_key, pkg_status = x @@ -3136,9 +3169,9 @@ class depgraph: metadata = dict(izip(self._mydbapi_keys, self.mydbapi[root].aux_get(pkg_key, self._mydbapi_keys))) try: - if not (system_set.findAtomForPackage(pkg_key, metadata) or \ - world_set.findAtomForPackage(pkg_key, metadata)): - myfavkey = portage.cpv_getkey(pkg_key) + myfavkey = create_world_atom(pkg_key, metadata, + args_set, world_set, portdb) + if myfavkey: if myfavkey in added_favorites: continue added_favorites.add(myfavkey) @@ -3290,9 +3323,8 @@ class MergeTask(object): del x, mytype, myroot, mycpv, mystatus, quiet_config del shown_verifying_msg, quiet_settings - #buildsyspkg: I need mysysdict also on resume (moved from the else block) system_set = SystemSet(self.settings) - favorites_set = AtomSet(favorites) + args_set = AtomSet(favorites) world_set = WorldSet(self.settings) if "--resume" not in self.myopts: mymergelist = mylist @@ -3389,7 +3421,7 @@ class MergeTask(object): #buildsyspkg: Check if we need to _force_ binary package creation issyspkg = ("buildsyspkg" in myfeat) \ and x[0] != "blocks" \ - and mysysdict.has_key(portage.cpv_getkey(x[2])) \ + and system_set.findAtomForPackage(pkg_key, metadata) \ and "--buildpkg" not in self.myopts if x[0] in ["ebuild","blocks"]: if x[0] == "blocks" and "--fetchonly" not in self.myopts: @@ -3575,13 +3607,12 @@ class MergeTask(object): self.trees[x[1]]["vartree"].inject(x[2]) myfavkey = portage.cpv_getkey(x[2]) if not fetchonly and not pretend and \ - favorites_set.findAtomForPackage(pkg_key, metadata): + args_set.findAtomForPackage(pkg_key, metadata): world_set.lock() world_set.load() - #don't record if already in system profile or already recorded - if not system_set.findAtomForPackage(pkg_key, metadata) and \ - not world_set.findAtomForPackage(pkg_key, metadata): - #we don't have a favorites entry for this package yet; add one + myfavkey = create_world_atom(pkg_key, metadata, + args_set, world_set, portdb) + if myfavkey: world_set.add(myfavkey) print ">>> Recording",myfavkey,"in \"world\" favorites file..." emergelog(xterm_titles, " === ("+\ @@ -5009,10 +5040,11 @@ def action_depclean(settings, trees, ldpath_mtimes, vardb = dep_check_trees[myroot]["vartree"].dbapi # Constrain dependency selection to the installed packages. dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"] - syslist = getlist(settings, "system") - worldlist = getlist(settings, "world") - system_and_world = AtomSet(syslist) - system_and_world.update(worldlist) + system_set = SystemSet(settings) + syslist = list(system_set) + world_set = WorldSet(settings) + world_set.load() + worldlist = list(world_set) fakedb = portage.fakedbapi(settings=settings) myvarlist = vardb.cpv_all() @@ -5050,29 +5082,11 @@ def action_depclean(settings, trees, ldpath_mtimes, if not atom.startswith("!") and priority == hard: unresolveable.setdefault(atom, []).append(parent) continue - system_or_world = False - if parent in ('world', 'system'): - system_or_world = True - else: - for pkg in pkgs: - metadata = dict(izip(metadata_keys, - vardb.aux_get(pkg, metadata_keys))) - try: - if system_and_world.findAtomForPackage(pkg, metadata): - system_or_world = True - break - except portage_exception.InvalidDependString, e: - writemsg("\n\n!!! '%s' has invalid PROVIDE: %s\n" % \ - (pkg, str(e)), noiselevel=-1) - writemsg("!!! see '%s'\n\n" % os.path.join( - myroot, portage.VDB_PATH, pkg, "PROVIDE"), - noiselevel=-1) - del e - if not system_or_world: + if len(pkgs) > 1 and parent != "world": # Prune all but the best matching slot, since that's all that a - # deep world update would pull in. Don't prune if the cpv is in - # system or world though, since those sets trigger greedy update - # of all slots. + # deep world update would pull in. Don't prune if this atom comes + # directly from world though, since world atoms are greedy when + # they don't specify a slot. pkgs = [portage.best(pkgs)] for pkg in pkgs: if fakedb.cpv_exists(pkg): -- cgit v1.2.3-1-g7c22