Record a slot atom in the world file for any atom that is precise enough to identify...
authorZac Medico <zmedico@gentoo.org>
Wed, 4 Jul 2007 02:31:12 +0000 (02:31 -0000)
committerZac Medico <zmedico@gentoo.org>
Wed, 4 Jul 2007 02:31:12 +0000 (02:31 -0000)
svn path=/main/trunk/; revision=7142

RELEASE-NOTES
pym/emerge/__init__.py

index faa5803163c2976a8fd6779837ba73c8b7b0600d..aa126269f108465924113cca43cfa99fb762d1ed 100644 (file)
@@ -7,9 +7,6 @@ portage-2.2
 * The python namespace for portage has been sanitized, all portage related code
   is now contained within the portage namespace. External script should be updated
   accordingly, though links exist for backward compability.
-* The "save_summary" and "echo" elog modules are now enabled by default. Setting
-  PORTAGE_ELOG_SYSTEM in make.conf will override this, so if you don't want elog
-  set PORTAGE_ELOG_SYSTEM="" in make.conf
 * -* support in package.keywords was changed as it was inconsistent with 
   ACCEPT_KEYWORDS behavior (also see http://dev.gentoo.org/~genone/docs/KEYWORDS.stupid).
   Previously having -* in package.keywords matched packages with KEYWORDS="-*", 
@@ -21,11 +18,20 @@ portage-2.2
 portage-2.1.3
 ==================================
 
+* The "save_summary" and "echo" elog modules are now enabled by default. Setting
+  PORTAGE_ELOG_SYSTEM in make.conf will override this, so if you don't want elog
+  set PORTAGE_ELOG_SYSTEM="" in make.conf
 * The unmerge process will remove any file that is not claimed by another
   package in the same slot and is not protected by CONFIG_PROTECT, even if the
   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
 ==================================
index ee0494f9b43343210ed4da083e8a6a60bf586ec8..875e53726080d3ec22516527d009f1c6056bc181 100644 (file)
@@ -674,6 +674,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("-"):
@@ -2420,9 +2449,12 @@ class depgraph(object):
                        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])
@@ -3181,10 +3213,11 @@ class depgraph(object):
                        "--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
@@ -3193,9 +3226,9 @@ class depgraph(object):
                        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)
@@ -3348,9 +3381,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
@@ -3447,7 +3479,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:
@@ -3637,13 +3669,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, " === ("+\
@@ -5160,10 +5191,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()
 
@@ -5201,29 +5233,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):