portage-2.2
-------------
+* Add link level dependency awareness to emerge --depclean and --prune actions
+ in order to protect against uninstallation of required libraries.
+ packages in the same way, and also drops any masked packages.
+* Add license visibility filtering (GLEP 23)
+* Add support for generic package sets (also see RELEASE-NOTES)
+
+portage-2.1.6
+-------------
+
* Add support for a new EAPI="2" value. For more information about new EAPI
features, refer to the "Ebuild" chapter of the html documentation that is
installed with portage.
as a decent substitute for module-rebuild.
* Namespace sanitizing: move all portage related code into portage.* namespace,
rename portage_foo modules to portage.foo (but keep symlinks for compability)
-* Add license visibility filtering (GLEP 23)
-* Experimental support for preserving old library files on package upgrades
- based on FEATURES=preserve-libs
* Add support for news items (GLEP 42)
-* Add support for generic package sets (also see RELEASE-NOTES)
portage-2.1.5
-------------
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.
-* -* 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="-*",
- now it resets the ACCEPT_KEYWORDS list for the given atom like it does when
- used in ACCEPT_KEYWORDS.
- For packages that don't specify any other KEYWORDS you can use the new ** token
- as documented in portage(5) to disable KEYWORDS filtering completely.
* Portage now warns if an ebuild repository does not have a name, as several new
features in 2.2 make use of or require named repositories. The repository name
is stored in profiles/repo_name in each repository.
* "world" does no longer include "system" unconditionally, but you can add
"@system" to the world_sets file to restore the old state.
+portage-2.1.6
+==================================
+
+* FEATURES=fixpackages is now enabled by default via make.globals. Set
+ FEATURES="-fixpackages" in make.conf if you'd like to disable it.
+* 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.
+* -* 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="-*",
+ now it resets the ACCEPT_KEYWORDS list for the given atom like it does when
+ used in ACCEPT_KEYWORDS.
+ For packages that don't specify any other KEYWORDS you can use the new ** token
+ as documented in portage(5) to disable KEYWORDS filtering completely.
+
portage-2.1.5
==================================
RESUMECOMMAND="wget -c -t 5 -T 60 --passive-ftp -O \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
# Default user options
-FEATURES="distlocks parallel-fetch protect-owned sandbox
+FEATURES="distlocks fixpackages parallel-fetch protect-owned sandbox
sfperms strict unmerge-orphans userfetch"
# Ignore file collisions in /lib/modules since files inside this directory
The list is a single entry specifying the full address of the directory
serving the tbz2's for your system. This is only used when running with
the get binary pkg options are given to \fBemerge\fR. Review \fBemerge\fR(1)
-for more information. For versions of portage less that 2.2, this variable
+for more information. For versions of portage less that 2.1.6, this variable
should point to the 'All' directory on the host that creates the binary
-packages and not to the root of the \fBPKGDIR\fR. Starting with portage 2.2,
+packages and not to the root of the \fBPKGDIR\fR. Starting with portage 2.1.6,
it should point to a directory containing a 'Packages' index file. If
${PORTAGE_BINHOST}/Packages does not exist then portage will attempt to use
the older protocol.
automatically, but support for backtracking (removal nodes that have
already been selected) will be required in order to handle all possible
cases.
-
- When a slot conflict occurs due to USE deps, there are a few
- different cases to consider:
-
- 1) New USE are correctly set but --newuse wasn't requested so an
- installed package with incorrect USE happened to get pulled
- into graph before the new one.
-
- 2) New USE are incorrectly set but an installed package has correct
- USE so it got pulled into the graph, and a new instance also got
- pulled in due to --newuse or an upgrade.
-
- 3) Multiple USE deps exist that can't be satisfied simultaneously,
- and multiple package instances got pulled into the same slot to
- satisfy the conflicting deps.
-
- TODO: Distinguish the above cases and tailor messages to suit them.
"""
if not self._slot_collision_info:
indent = " "
# Max number of parents shown, to avoid flooding the display.
max_parents = 3
+ explanation_columns = 70
+ explanations = 0
for (slot_atom, root), slot_nodes \
in self._slot_collision_info.iteritems():
msg.append(str(slot_atom))
else:
msg.append(" (no parents)\n")
msg.append("\n")
+ explanation = self._slot_conflict_explanation(slot_nodes)
+ if explanation:
+ explanations += 1
+ msg.append(indent + "Explanation:\n\n")
+ for line in textwrap.wrap(explanation, explanation_columns):
+ msg.append(2*indent + line + "\n")
+ msg.append("\n")
msg.append("\n")
sys.stderr.write("".join(msg))
sys.stderr.flush()
- if "--quiet" in self.myopts:
+ explanations_for_all = explanations == len(self._slot_collision_info)
+
+ if explanations_for_all or "--quiet" in self.myopts:
return
msg = []
f.end_paragraph(1)
f.writer.flush()
+ def _slot_conflict_explanation(self, slot_nodes):
+ """
+ When a slot conflict occurs due to USE deps, there are a few
+ different cases to consider:
+
+ 1) New USE are correctly set but --newuse wasn't requested so an
+ installed package with incorrect USE happened to get pulled
+ into graph before the new one.
+
+ 2) New USE are incorrectly set but an installed package has correct
+ USE so it got pulled into the graph, and a new instance also got
+ pulled in due to --newuse or an upgrade.
+
+ 3) Multiple USE deps exist that can't be satisfied simultaneously,
+ and multiple package instances got pulled into the same slot to
+ satisfy the conflicting deps.
+
+ Currently, explanations and suggested courses of action are generated
+ for cases 1 and 2. Case 3 is too complex to give a useful suggestion.
+ """
+
+ if len(slot_nodes) != 2:
+ # Suggestions are only implemented for
+ # conflicts between two packages.
+ return None
+
+ all_conflict_atoms = self._slot_conflict_parent_atoms
+ matched_node = None
+ matched_atoms = None
+ unmatched_node = None
+ for node in slot_nodes:
+ parent_atoms = self._parent_atoms.get(node)
+ if not parent_atoms:
+ # Normally, there are always parent atoms. If there are
+ # none then something unexpected is happening and there's
+ # currently no suggestion for this case.
+ return None
+ conflict_atoms = all_conflict_atoms.intersection(parent_atoms)
+ for parent_atom in conflict_atoms:
+ parent, atom = parent_atom
+ if not atom.use:
+ # Suggestions are currently only implemented for cases
+ # in which all conflict atoms have USE deps.
+ return None
+ if conflict_atoms:
+ if matched_node is not None:
+ # If conflict atoms match multiple nodes
+ # then there's no suggestion.
+ return None
+ matched_node = node
+ matched_atoms = conflict_atoms
+ else:
+ if unmatched_node is not None:
+ # Neither node is matched by conflict atoms, and
+ # there is no suggestion for this case.
+ return None
+ unmatched_node = node
+
+ if matched_node is None or unmatched_node is None:
+ # This shouldn't happen.
+ return None
+
+ if unmatched_node.installed and not matched_node.installed:
+ return "New USE are correctly set, but --newuse wasn't" + \
+ " requested, so an installed package with incorrect USE " + \
+ "happened to get pulled into the dependency graph. " + \
+ "In order to solve " + \
+ "this, either specify the --newuse option or explicitly " + \
+ " reinstall '%s'." % matched_node.slot_atom
+
+ if matched_node.installed and not unmatched_node.installed:
+ atoms = sorted(set(atom for parent, atom in matched_atoms))
+ explanation = ("New USE for '%s' are incorrectly set. " + \
+ "In order to solve this, adjust USE to satisfy '%s'") % \
+ (matched_node.slot_atom, atoms[0])
+ if len(atoms) > 1:
+ for atom in atoms[1:-1]:
+ explanation += ", '%s'" % (atom,)
+ if len(atoms) > 2:
+ explanation += ","
+ explanation += " and '%s'" % (atoms[-1],)
+ explanation += "."
+ return explanation
+
+ return None
+
def _process_slot_conflicts(self):
"""
Process slot conflict data to identify specific atoms which
def display_preserved_libs(vardbapi):
MAX_DISPLAY = 3
+ # Ensure the registry is consistent with existing files.
+ vardbapi.plib_registry.pruneNonExisting()
+
if vardbapi.plib_registry.hasEntries():
print
print colorize("WARN", "!!!") + " existing preserved libs:"
writemsg_stdout("\n\n")
writemsg_stdout(green("Performing Global Updates: ")+bold(mykey)+"\n")
writemsg_stdout("(Could take a couple of minutes if you have a lot of binary packages.)\n")
- writemsg_stdout(" "+bold(".")+"='update pass' "+bold("*")+"='binary update' "+bold("@")+"='/var/db move'\n"+" "+bold("s")+"='/var/db SLOT move' "+bold("%")+"='binary move' "+bold("S")+"='binary SLOT move'\n "+bold("p")+"='update /etc/portage/package.*'\n")
+ writemsg_stdout(" " + bold(".") + "='update pass' " + \
+ bold("*") + "='binary update' " + bold("#") + \
+ "='/var/db update' " + bold("@") + "='/var/db move'\n" + \
+ " " + bold("s") + "='/var/db SLOT move' " + \
+ bold("%") + "='binary move' " + bold("S") + \
+ "='binary SLOT move'\n " + \
+ bold("p") + "='update /etc/portage/package.*'\n")
valid_updates, errors = parse_updates(mycontent)
myupd.extend(valid_updates)
writemsg_stdout(len(valid_updates) * "." + "\n")
# We gotta do the brute force updates for these now.
if mysettings["PORTAGE_CALLER"] == "fixpackages" or \
"fixpackages" in mysettings.features:
- def onProgress(maxval, curval):
- writemsg_stdout("*")
- vardb.update_ents(myupd, onProgress=onProgress)
+ def onUpdate(maxval, curval):
+ if curval > 0:
+ writemsg_stdout("#")
+ vardb.update_ents(myupd, onUpdate=onUpdate)
if bindb:
- bindb.update_ents(myupd, onProgress=onProgress)
+ def onUpdate(maxval, curval):
+ if curval > 0:
+ writemsg_stdout("*")
+ bindb.update_ents(myupd, onUpdate=onUpdate)
else:
do_upgrade_packagesmessage = 1
else:
writemsg("!!! Invalid db entry: %s\n" % mypath, noiselevel=-1)
- def update_ents(self, updates, onProgress=None):
+ def update_ents(self, updates, onProgress=None, onUpdate=None):
"""
Update metadata of all packages for package moves.
@param updates: A list of move commands
@type updates: List
@param onProgress: A progress callback function
@type onProgress: a callable that takes 2 integer arguments: maxval and curval
+ @param onUpdate: A progress callback function called only
+ for packages that are modified by updates.
+ @type onUpdate: a callable that takes 2 integer arguments:
+ maxval and curval
"""
cpv_all = self.cpv_all()
cpv_all.sort()
update_keys = ["DEPEND", "RDEPEND", "PDEPEND", "PROVIDE"]
from itertools import izip
from portage.update import update_dbentries
+ if onUpdate:
+ onUpdate(maxval, 0)
if onProgress:
onProgress(maxval, 0)
for i, cpv in enumerate(cpv_all):
metadata_updates = update_dbentries(updates, metadata)
if metadata_updates:
aux_update(cpv, metadata_updates)
+ if onUpdate:
+ onUpdate(maxval, i+1)
if onProgress:
onProgress(maxval, i+1)
break
continue
self.vartree.dbapi.removeFromContents(cpv, removed)
+ else:
+ # Prune any preserved libs that may have
+ # been unmerged with this package.
+ self.vartree.dbapi.plib_registry.pruneNonExisting()
finally:
if builddir_lock: