Merged from trunk -r11755:11768
authorFabian Groffen <grobian@gentoo.org>
Sat, 1 Nov 2008 16:01:40 +0000 (16:01 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 1 Nov 2008 16:01:40 +0000 (16:01 -0000)
   | 11756   | Bug #244975 - Don't allow the user to make portage unmerge   |
   | zmedico | itself since there's never any valid reason to do so.        |

   | 11758   | Use portage.const.PORTAGE_PACKAGE_ATOM where appropriate.    |
   | zmedico |                                                              |

   | 11759   | Pass a Package instance into the config.setcpv() call.       |
   | zmedico |                                                              |

   | 11760   | Fix broken stuff to avoid tracebacks when running in commit  |
   | zmedico | mode with --pretend and no vcs.                              |

   | 11761   | Remove unused conditional_disabled and conditional_enabled   |
   | zmedico | attributes from _use_dep.__slots__.                          |

   | 11762   | Bug #244947 - Add repoman support for checking masked and    |
   | zmedico | forced flags when verifying USE deps. Thanks to Brian        |
   |         | Harring for reporting.                                       |

   | 11763   | Revert previous commit since it doesn't properly calculate   |
   | zmedico | masked and forced flags for the package being matched (it    |
   |         | erroneously uses the masked and forced flags from the parent |
   |         | package).                                                    |

   | 11764   | Bug #236609 - Fix columns calculation for TERM="dumb".       |
   | zmedico | Thanks to Ulrich Müller <ulm@g.o> for the patch.            |

   | 11765   | In dblink._collision_protect(), remove redundant             |
   | zmedico | self.isowner() calls since self hasn't yet been merged and   |
   |         | therefore has no CONTENTS file for ownership checks. Also,   |
   |         | remove redundant isprotected() calls.                        |

   | 11766   | Bug #243178 - Handle file collisions with preserved libs by  |
   | zmedico | allowing the current package to assume ownership and         |
   |         | unregistering the preserved libraries.                       |

   | 11767   | Eliminate duplicate code by calling equivalent               |
   | zmedico | dblink._clear_contents_cache().                              |

   | 11768   | Bug #244947 - Add basic repoman support for checking masked  |
   | zmedico | and forced flags when verifying USE deps. TODO: Add repoman  |
   |         | support in dep_check() for evaluation of conditional USE     |
   |         | deps based on forced/masked flags. masked flags, so that     |
   |         | repoman can also                                             |
   Merged from trunk -r11768:11776

   | 11769   | Bug #244947 - Add repoman support for checking masked and    |
   | zmedico | forced flags on conditional USE deps.                        |

   | 11770   | Bug #244792 - Remove confcache support.                      |
   | zmedico |                                                              |

   | 11771   | Bug #241906 - Handle InvalidAtom exception raised from       |
   | zmedico | vardbapi.match().                                            |

   | 11772   | Bug #240295 - When emake is called, echo the make command    |
   | zmedico | similar to the way that econf echoes the configure command.  |

   | 11773   | Filter PORTAGE_VERBOSE in save_ebuild_env().                 |
   | zmedico |                                                              |

   | 11774   | Remove unused imports.                                       |
   | zmedico |                                                              |

   | 11775   | Define __all__ and remove unused import.                     |
   | zmedico |                                                              |

   | 11776   | Define __all__ and remove unused imports.                    |
   | zmedico |                                                              |

svn path=/main/branches/prefix/; revision=11785

bin/ebuild.sh
bin/emake
bin/isolated-functions.sh
bin/regenworld
bin/repoman
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/dbapi/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/vartree.py
pym/portage/dep.py

index 6a935f829e8eac2eb2e920b9ef948f22f84fc52a..fff81dc4de841bcf62a99ea07000a2e0896bba18 100755 (executable)
@@ -495,32 +495,7 @@ econf() {
                        LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}"
                fi
 
-               local TMP_CONFCACHE_DIR CONFCACHE_ARG
-               if hasq confcache $FEATURES && ! hasq confcache $RESTRICT; then
-                       CONFCACHE="$(type -P confcache)"
-                       if [ -z "${CONFCACHE}" ]; then
-                               ewarn "disabling confcache, binary cannot be found"
-                       else
-                               CONFCACHE="${CONFCACHE/ /\ }"
-                               TMP_CONFCACHE_DIR="${CONFCACHE:+${CONFCACHE_DIR:-${PORTAGE_TMPDIR}/confcache}}"
-                               TMP_CONFCACHE_DIR="${TMP_CONFCACHE_DIR/ /\ }"
-                               CONFCACHE_ARG="--confcache-dir"
-                               local s
-                               if [ -n "$CCACHE_DIR" ]; then
-                                       s="$CCACHE_DIR"
-                               fi
-                               if [ -n "$DISTCC_DIR" ]; then
-                                       s="${s:+${s}:}$DISTCC_DIR"
-                               fi
-                               if [ -n "$s" ]; then
-                                       CONFCACHE_ARG="--confcache-ignore $s $CONFCACHE_ARG"
-                               fi
-                       fi
-               else
-                       CONFCACHE=
-               fi
-
-               vecho ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+               vecho "${ECONF_SOURCE}/configure" \
                        --prefix="${EPREFIX}"/usr \
                        --host=${CHOST} \
                        --mandir="${EPREFIX}"/usr/share/man \
@@ -531,7 +506,7 @@ econf() {
                        "$@" \
                        ${LOCAL_EXTRA_ECONF}
 
-               if ! ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+               if ! "${ECONF_SOURCE}/configure" \
                        --prefix="${EPREFIX}"/usr \
                        --host=${CHOST} \
                        --mandir="${EPREFIX}"/usr/share/man \
index a5abf9c108998616989c794196f20728a1fb2a8a..83bc87c4292e1831067828c8eead285dd1d19167 100755 (executable)
--- a/bin/emake
+++ b/bin/emake
@@ -11,4 +11,6 @@
 #        /etc/make.globals here because emake is only called from an
 #        ebuild.
 
+[[ $PORTAGE_QUIET = 1 ]] || echo ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
+
 exec ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
index 7b8a5c935039ea7c0d4c9f6df44dcf6f6e158f77..61bc6b6982ee04d7030b4754c94c55c9540d1057 100755 (executable)
@@ -380,7 +380,7 @@ set_colors() {
        (( COLS > 0 )) || (( COLS = 80 ))
        COLS=$((${COLS} - 8))   # width of [ ok ] == 7
        # Adjust COLS so that eend works properly on a standard BSD console.
-       [ "${TERM}" = "cons25" ] && COLS=$((${COLS} - 1))
+       [[ $TERM = cons25 || $TERM = dumb ]] && ((COLS--))
 
        # Now, ${ENDCOL} will move us to the end of the
        # column;  irregardless of character width
@@ -537,7 +537,7 @@ save_ebuild_env() {
                        PORTAGE_INST_UID PORTAGE_LOG_FILE PORTAGE_MASTER_PID \
                        PORTAGE_QUIET \
                        PORTAGE_REPO_NAME PORTAGE_RESTRICT PORTAGE_UPDATE_ENV \
-                       PORTAGE_WORKDIR_MODE PORTDIR \
+                       PORTAGE_VERBOSE PORTAGE_WORKDIR_MODE PORTDIR \
                        PORTDIR_OVERLAY ${!PORTAGE_SANDBOX_*} PREROOTPATH \
                        PROFILE_PATHS PWORKDIR QA_INTERCEPTORS \
                        RC_DEFAULT_INDENT RC_DOT_PATTERN RC_ENDCOL \
index 7d9fccf4b5a54156bbafd85c80484a3d0e4d418c..2c251c25bd59616611e15d3c1411d85248373ab6 100755 (executable)
@@ -4,6 +4,7 @@
 # $Id$
 
 import sys, os
+import portage.exception
 
 # for an explanation on this logic, see pym/_emerge/__init__.py
 import os
@@ -85,7 +86,7 @@ for mykey in biglist:
        #print "checking:",mykey
        try:
                mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
-       except KeyError:
+       except (portage.exception.InvalidAtom, KeyError):
                if "--debug" in sys.argv:
                        print "* ignoring broken log entry for %s (likely injected)" % mykey
        except ValueError, e:
index 553099b93d2f4ff48dd36f2b6eec05751ccc81f4..b784430763a76d7fe0e31b36e75426be31b811ef 100755 (executable)
@@ -750,6 +750,8 @@ new_ebuilds = set()
 modified_changelogs = set()
 mychanged = []
 mynew = []
+myremoved = []
+
 if vcs == "cvs":
        mycvstree = cvstree.getentries("./", recursive=1)
        mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
@@ -1468,7 +1470,7 @@ for x in scanlist:
                                portdb.mysettings = dep_settings
                                portdb.xcache = xcache
                                # for package.use.mask support inside dep_check
-                               dep_settings.setcpv("/".join((catdir, y)))
+                               dep_settings.setcpv(pkg)
                                dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
                                # just in case, prevent config.reset() from nuking these.
                                dep_settings.backup_changes("ACCEPT_KEYWORDS")
@@ -1815,7 +1817,8 @@ else:
                unameout += platform.processor()
        else:
                unameout += platform.machine()
-       commitmessage+="\n(Portage version: "+str(portage_version)+"/"+vcs+"/"+unameout
+       commitmessage += "\n(Portage version: %s/%s/%s" % \
+               (portage_version, vcs, unameout)
        if options.force:
                commitmessage += ", RepoMan options: --force"
        commitmessage += ")"
index 8122cb76aa6039a3c94bd21b3d080212f8e02781..12308d8281c3fd4e1925f7c0312c9a4149155139 100644 (file)
@@ -56,13 +56,13 @@ else:
 import portage
 
 
-from portage import digraph, portdbapi
-from portage.const import NEWS_LIB_PATH, CACHE_PATH, PRIVATE_PATH, USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
+from portage import digraph
+from portage.const import NEWS_LIB_PATH
 
 import _emerge.help
 import portage.xpak, commands, errno, re, socket, time, types
 from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
-       havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
+       nc_len, red, teal, turquoise, xtermTitle, \
        xtermTitleReset, yellow
 from portage.output import create_color_func
 good = create_color_func("GOOD")
@@ -10531,7 +10531,7 @@ def unmerge(root_config, myopts, unmerge_action,
        candidate_catpkgs=[]
        global_unmerge=0
        xterm_titles = "notitles" not in settings.features
-
+       out = portage.output.EOutput()
        pkg_cache = {}
        db_keys = list(vartree.dbapi._aux_cache_keys)
 
@@ -10796,6 +10796,21 @@ def unmerge(root_config, myopts, unmerge_action,
                                # It could have been uninstalled
                                # by a concurrent process.
                                continue
+
+                       if unmerge_action != "clean" and \
+                               root_config.root == "/" and \
+                               portage.match_from_list(
+                               portage.const.PORTAGE_PACKAGE_ATOM, [pkg]):
+                               msg = ("Not unmerging package %s since there is no valid " + \
+                               "reason for portage to unmerge itself.") % (pkg.cpv,)
+                               for line in textwrap.wrap(msg, 75):
+                                       out.eerror(line)
+                               # adjust pkgmap so the display output is correct
+                               pkgmap[cp]["selected"].remove(cpv)
+                               all_selected.remove(cpv)
+                               pkgmap[cp]["protected"].add(cpv)
+                               continue
+
                        parents = []
                        for s in installed_sets:
                                # skip sets that the user requested to unmerge, and skip world 
@@ -10854,10 +10869,18 @@ def unmerge(root_config, myopts, unmerge_action,
                                print "    %s\n" % ", ".join(parents)
                                # adjust pkgmap so the display output is correct
                                pkgmap[cp]["selected"].remove(cpv)
+                               all_selected.remove(cpv)
                                pkgmap[cp]["protected"].add(cpv)
        
        del installed_sets
 
+       numselected = len(all_selected)
+       if not numselected:
+               writemsg_level(
+                       "\n>>> No packages selected for removal by " + \
+                       unmerge_action + "\n")
+               return 0
+
        # Unmerge order only matters in some cases
        if not ordered:
                unordered = {}
@@ -11819,9 +11842,11 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                portdb = trees[settings["ROOT"]]["porttree"].dbapi
                root_config = trees[settings["ROOT"]]["root_config"]
 
-       mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
+       mybestpv = portdb.xmatch("bestmatch-visible",
+               portage.const.PORTAGE_PACKAGE_ATOM)
        mypvs = portage.best(
-               trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
+               trees[settings["ROOT"]]["vartree"].dbapi.match(
+               portage.const.PORTAGE_PACKAGE_ATOM))
 
        chk_updated_cfg_files(EPREFIX, settings.get("CONFIG_PROTECT","").split())
 
index 35b57250d8f875e9d4ef263c9515e53933610f47..71f8b444a63f7cf336e2304b8339cf4e62441f1b 100644 (file)
@@ -2017,45 +2017,13 @@ class config(object):
                if defaults != self.configdict["defaults"].get("USE",""):
                        self.configdict["defaults"]["USE"] = defaults
                        has_changed = True
-               useforce = []
-               pos = 0
-               for i in xrange(len(self.profiles)):
-                       cpdict = self.puseforce_list[i].get(cp, None)
-                       if cpdict:
-                               keys = cpdict.keys()
-                               while keys:
-                                       best_match = best_match_to_list(cpv_slot, keys)
-                                       if best_match:
-                                               keys.remove(best_match)
-                                               useforce.insert(pos, cpdict[best_match])
-                                       else:
-                                               break
-                               del keys
-                       if self.useforce_list[i]:
-                               useforce.insert(pos, self.useforce_list[i])
-                       pos = len(useforce)
-               useforce = set(stack_lists(useforce, incremental=True))
+
+               useforce = self._getUseForce(cpv_slot)
                if useforce != self.useforce:
                        self.useforce = useforce
                        has_changed = True
-               usemask = []
-               pos = 0
-               for i in xrange(len(self.profiles)):
-                       cpdict = self.pusemask_list[i].get(cp, None)
-                       if cpdict:
-                               keys = cpdict.keys()
-                               while keys:
-                                       best_match = best_match_to_list(cpv_slot, keys)
-                                       if best_match:
-                                               keys.remove(best_match)
-                                               usemask.insert(pos, cpdict[best_match])
-                                       else:
-                                               break
-                               del keys
-                       if self.usemask_list[i]:
-                               usemask.insert(pos, self.usemask_list[i])
-                       pos = len(usemask)
-               usemask = set(stack_lists(usemask, incremental=True))
+
+               usemask = self._getUseMask(cpv_slot)
                if usemask != self.usemask:
                        self.usemask = usemask
                        has_changed = True
@@ -2227,6 +2195,52 @@ class config(object):
 
                return iuse_implicit
 
+       def _getUseMask(self, pkg):
+               cp = getattr(pkg, "cp", None)
+               if cp is None:
+                       cp = dep_getkey(pkg)
+               usemask = []
+               pos = 0
+               for i in xrange(len(self.profiles)):
+                       cpdict = self.pusemask_list[i].get(cp, None)
+                       if cpdict:
+                               keys = cpdict.keys()
+                               while keys:
+                                       best_match = best_match_to_list(pkg, keys)
+                                       if best_match:
+                                               keys.remove(best_match)
+                                               usemask.insert(pos, cpdict[best_match])
+                                       else:
+                                               break
+                               del keys
+                       if self.usemask_list[i]:
+                               usemask.insert(pos, self.usemask_list[i])
+                       pos = len(usemask)
+               return set(stack_lists(usemask, incremental=True))
+
+       def _getUseForce(self, pkg):
+               cp = getattr(pkg, "cp", None)
+               if cp is None:
+                       cp = dep_getkey(pkg)
+               useforce = []
+               pos = 0
+               for i in xrange(len(self.profiles)):
+                       cpdict = self.puseforce_list[i].get(cp, None)
+                       if cpdict:
+                               keys = cpdict.keys()
+                               while keys:
+                                       best_match = best_match_to_list(pkg, keys)
+                                       if best_match:
+                                               keys.remove(best_match)
+                                               useforce.insert(pos, cpdict[best_match])
+                                       else:
+                                               break
+                               del keys
+                       if self.useforce_list[i]:
+                               useforce.insert(pos, self.useforce_list[i])
+                       pos = len(useforce)
+               return set(stack_lists(useforce, incremental=True))
+
        def _getMaskAtom(self, cpv, metadata):
                """
                Take a package and return a matching package.mask atom, or None if no
@@ -4956,10 +4970,6 @@ def _prepare_features_dirs(mysettings):
                        "basedir_var":"CCACHE_DIR",
                        "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"),
                        "always_recurse":False},
-               "confcache":{
-                       "basedir_var":"CONFCACHE_DIR",
-                       "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "confcache"),
-                       "always_recurse":False},
                "distcc":{
                        "basedir_var":"DISTCC_DIR",
                        "default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"),
@@ -6144,7 +6154,7 @@ def dep_virtual(mysplit, mysettings):
        return newsplit
 
 def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
-       trees=None, **kwargs):
+       trees=None, use_mask=None, use_force=None, **kwargs):
        """Recursively expand new-style virtuals so as to collapse one or more
        levels of indirection.  In dep_zapdeps, new-style virtuals will be assigned
        zero cost regardless of whether or not they are currently installed. Virtual
@@ -6180,8 +6190,14 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                        raise portage.exception.ParseError(
                                                "invalid atom: '%s'" % x)
 
-               # Repoman only checks IUSE for USE deps, so there's
-               # no need to evaluate conditionals.
+               if repoman and x.use and x.use.conditional:
+                       evaluated_atom = portage.dep.remove_slot(x)
+                       if x.slot:
+                               evaluated_atom += ":%s" % x.slot
+                       evaluated_atom += str(x.use._eval_qa_conditionals(
+                               use_mask, use_force))
+                       x = portage.dep.Atom(evaluated_atom)
+
                if not repoman and \
                        myuse is not None and isinstance(x, portage.dep.Atom) and x.use:
                        if x.use.conditional:
@@ -6572,7 +6588,8 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
        # collapse one or more levels of indirection.
        try:
                mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
-                       use=use, mode=mode, myuse=myuse, use_cache=use_cache,
+                       use=use, mode=mode, myuse=myuse,
+                       use_force=useforce, use_mask=mymasks, use_cache=use_cache,
                        use_binaries=use_binaries, myroot=myroot, trees=trees)
        except portage.exception.ParseError, e:
                return [0, str(e)]
index 0900fcfa8013a430d3567e6afb3764ea8c54f2fe..2bdb3e7cdefaa5d34eea89ec34a3cc705d823689 100644 (file)
@@ -2,15 +2,16 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
+__all__ = ["dbapi"]
+
 import os
 import re
-from portage.dep import Atom, dep_getslot, dep_getkey, \
-       dep_getusedeps, match_from_list
+from portage.dep import match_from_list
 from portage.locks import unlockfile
 from portage.output import red
 from portage.util import writemsg
 from portage import auxdbkeys, dep_expand
-from portage.versions import catpkgsplit, catsplit, pkgcmp
+from portage.versions import catpkgsplit, pkgcmp
 
 
 class dbapi(object):
@@ -150,7 +151,7 @@ class dbapi(object):
                        self._iuse_implicit = self.settings._get_implicit_iuse()
                for cpv in cpv_iter:
                        try:
-                               iuse, use = self.aux_get(cpv, ["IUSE", "USE"])
+                               iuse, slot, use = self.aux_get(cpv, ["IUSE", "SLOT", "USE"])
                        except KeyError:
                                continue
                        use = use.split()
@@ -169,6 +170,20 @@ class dbapi(object):
                                        continue
                                if atom.use.disabled.intersection(use):
                                        continue
+                       else:
+                               # Check masked and forced flags for repoman.
+                               mysettings = getattr(self, "mysettings", None)
+                               if mysettings is not None and not mysettings.local_config:
+
+                                       pkg = "%s:%s" % (cpv, slot)
+                                       usemask = mysettings._getUseMask(pkg)
+                                       if usemask.intersection(atom.use.enabled):
+                                               continue
+
+                                       useforce = mysettings._getUseForce(pkg).difference(usemask)
+                                       if useforce.intersection(atom.use.disabled):
+                                               continue
+
                        yield cpv
 
        def invalidentry(self, mypath):
index d4d4508e2d7a304ad6acfd41560e1a515960607e..c46ba7e76a59b6ebacbd088742b9e9bdf0879a34 100644 (file)
@@ -2,10 +2,12 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
+__all__ = ["bindbapi", "binarytree"]
+
 from portage.cache.mappings import slot_dict_class
 from portage.dep import isvalidatom, isjustname, dep_getkey, match_from_list
 from portage.dbapi.virtual import fakedbapi
-from portage.exception import InvalidPackageName, InvalidAtom, \
+from portage.exception import InvalidPackageName, \
        PermissionDenied, PortageException
 from portage.output import green, EOutput
 from portage.util import ensure_dirs, normalize_path, writemsg, writemsg_stdout
index e200a36c5f93cc88b57b7ed612a3f2d65247b939..6fb04895a24486d46ede084dfbfa5822d56246a5 100644 (file)
@@ -8,11 +8,11 @@ __all__ = ["PreservedLibsRegistry", "LinkageMap",
 
 from portage.checksum import perform_md5
 from portage.const import CACHE_PATH, CONFIG_MEMORY_FILE, \
-       PRIVATE_PATH, VDB_PATH, EPREFIX, EPREFIX_LSTRIP
-from portage.data import portage_gid, portage_uid, secpass, ostype
+       PORTAGE_PACKAGE_ATOM, PRIVATE_PATH, VDB_PATH, EPREFIX, EPREFIX_LSTRIP
+from portage.data import portage_gid, portage_uid, secpass
 from portage.dbapi import dbapi
 from portage.dep import use_reduce, paren_reduce, isvalidatom, \
-       isjustname, dep_getkey
+       isjustname, dep_getkey, match_from_list
 from portage.exception import InvalidData, InvalidPackageName, \
        FileNotFound, PermissionDenied, UnsupportedAPIException
 from portage.locks import lockdir, unlockdir
@@ -3135,6 +3135,18 @@ class dblink(object):
                        collision_ignore = set([normalize_path(myignore) for myignore in \
                                shlex.split(self.settings.get("COLLISION_IGNORE", ""))])
 
+                       # For collisions with preserved libraries, the current package
+                       # will assume ownership and the libraries will be unregistered.
+                       plib_dict = self.vartree.dbapi.plib_registry.getPreservedLibs()
+                       plib_cpv_map = {}
+                       plib_paths = set()
+                       for cpv, paths in plib_dict.iteritems():
+                               plib_paths.update(paths)
+                               for f in paths:
+                                       plib_cpv_map[f] = cpv
+                       plib_inodes = self._lstat_inode_map(plib_paths)
+                       plib_collisions = {}
+
                        showMessage = self._display_merge
                        scheduler = self._scheduler
                        stopmerge = False
@@ -3186,12 +3198,29 @@ class dblink(object):
                                                raise
                                if f[0] != "/":
                                        f="/"+f
+
+                               plibs = plib_inodes.get((dest_lstat.st_dev, dest_lstat.st_ino))
+                               if plibs:
+                                       for path in plibs:
+                                               cpv = plib_cpv_map[path]
+                                               paths = plib_collisions.get(cpv)
+                                               if paths is None:
+                                                       paths = set()
+                                                       plib_collisions[cpv] = paths
+                                               paths.add(path)
+                                       # The current package will assume ownership and the
+                                       # libraries will be unregistered, so exclude this
+                                       # path from the normal collisions.
+                                       continue
+
                                isowned = False
                                full_path = os.path.join(destroot, f.lstrip(os.path.sep))
-                               for ver in [self] + mypkglist:
-                                       if (ver.isowner(f, destroot) or ver.isprotected(full_path)):
+                               for ver in mypkglist:
+                                       if ver.isowner(f, destroot):
                                                isowned = True
                                                break
+                               if not isowned and self.isprotected(full_path):
+                                       isowned = True
                                if not isowned:
                                        stopmerge = True
                                        if collision_ignore:
@@ -3204,7 +3233,33 @@ class dblink(object):
                                                                        break
                                        if stopmerge:
                                                collisions.append(f)
-                       return collisions
+                       return collisions, plib_collisions
+
+       def _lstat_inode_map(self, path_iter):
+               """
+               Use lstat to create a map of the form:
+                 {(st_dev, st_ino) : set([path1, path2, ...])}
+               Multiple paths may reference the same inode due to hardlinks.
+               All lstat() calls are relative to self.myroot.
+               """
+               root = self.myroot
+               inode_map = {}
+               for f in path_iter:
+                       path = os.path.join(root, f.lstrip(os.sep))
+                       try:
+                               st = os.lstat(path)
+                       except OSError, e:
+                               if e.errno not in (errno.ENOENT, errno.ENOTDIR):
+                                       raise
+                               del e
+                               continue
+                       key = (st.st_dev, st.st_ino)
+                       paths = inode_map.get(key)
+                       if paths is None:
+                               paths = set()
+                               inode_map[key] = paths
+                       paths.add(f)
+               return inode_map
 
        def _security_check(self, installed_instances):
                if not installed_instances:
@@ -3463,7 +3518,8 @@ class dblink(object):
                        blockers = self._blockers()
                if blockers is None:
                        blockers = []
-               collisions = self._collision_protect(srcroot, destroot,
+               collisions, plib_collisions = \
+                       self._collision_protect(srcroot, destroot,
                        others_in_slot + blockers, myfilelist + mylinklist)
 
                # Make sure the ebuild environment is initialized and that ${T}/elog
@@ -3697,17 +3753,14 @@ class dblink(object):
                # just been merged.
                others_in_slot.append(self)  # self has just been merged
                for dblnk in others_in_slot:
-                       dblnk.contentscache = None
-                       dblnk._contents_inodes = None
-                       dblnk._contents_basenames = None
+                       dblnk._clear_contents_cache()
 
                # If portage is reinstalling itself, remove the old
                # version now since we want to use the temporary
                # PORTAGE_BIN_PATH that will be removed when we return.
                reinstall_self = False
                if self.myroot == "/" and \
-                       "sys-apps" == self.cat and \
-                       "portage" == pkgsplit(self.pkg)[0]:
+                       match_from_list(PORTAGE_PACKAGE_ATOM, [self.mycpv]):
                        reinstall_self = True
 
                autoclean = self.settings.get("AUTOCLEAN", "yes") == "yes"
@@ -3746,6 +3799,24 @@ class dblink(object):
                        self.vartree.dbapi.removeFromContents(blocker, iter(contents),
                                relative_paths=False)
 
+               # Unregister any preserved libs that this package has overwritten
+               # and update the contents of the packages that owned them.
+               plib_registry = self.vartree.dbapi.plib_registry
+               plib_dict = plib_registry.getPreservedLibs()
+               for cpv, paths in plib_collisions.iteritems():
+                       if cpv not in plib_dict:
+                               continue
+                       if cpv == self.mycpv:
+                               continue
+                       try:
+                               slot, counter = self.vartree.dbapi.aux_get(
+                                       cpv, ["SLOT", "COUNTER"])
+                       except KeyError:
+                               continue
+                       remaining = [f for f in plib_dict[cpv] if f not in paths]
+                       plib_registry.register(cpv, slot, counter, remaining)
+                       self.vartree.dbapi.removeFromContents(cpv, paths)
+
                self.vartree.dbapi._add(self)
                contents = self.getcontents()
 
@@ -4094,8 +4165,7 @@ class dblink(object):
                if self.vartree.dbapi._categories is not None:
                        self.vartree.dbapi._categories = None
                if self.myroot == "/" and \
-                       "sys-apps" == self.cat and \
-                       "portage" == pkgsplit(self.pkg)[0]:
+                       match_from_list(PORTAGE_PACKAGE_ATOM, [self.mycpv]):
                        settings = self.settings
                        base_path_orig = os.path.dirname(settings["PORTAGE_BIN_PATH"])
                        from tempfile import mkdtemp
index b36a6bf5a0eafb7b340ff97eebbe5d4962ba29b1..fc6a8b10e66d13f9cbe2f490000ee56511f61110 100644 (file)
@@ -341,8 +341,8 @@ def dep_opconvert(deplist):
 
 class _use_dep(object):
 
-       __slots__ = ("__weakref__", "conditional", "conditional_disabled",
-               "conditional_enabled", "disabled", "enabled", "tokens", "required")
+       __slots__ = ("__weakref__", "conditional",
+               "disabled", "enabled", "tokens", "required")
 
        _conditionals_class = portage.cache.mappings.slot_dict_class(
                ("disabled", "enabled", "equal", "not_equal"), prefix="")
@@ -459,6 +459,31 @@ class _use_dep(object):
 
                return _use_dep(tokens)
 
+       def _eval_qa_conditionals(self, use_mask, use_force):
+               """
+               For repoman, evaluate all possible combinations within the constraints
+               of the given use.force and use.mask settings. The result may seem
+               ambiguous in the sense that the same flag can be in both the enabled
+               and disabled sets, but this is useful within the context of how its
+               intended to be used by repoman. It is assumed that the caller has
+               already ensured that there is no intersection between the given
+               use_mask and use_force sets when necessary.
+               """
+               tokens = []
+
+               conditional = self.conditional
+               tokens.extend(self.enabled)
+               tokens.extend("-" + x for x in self.disabled)
+               tokens.extend(x for x in conditional.enabled if x not in use_mask)
+               tokens.extend("-" + x for x in conditional.disabled if x not in use_force)
+
+               tokens.extend(x for x in conditional.equal if x not in use_mask)
+               tokens.extend("-" + x for x in conditional.equal if x not in use_force)
+               tokens.extend("-" + x for x in conditional.not_equal if x not in use_mask)
+               tokens.extend(x for x in conditional.not_equal if x not in use_force)
+
+               return _use_dep(tokens)
+
 class _AtomCache(type):
        """
        Cache Atom instances from constructor calls and reuse