From ef019ad47d51df02deccb780f135d01e3314eab9 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 30 Sep 2007 21:25:28 +0000 Subject: Reimplement portdbapi.visible() so that is works without 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 | 96 +++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 357b17232..dc54efe5c 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -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" -- cgit v1.2.3-1-g7c22