summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--RELEASE-NOTES6
-rwxr-xr-xbin/emerge96
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):