From: Fabian Groffen Date: Sat, 13 Oct 2007 12:29:59 +0000 (-0000) Subject: Merged from trunk 8085:8102 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=b8c147387f360fa679af46206f3667039415a4e4;p=portage.git Merged from trunk 8085:8102 | 8086 | Bug #195527 - Unconditionally detect file collisions and log | | zmedico | them as eerror messages via elog. This will allow us to | | | collect more file collision data but it won't be quite as | | | annoying as enabling collision-protect by default would be. | | 8087 | Bug #195527 - Add some more information to the file | | zmedico | collision eerror message to try and prevent user confusion: | | | - Hint that `equery belongs ` can be used to find the | | | installed package that owns a file. - Advise then NOT to | | | file a bug without reporting exactly which two packages | | | install the same file(s). | | 8089 | s:this package wants:this package will: | | zmedico | | | 8091 | Remove a redundant call to elog_process(). | | zmedico | | | 8093 | Bug #195370 - Filter some more bogus matches due to | | zmedico | old-style virtuals. | | 8096 | In dblink.treewalk(), use os.walk() instead of | | zmedico | portage.listdir() in order to avoid cacheddir() bloat when | | | listing the files to be merged from ${D}. | | 8097 | Use os.listdir() instead of portage.listdir() in | | zmedico | dblink.mergeme(). | | 8098 | Remove a chdir() call that's no longer needed for the | | zmedico | collision-protect symlink code. | | 8100 | Make the file collision eerror message less verbose when in | | zmedico | --quiet mode. | | 8102 | Handle the PortageException that can be raised from | | zmedico | portage.mail.send_mail(). | svn path=/main/branches/prefix/; revision=8106 --- diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py index a0c70fac6..3308932db 100644 --- a/pym/emerge/__init__.py +++ b/pym/emerge/__init__.py @@ -3115,12 +3115,16 @@ class depgraph(object): #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty" #param is used for -u, where you still *do* want to see when something is being upgraded. myoldbest="" + installed_versions = vardb.match(portage.cpv_getkey(pkg_key)) if vardb.cpv_exists(pkg_key): addl=" "+yellow("R")+fetch+" " if x[3] != "nomerge": if ordered: counters.reinst += 1 - elif vardb.match(portage.dep_getkey(pkg_key)): + # filter out old-style virtual matches + elif installed_versions and \ + portage.cpv_getkey(installed_versions[0]) == \ + portage.cpv_getkey(pkg_key): mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0] slot_atom = "%s:%s" % \ (portage.cpv_getkey(pkg_key), mynewslot) diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 207cca8bf..4fc590a46 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -1477,12 +1477,6 @@ class dblink(object): def _collision_protect(self, srcroot, destroot, mypkglist, mycontents, mysymlinks): collision_ignore = set([normalize_path(myignore) for myignore in \ self.settings.get("COLLISION_IGNORE", "").split()]) - - # the linkcheck only works if we are in srcroot - mycwd = os.getcwd() - os.chdir(srcroot) - - mysymlinked_directories = [s + os.path.sep for s in mysymlinks] del mysymlinks @@ -1546,7 +1540,6 @@ class dblink(object): isowned = True break if not isowned: - collisions.append(f) stopmerge = True if collision_ignore: if f in collision_ignore: @@ -1556,7 +1549,9 @@ class dblink(object): if f.startswith(myignore + os.path.sep): stopmerge = False break - if stopmerge: + if stopmerge: + collisions.append(f) + if stopmerge and "collision-protect" in self.settings.features: print red("*")+" This package is blocked because it wants to overwrite" print red("*")+" files belonging to other packages (see list below)." print red("*")+" If you have no clue what this is all about report it " @@ -1600,10 +1595,7 @@ class dblink(object): print "None of the installed packages claim the above file(s)." print sys.exit(1) - try: - os.chdir(mycwd) - except OSError: - pass + return collisions def _security_check(self, installed_instances): if not installed_instances: @@ -1686,6 +1678,9 @@ class dblink(object): secondhand is a list of symlinks that have been skipped due to their target not existing; we will merge these symlinks at a later time. """ + + srcroot = normalize_path(srcroot).rstrip(os.path.sep) + os.path.sep + if not os.path.isdir(srcroot): writemsg("!!! Directory Not Found: D='%s'\n" % srcroot, noiselevel=-1) @@ -1736,25 +1731,26 @@ class dblink(object): # has to be before the counter is written) - genone counter = self.vartree.dbapi.counter_tick(self.myroot, mycpv=self.mycpv) - myfilelist = None - mylinklist = None + myfilelist = [] + mylinklist = [] + def onerror(e): + raise + for parent, dirs, files in os.walk(srcroot, onerror=onerror): + for f in files: + file_path = os.path.join(parent, f) + file_mode = os.lstat(file_path).st_mode + if stat.S_ISREG(file_mode): + myfilelist.append(file_path[len(srcroot):]) + elif stat.S_ISLNK(file_mode): + mylinklist.append(file_path[len(srcroot):]) # Preserve old libs if they are still in use if slot_matches and "preserve-libs" in self.settings.features: - myfilelist = listdir(srcroot, recursive=1, filesonly=1, followSymlinks=False) - mylinklist = filter(os.path.islink, [os.path.join(srcroot, x) for x in listdir(srcroot, recursive=1, filesonly=0, followSymlinks=False)]) - mylinklist = [x[len(srcroot):] for x in mylinklist] self._preserve_libs(srcroot, destroot, myfilelist+mylinklist, counter) # check for package collisions - if "collision-protect" in self.settings.features: - if myfilelist == None: - myfilelist = listdir(srcroot, recursive=1, filesonly=1, followSymlinks=False) - if mylinklist == None: - mylinklist = filter(os.path.islink, [os.path.join(srcroot, x) for x in listdir(srcroot, recursive=1, filesonly=0, followSymlinks=False)]) - mylinklist = [x[len(srcroot):] for x in mylinklist] - self._collision_protect(srcroot, destroot, others_in_slot, - myfilelist+mylinklist, mylinklist) + collisions = self._collision_protect(srcroot, destroot, others_in_slot, + myfilelist+mylinklist, mylinklist) if True: """ The merge process may move files out of the image directory, @@ -1781,6 +1777,41 @@ class dblink(object): use_cache=0, tree=self.treetype, mydbapi=mydbapi, vartree=self.vartree) + if collisions: + msg = "This package will overwrite one or more files that" + \ + " may belong to other packages (see list below)." + \ + " Add \"collision-protect\" to FEATURES in make.conf" + \ + " if you would like the merge to abort in cases like this." + if self.settings.get("PORTAGE_QUIET") != "1": + msg += " If you have determined that one or more of the" + \ + " files actually belong to another installed package then" + \ + " go to http://bugs.gentoo.org and report it as a bug." + \ + " Be sure to identify both this package and the other" + \ + " installed package in the bug report. Use a command such" + \ + " as \\`equery belongs \\` to identify the" + \ + " installed package that owns a file. Do NOT file a bug" + \ + " without reporting exactly which two packages install" + \ + " the same file(s)." + + self.settings["EBUILD_PHASE"] = "preinst" + cmd = "source '%s/isolated-functions.sh' ; " % PORTAGE_BIN_PATH + from textwrap import wrap + msg = wrap(msg, 70) + for line in msg: + cmd += "eerror \"%s\" ; " % line + cmd += "eerror ; " + cmd += "eerror \"Detected file collision(s):\" ; " + cmd += "eerror ; " + + from portage.output import colorize + for f in collisions: + cmd += "eerror \" '%s'\" ; " % colorize("INFORM", + os.path.join(destroot, f.lstrip(os.path.sep))) + + from portage import process + process.spawn(["bash", "-c", cmd], + env=self.settings.environ()) + # XXX: Decide how to handle failures here. if a != os.EX_OK: writemsg("!!! FAILED preinst: "+str(a)+"\n", noiselevel=-1) @@ -1953,7 +1984,7 @@ class dblink(object): # this is supposed to merge a list of files. There will be 2 forms of argument passing. if isinstance(stufftomerge, basestring): #A directory is specified. Figure out protection paths, listdir() it and process it. - mergelist = listdir(join(srcroot, stufftomerge)) + mergelist = os.listdir(join(srcroot, stufftomerge)) offset = stufftomerge else: mergelist = stufftomerge diff --git a/pym/portage/elog/mod_mail.py b/pym/portage/elog/mod_mail.py index c9fa5b563..922ea0846 100644 --- a/pym/portage/elog/mod_mail.py +++ b/pym/portage/elog/mod_mail.py @@ -4,6 +4,8 @@ # $Id$ import portage.mail, socket +from portage.exception import PortageException +from portage.util import writemsg def process(mysettings, key, logentries, fulltext): if mysettings.has_key("PORTAGE_ELOG_MAILURI"): @@ -32,6 +34,9 @@ def process(mysettings, key, logentries, fulltext): mysubject = mysubject.replace("${ACTION}", action) mymessage = portage.mail.create_message(myfrom, myrecipient, mysubject, fulltext) - portage.mail.send_mail(mysettings, mymessage) + try: + portage.mail.send_mail(mysettings, mymessage) + except PortageException, e: + writemsg("%s\n" % str(e), noiselevel=-1) return