From: Fabian Groffen Date: Sun, 24 Dec 2006 09:53:02 +0000 (-0000) Subject: Merged from trunk 5336:5350 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=f1da11b40ddbba64dc04fb81cfb2501f2fe604f0;p=portage.git Merged from trunk 5336:5350 For bug #158649, minimize portdb cache pulls for installed packages when --nodeps is enabled. This patch also allows the vardb lock to be released before doing any cache pulls (even when --nodeps is not enabled), and updates the spinner while the metadata is being pulled. More intelligently handle CacheCorruption errors in the writable cache. For bug #158558, ignore invalid depstrings for packages that are being replaced anyway (otherwise the user would be forced to manually unmerge the package). When a removal phase fails, tell the user where the ebuild is and advise them that the ebuild can be removed in order to skip the removal phases. For installed packages with invalid depstrings, tell the user the location of the *DEPEND files. For bug #158632, make aux_get caching safe for missing values in cache entries. For bug #158658, fix the 'TypeError: int argument required' that happens in the finalize() routine. Use the return value from setdefault to avoid an extra dict lookup. Create a backward compatibility mode for dep_check() so that emerge can use it to gracefully deal with installed packages that have invalid atoms or dep syntax. Make emerge enable backward compatibility mode for dep_check() calls on installed packages so that it can gracefully invalid atoms or dep syntax. Fix the "help" phase so that it works without build dirs. For bug #158649, allow --buildpkgonly to bypass the fakedb population like --nodeps does. Revert the default choice for --ask --unmerge (bug #158354) because people are complaining. Use a pipe instead of a temp file for the depend phase. svn path=/main/branches/prefix/; revision=5373 --- diff --git a/bin/ebuild.sh b/bin/ebuild.sh index e9ffea3dd..8e8c3dd96 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1759,39 +1759,33 @@ for myarg in ${EBUILD_SH_ARGS} ; do export SANDBOX_ON="0" set -f - # Handled in portage.py now - #dbkey=${PORTAGE_CACHEDIR}/${CATEGORY}/${PF} - - if [ ! -d "${dbkey%/*}" ]; then - install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}" + if [ -n "${dbkey}" ] ; then + if [ ! -d "${dbkey%/*}" ]; then + install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}" + fi + # Make it group writable. 666&~002==664 + umask 002 fi - # Make it group writable. 666&~002==664 - umask 002 + auxdbkeys="DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE + DESCRIPTION KEYWORDS INHERITED IUSE CDEPEND PDEPEND PROVIDE EAPI + UNUSED_01 UNUSED_02 UNUSED_03 UNUSED_04 UNUSED_05 UNUSED_06 + UNUSED_07" #the extra $(echo) commands remove newlines - echo $(echo "$DEPEND") > $dbkey - echo $(echo "$RDEPEND") >> $dbkey - echo $(echo "$SLOT") >> $dbkey - echo $(echo "$SRC_URI") >> $dbkey - echo $(echo "$RESTRICT") >> $dbkey - echo $(echo "$HOMEPAGE") >> $dbkey - echo $(echo "$LICENSE") >> $dbkey - echo $(echo "$DESCRIPTION") >> $dbkey - echo $(echo "$KEYWORDS") >> $dbkey - echo $(echo "$INHERITED") >> $dbkey - echo $(echo "$IUSE") >> $dbkey - echo >> $dbkey - echo $(echo "$PDEPEND") >> $dbkey - echo $(echo "$PROVIDE") >> $dbkey - echo $(echo "${EAPI:-0}") >> $dbkey - echo $(echo "$UNUSED_01") >> $dbkey - echo $(echo "$UNUSED_02") >> $dbkey - echo $(echo "$UNUSED_03") >> $dbkey - echo $(echo "$UNUSED_04") >> $dbkey - echo $(echo "$UNUSED_05") >> $dbkey - echo $(echo "$UNUSED_06") >> $dbkey - echo $(echo "$UNUSED_07") >> $dbkey + unset CDEPEND + [ -n "${EAPI}" ] && EAPI=0 + if [ -n "${dbkey}" ] ; then + > "${dbkey}" + for f in ${auxdbkeys} ; do + echo $(echo ${!f}) >> "${dbkey}" || exit $? + done + else + for f in ${auxdbkeys} ; do + echo $(echo ${!f}) 1>&9 || exit $? + done + 9>&- + fi set +f #make sure it is writable by our group: exit 0 @@ -1811,7 +1805,9 @@ for myarg in ${EBUILD_SH_ARGS} ; do done # Save the env only for relevant phases. -if [ -n "$myarg" ] && [ "$myarg" != "clean" ]; then +if [ -n "${myarg}" ] && \ + [ "${myarg}" != "clean" ] && \ + [ "${myarg}" != "help" ] ; then # Do not save myarg in the env, or else the above [ -n "$myarg" ] test will # give a false positive when ebuild.sh is sourced. unset myarg diff --git a/bin/emerge b/bin/emerge index 8ffc9bd67..d005c4859 100755 --- a/bin/emerge +++ b/bin/emerge @@ -40,6 +40,7 @@ from output import create_color_func good = create_color_func("GOOD") bad = create_color_func("BAD") +import portage_dep import portage_util import portage_locks import portage_exception @@ -715,7 +716,6 @@ class FakeVartree(portage.vartree): self.root = real_vartree.root self.settings = real_vartree.settings self.dbapi = portage.fakedbapi(settings=real_vartree.settings) - global_updates = None vdb_path = os.path.join(self.root, portage.VDB_PATH) try: # At least the parent needs to exist for the lock file. @@ -728,7 +728,6 @@ class FakeVartree(portage.vartree): vdb_lock = portage_locks.lockdir(vdb_path) mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE", "DEPEND", "RDEPEND", "PDEPEND"] - portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"] real_dbapi = real_vartree.dbapi slot_counters = {} for cpv in real_dbapi.cpv_all(): @@ -746,17 +745,6 @@ class FakeVartree(portage.vartree): continue slot_counters[myslot_atom] = mycounter self.dbapi.cpv_inject(cpv, metadata=metadata) - try: - # Use the live ebuild metadata if possible. - live_metadata = dict(izip(portdb_keys, - portdb.aux_get(cpv, portdb_keys))) - self.dbapi.aux_update(cpv, live_metadata) - except (KeyError, portage_exception.PortageException): - if global_updates is None: - global_updates = \ - grab_global_updates(portdb.porttree_root) - perform_global_updates( - cpv, self.dbapi, global_updates) finally: if vdb_lock: portage_locks.unlockdir(vdb_lock) @@ -765,6 +753,33 @@ class FakeVartree(portage.vartree): self.settings.treeVirtuals = portage_util.map_dictlist_vals( portage.getCPFromCPV, self.get_all_provides()) + # Intialize variables needed for lazy cache pulls of the live ebuild + # metadata. This ensures that the vardb lock is released ASAP, without + # being delayed in case cache generation is triggered. + self._aux_get = self.dbapi.aux_get + self.dbapi.aux_get = self._aux_get_wrapper + self._aux_get_history = set() + self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"] + self._portdb = portdb + self._global_updates = None + + def _aux_get_wrapper(self, pkg, wants): + if pkg in self._aux_get_history: + return self._aux_get(pkg, wants) + self._aux_get_history.add(pkg) + try: + # Use the live ebuild metadata if possible. + live_metadata = dict(izip(self._portdb_keys, + self._portdb.aux_get(pkg, self._portdb_keys))) + self.dbapi.aux_update(pkg, live_metadata) + except (KeyError, portage_exception.PortageException): + if self._global_updates is None: + self._global_updates = \ + grab_global_updates(self._portdb.porttree_root) + perform_global_updates( + pkg, self.dbapi, self._global_updates) + return self._aux_get(pkg, wants) + def grab_global_updates(portdir): from portage_update import grab_updates, parse_updates updpath = os.path.join(portdir, "profiles", "updates") @@ -803,12 +818,16 @@ def show_invalid_depstring_notice(parent_node, depstring, error_msg): p_type, p_root, p_key, p_status = parent_node msg = [] if p_status == "nomerge": + category, pf = portage.catsplit(p_key) + pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf) msg.append("Portage is unable to process the dependencies of the ") msg.append("'%s' package. " % p_key) msg.append("In order to correct this problem, the package ") msg.append("should be uninstalled, reinstalled, or upgraded. ") msg.append("As a temporary workaround, the --nodeps option can ") - msg.append("be used to ignore all dependencies.") + msg.append("be used to ignore all dependencies. For reference, ") + 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("Please notify the '%s' package maintainer " % p_key) @@ -859,10 +878,15 @@ class depgraph: # have after new packages have been installed. fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot]) self.mydbapi[myroot] = fakedb - for pkg in vardb.cpv_all(): - fakedb.cpv_inject(pkg, - metadata=dict(izip(self._mydbapi_keys, - vardb.aux_get(pkg, self._mydbapi_keys)))) + if "--nodeps" not in self.myopts and \ + "--buildpkgonly" not in self.myopts: + # --nodeps bypasses this, since it isn't needed in this case + # and the cache pulls might trigger (slow) cache generation. + for pkg in vardb.cpv_all(): + self.spinner.update() + fakedb.cpv_inject(pkg, + metadata=dict(izip(self._mydbapi_keys, + vardb.aux_get(pkg, self._mydbapi_keys)))) del vardb, fakedb self.useFlags[myroot] = {} if "--usepkg" in self.myopts: @@ -1355,6 +1379,8 @@ class depgraph: bindb = self.trees[myroot]["bintree"].dbapi vardb = self.trees[myroot]["vartree"].dbapi pkgsettings = self.pkgsettings[myroot] + if myparent: + p_type, p_root, p_key, p_status = myparent if "--debug" in self.myopts: print @@ -1367,10 +1393,15 @@ class depgraph: #processing dependencies """ Call portage.dep_check to evaluate the use? conditionals and make sure all dependencies are satisfiable. """ - mycheck = portage.dep_check(depstring, None, - pkgsettings, myuse=myuse, - use_binaries=("--usepkgonly" in self.myopts), - myroot=myroot, trees=self.trees) + try: + if myparent and p_status == "nomerge": + portage_dep._dep_check_strict = False + mycheck = portage.dep_check(depstring, None, + pkgsettings, myuse=myuse, + use_binaries=("--usepkgonly" in self.myopts), + myroot=myroot, trees=self.trees) + finally: + portage_dep._dep_check_strict = True if not mycheck[0]: show_invalid_depstring_notice(myparent, depstring, mycheck[1]) @@ -1586,6 +1617,17 @@ class depgraph: "--nodeps" in self.myopts: return True + modified_slots = {} + for myroot in self.trees: + myslots = {} + modified_slots[myroot] = myslots + final_db = self.mydbapi[myroot] + slot_node_map = self._slot_node_map[myroot] + for slot_atom, mynode in slot_node_map.iteritems(): + mytype, myroot, mycpv, mystatus = mynode + if mystatus == "merge": + myslots[slot_atom] = mycpv + #if "deep" in self.myparams: if True: # Pull in blockers from all installed packages that haven't already @@ -1626,10 +1668,22 @@ class depgraph: # It is crucial to pass in final_db here in order to # optimize dep_check calls by eliminating atoms via # dep_wordreduce and dep_eval calls. - success, atoms = portage.dep_check(depstr, final_db, - pkgsettings, myuse=myuse, trees=dep_check_trees, - myroot=myroot) + try: + portage_dep._dep_check_strict = False + success, atoms = portage.dep_check(depstr, + final_db, pkgsettings, myuse=myuse, + trees=dep_check_trees, myroot=myroot) + finally: + portage_dep._dep_check_strict = True if not success: + slot_atom = "%s:%s" % (portage.dep_getkey(pkg), + vardb.aux_get(pkg, ["SLOT"])[0]) + if slot_atom in modified_slots[myroot]: + # This package is being replaced anyway, so + # ignore invalid dependencies so as not to + # annoy the user too much (otherwise they'd be + # forced to manually unmerge it first). + continue show_invalid_depstring_notice( ("installed", myroot, pkg, "nomerge"), depstr, atoms) @@ -1650,18 +1704,6 @@ class depgraph: self.blocker_parents[blocker] = myparents myparents.add(myparent) - modified_slots = {} - if self.blocker_parents: - for myroot in self.trees: - myslots = {} - modified_slots[myroot] = myslots - final_db = self.mydbapi[myroot] - slot_node_map = self._slot_node_map[myroot] - for slot_atom, mynode in slot_node_map.iteritems(): - mytype, myroot, mycpv, mystatus = mynode - if mystatus == "merge": - modified_slots[myroot][slot_atom] = mycpv - for blocker in self.blocker_parents.keys(): mytype, myroot, mydep = blocker initial_db = self.trees[myroot]["vartree"].dbapi @@ -3184,8 +3226,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files, #we're done... return return 0 if "--ask" in myopts: - if userquery("Would you like to unmerge these packages?", - responses=["No", "Yes"], colours=[red, green]) == "No": + if userquery("Would you like to unmerge these packages?")=="No": # enter pretend mode for correct formatting of results myopts["--pretend"] = True print @@ -3206,11 +3247,32 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files, vartree=vartree, ldpath_mtimes=ldpath_mtimes) if retval != os.EX_OK: emergelog(xterm_titles, " !!! unmerge FAILURE: "+y) + ebuild = vartree.dbapi.findname(y) + show_unmerge_failure_message(y, ebuild, retval) + sys.exit(retval) else: clean_world(vartree.dbapi, y) emergelog(xterm_titles, " >>> unmerge success: "+y) return 1 +def show_unmerge_failure_message(pkg, ebuild, retval): + + from formatter import AbstractFormatter, DumbWriter + f = AbstractFormatter(DumbWriter(maxcol=72)) + + msg = [] + msg.append("A removal phase of the '%s' package " % pkg) + msg.append("has failed with exit value %s. " % retval) + msg.append("The problem occurred while executing ") + msg.append("the ebuild located at '%s'. " % ebuild) + msg.append("If necessary, manually remove the ebuild " ) + msg.append("in order to skip the execution of removal phases.") + + print + for x in msg: + f.add_flowing_data(x) + f.end_paragraph(1) + def chk_updated_info_files(root, infodirs, prev_mtimes, retval): print @@ -4227,8 +4289,12 @@ def action_depclean(settings, trees, ldpath_mtimes, else: print "hard" - success, atoms = portage.dep_check(depstr, None, settings, - myuse=usedef, trees=dep_check_trees, myroot=myroot) + try: + portage_dep._dep_check_strict = False + success, atoms = portage.dep_check(depstr, None, settings, + myuse=usedef, trees=dep_check_trees, myroot=myroot) + finally: + portage_dep._dep_check_strict = True if not success: show_invalid_depstring_notice( ("installed", myroot, pkg, "nomerge"), @@ -4329,12 +4395,11 @@ def action_build(settings, trees, mtimedb, sys.exit(0) myparams = create_depgraph_params(myopts, myaction) - mydepgraph = depgraph(settings, trees, - myopts, myparams, spinner) if myaction in ["system","world"]: if not ("--quiet" in myopts): print "Calculating",myaction,"dependencies ", sys.stdout.flush() + mydepgraph = depgraph(settings, trees, myopts, myparams, spinner) if not mydepgraph.xcreate(myaction): print "!!! Depgraph creation failed." sys.exit(1) @@ -4344,6 +4409,7 @@ def action_build(settings, trees, mtimedb, if not ("--quiet" in myopts): print "Calculating dependencies ", sys.stdout.flush() + mydepgraph = depgraph(settings, trees, myopts, myparams, spinner) try: retval, favorites = mydepgraph.select_files(myfiles) except portage_exception.PackageNotFound, e: diff --git a/pym/cache/metadata_overlay.py b/pym/cache/metadata_overlay.py index 1716e3dd4..24ab16349 100644 --- a/pym/cache/metadata_overlay.py +++ b/pym/cache/metadata_overlay.py @@ -6,6 +6,7 @@ import time if not hasattr(__builtins__, "set"): from sets import Set as set from cache import template +from cache.cache_errors import CacheCorruption from cache.flat_hash import database as db_rw from cache.metadata import database as db_ro @@ -25,6 +26,9 @@ class database(template.database): value = self.db_rw[cpv] except KeyError: return self.db_ro[cpv] # raises a KeyError when necessary + except CacheCorruption: + del self.db_rw[cpv] + return self.db_ro[cpv] # raises a KeyError when necessary if self._is_whiteout(value): if self._is_whiteout_valid(cpv, value): raise KeyError(cpv) diff --git a/pym/elog_modules/mod_mail_summary.py b/pym/elog_modules/mod_mail_summary.py index 53628b920..5e642f418 100644 --- a/pym/elog_modules/mod_mail_summary.py +++ b/pym/elog_modules/mod_mail_summary.py @@ -29,7 +29,8 @@ def finalize(mysettings): mysubject = mysubject.replace("${PACKAGE}", count) mysubject = mysubject.replace("${HOST}", socket.getfqdn()) - mybody = "elog messages for the following packages generated by process %d on host %s:\n" % (count, os.getpid(), socket.getfqdn()) + mybody = "elog messages for the following packages generated by " + \ + "process %d on host %s:\n" % (os.getpid(), socket.getfqdn()) for cpv in _items.keys(): mybody += "- %s\n" % cpv diff --git a/pym/portage.py b/pym/portage.py index 69845e12d..43787bbe1 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -1997,7 +1997,7 @@ class config: # XXX This would be to replace getstatusoutput completely. # XXX Issue: cannot block execution. Deadlock condition. -def spawn(mystring,mysettings,debug=0,free=0,droppriv=0,sesandbox=0,fd_pipes=None,**keywords): +def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keywords): """spawn a subprocess with optional sandbox protection, depending on whether sandbox is enabled. The "free" argument, when set to 1, will disable sandboxing. This allows us to @@ -3123,7 +3123,32 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, # get possible slot information from the deps file if mydo == "depend": writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2) - if dbkey: + if isinstance(dbkey, dict): + mysettings["dbkey"] = "" + pr, pw = os.pipe() + fd_pipes = {0:0, 1:1, 2:2, 9:pw} + mypids = spawn(EBUILD_SH_BINARY + " depend", mysettings, + fd_pipes=fd_pipes, returnpid=True) + os.close(pw) # belongs exclusively to the child process now + maxbytes = 1024 + mybytes = [] + while True: + mybytes.append(os.read(pr, maxbytes)) + if not mybytes[-1]: + break + os.close(pr) + mybytes = "".join(mybytes) + global auxdbkeys + dbkey.update(izip(auxdbkeys, mybytes.split("\n"))) + retval = os.waitpid(mypids[0], 0)[1] + # If it got a signal, return the signal that was sent, but + # shift in order to distinguish it from a return value. (just + # like portage_exec.spawn() would do). + if retval & 0xff: + return (retval & 0xff) << 8 + # Otherwise, return its exit code. + return retval >> 8 + elif dbkey: mysettings["dbkey"] = dbkey else: mysettings["dbkey"] = \ @@ -3141,7 +3166,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, return 1 # Build directory creation isn't required for any of these. - if mydo not in ["fetch","digest","manifest"]: + if mydo not in ("digest", "fetch", "help", "manifest"): mystatus = prepare_build_dirs(myroot, mysettings, cleanup) if mystatus: return mystatus @@ -3588,11 +3613,12 @@ def unmerge(cat, pkg, myroot, mysettings, mytrimworld=1, vartree=None, ldpath_mt try: mylink.lockdb() if mylink.exists(): - mylink.unmerge(trimworld=mytrimworld, cleanup=1, + retval = mylink.unmerge(trimworld=mytrimworld, cleanup=1, ldpath_mtimes=ldpath_mtimes) - mylink.delete() - return 0 - return 1 + if retval == os.EX_OK: + mylink.delete() + return retval + return os.EX_OK finally: mylink.unlockdb() @@ -3653,7 +3679,8 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/", newsplit.append(_expand_new_virtuals(x, edebug, mydbapi, mysettings, myroot=myroot, trees=trees, **kwargs)) continue - if not isvalidatom(x, allow_blockers=True): + if portage_dep._dep_check_strict and \ + not isvalidatom(x, allow_blockers=True): raise portage_exception.ParseError( "invalid atom: '%s'" % x) mykey = dep_getkey(x) @@ -5342,55 +5369,13 @@ class portdbapi(dbapi): writemsg("doregen: %s %s\n" % (doregen,mycpv), 2) writemsg("Generating cache entry(0) for: "+str(myebuild)+"\n",1) - if self.tmpfs: - mydbkey = self.tmpfs+"/aux_db_key_temp" - else: - mydbkey = self.depcachedir+"/aux_db_key_temp" - - mylock = None - try: - mylock = portage_locks.lockfile(mydbkey, wantnewlockfile=1) - try: - os.unlink(mydbkey) - except (IOError, OSError), e: - if e.errno != errno.ENOENT: - raise - del e - - self.doebuild_settings.reset() - myret = doebuild(myebuild, "depend", "/", - self.doebuild_settings, dbkey=mydbkey, tree="porttree", - mydbapi=self) - if myret != os.EX_OK: - #depend returned non-zero exit code... - writemsg((red("\naux_get():") + \ - " (0) Error in '%s'. (%s)\n" + \ - " Check for syntax error or " + \ - "corruption in the ebuild. (--debug)\n\n") % \ - (myebuild, myret), noiselevel=-1) - raise KeyError(mycpv) - - try: - mycent = open(mydbkey, "r") - os.unlink(mydbkey) - mylines = mycent.readlines() - mycent.close() - except (IOError, OSError): - writemsg((red("\naux_get():") + \ - " (1) Error in '%s' ebuild.\n" + \ - " Check for syntax error or " + \ - "corruption in the ebuild. (--debug)\n\n") % myebuild, - noiselevel=-1) - raise KeyError(mycpv) - finally: - if mylock: - portage_locks.unlockfile(mylock) - + self.doebuild_settings.reset() mydata = {} - for x in range(0,len(mylines)): - if mylines[x][-1] == '\n': - mylines[x] = mylines[x][:-1] - mydata[auxdbkeys[x]] = mylines[x] + myret = doebuild(myebuild, "depend", + self.doebuild_settings["ROOT"], self.doebuild_settings, + dbkey=mydata, tree="porttree", mydbapi=self) + if myret != os.EX_OK: + raise KeyError(mycpv) if "EAPI" not in mydata or not mydata["EAPI"].strip(): mydata["EAPI"] = "0" @@ -5428,10 +5413,10 @@ class portdbapi(dbapi): if cache_me: aux_cache = {} + if not mydata.setdefault("EAPI", "0"): + mydata["EAPI"] = "0" for x in self._aux_cache_keys: - aux_cache[x] = mydata[x] - if not aux_cache["EAPI"]: - aux_cache["EAPI"] = "0" + aux_cache[x] = mydata.get(x, "") self._aux_cache[mycpv] = aux_cache return returnme @@ -6387,7 +6372,7 @@ class dblink: # XXX: Decide how to handle failures here. if retval != os.EX_OK: writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1) - sys.exit(123) + return retval self._unmerge_pkgfiles(pkgfiles) @@ -6402,7 +6387,7 @@ class dblink: # XXX: Decide how to handle failures here. if retval != os.EX_OK: writemsg("!!! FAILED postrm: %s\n" % retval, noiselevel=-1) - sys.exit(123) + return retval doebuild(myebuildpath, "cleanrm", self.myroot, self.settings, tree="vartree", mydbapi=self.vartree.dbapi, vartree=self.vartree) @@ -6425,6 +6410,7 @@ class dblink: portage_locks.unlockdir(catdir_lock) env_update(target_root=self.myroot, prev_mtimes=ldpath_mtimes, contents=contents) + return os.EX_OK def _unmerge_pkgfiles(self, pkgfiles): diff --git a/pym/portage_dep.py b/pym/portage_dep.py index feb499cf0..8f7ed0051 100644 --- a/pym/portage_dep.py +++ b/pym/portage_dep.py @@ -103,6 +103,11 @@ def paren_enclose(mylist): mystrparts.append(x) return " ".join(mystrparts) +# This is just for use by emerge so that it can enable a backward compatibility +# mode in order to gracefully deal with installed packages that have invalid +# atoms or dep syntax. +_dep_check_strict = True + def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): """ Takes a paren_reduce'd array and reduces the use? conditionals out @@ -127,6 +132,8 @@ def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): if deparray and deparray[-1] and deparray[-1][-1] == "?": raise portage_exception.InvalidDependString("Conditional without target in \""+paren_enclose(deparray)+"\"") + global _dep_check_strict + mydeparray = deparray[:] rlist = [] while mydeparray: @@ -186,6 +193,9 @@ def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): additions = use_reduce(target, uselist, masklist, matchall, excludeall) if additions: rlist.append(additions) + elif not _dep_check_strict: + # The old deprecated behavior. + rlist.append(target) else: raise portage_exception.InvalidDependString( "Conditional without parenthesis: '%s?'" % head)