def show_invalid_depstring_notice(parent_node, depstring, error_msg):
- from formatter import AbstractFormatter, DumbWriter
- f = AbstractFormatter(DumbWriter(maxcol=72))
-
- print "\n\n!!! Invalid or corrupt dependency specification: "
- print
- print error_msg
- print
- print parent_node
- print
- print depstring
- print
+ msg1 = "\n\n!!! Invalid or corrupt dependency specification: " + \
+ "\n\n%s\n\n%s\n\n%s\n\n" % (error_msg, parent_node, depstring)
p_type, p_root, p_key, p_status = parent_node
msg = []
if p_status == "nomerge":
msg.append("the problematic dependencies can be found in the ")
msg.append("*DEPEND files located in '%s/'." % pkg_location)
else:
- msg.append("This package can not be installed. ")
+ msg.append("This package can not be installed. ")
msg.append("Please notify the '%s' package maintainer " % p_key)
msg.append("about this problem.")
- for x in msg:
- f.add_flowing_data(x)
- f.end_paragraph(1)
+ msg2 = "".join("%s\n" % line for line in textwrap.wrap("".join(msg), 72))
+ writemsg_level(msg1 + msg2, level=logging.ERROR, noiselevel=-1)
class PackageVirtualDbapi(portage.dbapi):
"""
else:
return colorize("PKG_NOMERGE", pkg_str)
+ try:
+ properties = flatten(use_reduce(paren_reduce(
+ pkg.metadata["PROPERTIES"]), uselist=pkg.use.enabled))
+ except portage.exception.InvalidDependString, e:
+ if not pkg.installed:
+ show_invalid_depstring_notice(pkg,
+ pkg.metadata["PROPERTIES"], str(e))
+ del e
+ return 1
+ properties = []
+ interactive = "interactive" in properties
+ if interactive and pkg.operation == "merge":
+ addl = colorize("WARN", "I") + addl[1:]
+ if ordered:
+ counters.interactive += 1
+
if x[1]!="/":
if myoldbest:
myoldbest +=" "
self.totalsize = 0
self.restrict_fetch = 0
self.restrict_fetch_satisfied = 0
+ self.interactive = 0
def __str__(self):
total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
details.append("%s uninstall" % self.uninst)
if self.uninst > 1:
details[-1] += "s"
+ if self.interactive > 0:
+ details.append("%s %s" % (self.interactive,
+ colorize("WARN", "interactive")))
myoutput.append(", ".join(details))
if total_installs != 0:
myoutput.append(")")
def deallocate(self, settings):
self._deallocate(settings)
+ class _unknown_internal_error(portage.exception.PortageException):
+ """
+ Used internally to terminate scheduling. The specific reason for
+ the failure should have been dumped to stderr.
+ """
+ def __init__(self, value=""):
+ portage.exception.PortageException.__init__(self, value)
+
def __init__(self, settings, trees, mtimedb, myopts,
spinner, mergelist, favorites, digraph):
PollScheduler.__init__(self)
if max_jobs is None:
max_jobs = 1
self._set_max_jobs(max_jobs)
- background = self._background_mode()
- self._background = background
# The root where the currently running
# portage instance is installed.
self._config_pool = {}
self._blocker_db = {}
for root in trees:
- root_config = trees[root]["root_config"]
- if background:
- root_config.settings.unlock()
- root_config.settings["PORTAGE_BACKGROUND"] = "1"
- root_config.settings.backup_changes("PORTAGE_BACKGROUND")
- root_config.settings.lock()
-
- self.pkgsettings[root] = portage.config(
- clone=trees[root]["vartree"].settings)
self._config_pool[root] = []
self._blocker_db[root] = BlockerDB(trees[root]["root_config"])
if not (isinstance(task, Package) and \
task.operation == "merge"):
continue
- properties = flatten(use_reduce(paren_reduce(
- task.metadata["PROPERTIES"]), uselist=task.use.enabled))
+ try:
+ properties = flatten(use_reduce(paren_reduce(
+ task.metadata["PROPERTIES"]), uselist=task.use.enabled))
+ except portage.exception.InvalidDependString, e:
+ show_invalid_depstring_notice(task,
+ task.metadata["PROPERTIES"], str(e))
+ raise self._unknown_internal_error()
if "interactive" in properties:
interactive_tasks.append(task)
return interactive_tasks
graph = self._digraph
- for node in self._mergelist:
+ # Iterate over all nodes rather than just the merge list, because
+ # some uninstall nodes may not be in the merge list since they will
+ # be performed as part of an upgrade within a slot.
+ for node in graph.all_nodes():
if not isinstance(node, Package) or \
node.operation != "uninstall":
continue
self._logger.log(" *** Resuming merge...")
self._save_resume_list()
+
+ try:
+ self._background = self._background_mode()
+ except self._unknown_internal_error:
+ return 1
+
+ for root in self.trees:
+ root_config = self.trees[root]["root_config"]
+ if self._background:
+ root_config.settings.unlock()
+ root_config.settings["PORTAGE_BACKGROUND"] = "1"
+ root_config.settings.backup_changes("PORTAGE_BACKGROUND")
+ root_config.settings.lock()
+
+ self.pkgsettings[root] = portage.config(
+ clone=self.trees[root]["vartree"].settings)
+
rval = self._check_manifests()
if rval != os.EX_OK:
return rval
def _find_libs_to_preserve(self):
"""
- Get CONTENTS entries for libraries to be preserved. Returns a
- dict instance like that returned from getcontents().
+ Get set of relative paths for libraries to be preserved. The file
+ paths are selected from self._installed_instance.getcontents().
"""
if self._linkmap_broken or not \
(self._installed_instance is not None and \
old_contents = self._installed_instance.getcontents()
for f in list(preserve_paths):
f_abs = os.path.join(root, f.lstrip(os.sep))
- new_contents[f_abs] = old_contents[f_abs]
- if os.path.islink(f_abs):
- obj_type = "sym"
- else:
- obj_type = "obj"
+ contents_entry = old_contents.get(f_abs)
+ if contents_entry is None:
+ # This will probably never happen, but it might if one of the
+ # paths returned from findConsumers() refers to one of the libs
+ # that should be preserved yet the path is not listed in the
+ # contents. Such a path might belong to some other package, so
+ # it shouldn't be preserved here.
+ showMessage(("!!! File '%s' will not be preserved " + \
+ "due to missing contents entry\n") % (f_abs,),
+ level=logging.ERROR, noiselevel=-1)
+ preserve_paths.remove(f)
+ continue
+ new_contents[f_abs] = contents_entry
+ obj_type = contents_entry[0]
showMessage(">>> needed %s %s\n" % (obj_type, f_abs))
# Add parent directories to contents if necessary.
parent_dir = os.path.dirname(f_abs)
- while parent_dir != root:
+ while len(parent_dir) > len(root):
new_contents[parent_dir] = ["dir"]
prev = parent_dir
parent_dir = os.path.dirname(parent_dir)