Reimplement portdbapi.visible() so that is works without
authorZac Medico <zmedico@gentoo.org>
Sun, 30 Sep 2007 21:25:28 +0000 (21:25 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 30 Sep 2007 21:25:28 +0000 (21:25 -0000)
using self.xmatch(). This should be 100% compatible with
the previous implementation and have comparable
performance. By eliminating the xmatch() dependency, the
code becomes more generically usable, like for
visibility filtering of binary packages. It seems that
it will be necessary to move this code outside of the
dbapi since visiblity filtering is really a resolver
level function and to solve things like bug #88613 will
require a more flexible approach.
since the current internal

svn path=/main/trunk/; revision=7892

pym/portage/dbapi/porttree.py

index 357b17232cf16b6ffbe105ffaef3fb5efe98b958..dc54efe5c488614fadb7f9164a9c3677d6541969 100644 (file)
@@ -7,7 +7,7 @@ from portage.const import REPO_NAME_LOC
 from portage.data import portage_gid, secpass
 from portage.dbapi import dbapi
 from portage.dep import use_reduce, paren_reduce, dep_getslot, dep_getkey, \
-       match_from_list, match_to_list
+       match_from_list, match_to_list, remove_slot
 from portage.exception import OperationNotPermitted, PortageException, \
        UntrustedSignature, SecurityViolation, InvalidSignature, MissingSignature, \
        FileNotFound, InvalidDependString
@@ -585,54 +585,60 @@ class portdbapi(dbapi):
                """two functions in one.  Accepts a list of cpv values and uses the package.mask *and*
                packages file to remove invisible entries, returning remaining items.  This function assumes
                that all entries in mylist have the same category and package name."""
-               if (mylist is None) or (len(mylist) == 0):
+               if not mylist:
                        return []
-               newlist = mylist[:]
-               #first, we mask out packages in the package.mask file
-               mykey = newlist[0]
-               cpv = catpkgsplit(mykey)
-               if not cpv:
+
+               mysplit = catpkgsplit(mylist[0])
+               if not mysplit:
                        #invalid cat/pkg-v
-                       print "visible(): invalid cat/pkg-v:", mykey
+                       writemsg("visible(): invalid cat/pkg-v: %s\n" % (mylist[0], ),
+                               noiselevel=-1)
                        return []
-               mycp = cpv[0] + "/" + cpv[1]
-               maskdict = self.mysettings.pmaskdict
-               unmaskdict = self.mysettings.punmaskdict
-               if maskdict.has_key(mycp):
-                       for x in maskdict[mycp]:
-                               mymatches = self.xmatch("match-all", x)
-                               if mymatches is None:
-                                       #error in package.mask file; print warning and continue:
-                                       print "visible(): package.mask entry \"" + x + "\" is invalid, ignoring..."
-                                       continue
-                               for y in mymatches:
-                                       unmask = 0
-                                       if unmaskdict.has_key(mycp):
-                                               for z in unmaskdict[mycp]:
-                                                       mymatches_unmask = self.xmatch("match-all",z)
-                                                       if y in mymatches_unmask:
-                                                               unmask = 1
-                                                               break
-                                       if unmask == 0:
-                                               try:
-                                                       newlist.remove(y)
-                                               except ValueError:
-                                                       pass
-
-               profile_atoms = self.mysettings.prevmaskdict.get(mycp)
-               if profile_atoms:
-                       for x in profile_atoms:
-                               #important: only match against the still-unmasked entries...
-                               #notice how we pass "newlist" to the xmatch() call below....
-                               #Without this, ~ deps in the packages files are broken.
-                               mymatches=self.xmatch("match-list",x,mylist=newlist)
-                               if mymatches is None:
-                                       #error in packages file; print warning and continue:
-                                       print "emerge: visible(): profile packages entry \""+x+"\" is invalid, ignoring..."
-                                       continue
-                               newlist = [cpv for cpv in newlist if cpv in mymatches]
+               mycp = "%s/%s" % (mysplit[0], mysplit[1])
 
-               return newlist
+               cpv_slots = []
+               for cpv in mylist:
+                       try:
+                               myslot = self.aux_get(cpv, ["SLOT"])[0]
+                       except KeyError:
+                               # masked by corruption
+                               continue
+                       cpv_slots.append("%s:%s" % (cpv, myslot))
+
+               if cpv_slots:
+                       mask_atoms = self.mysettings.pmaskdict.get(mycp)
+                       if mask_atoms:
+                               unmask_atoms = self.mysettings.punmaskdict.get(mycp)
+                               for x in mask_atoms:
+                                       masked_pkgs = match_from_list(x, cpv_slots)
+                                       if not masked_pkgs:
+                                               continue
+                                       if unmask_atoms:
+                                               for y in unmask_atoms:
+                                                       unmasked_pkgs = match_from_list(y, masked_pkgs)
+                                                       if unmasked_pkgs:
+                                                               masked_pkgs = [pkg for pkg in masked_pkgs \
+                                                                       if pkg not in unmasked_pkgs]
+                                                               if not masked_pkgs:
+                                                                       break
+                                       if masked_pkgs:
+                                               cpv_slots = [pkg for pkg in cpv_slots \
+                                                       if pkg not in masked_pkgs]
+                                               if not cpv_slots:
+                                                       break
+
+               if cpv_slots:
+                       profile_atoms = self.mysettings.prevmaskdict.get(mycp)
+                       if profile_atoms:
+                               for x in profile_atoms:
+                                       cpv_slots = match_from_list(x.lstrip("*"), cpv_slots)
+                                       if not cpv_slots:
+                                               break
+
+               if not cpv_slots:
+                       return cpv_slots
+
+               return [remove_slot(pkg) for pkg in cpv_slots]
 
        def gvisible(self,mylist):
                "strip out group-masked (not in current group) entries"