Merged from trunk 4785:4794
authorFabian Groffen <grobian@gentoo.org>
Sun, 22 Oct 2006 14:03:16 +0000 (14:03 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sun, 22 Oct 2006 14:03:16 +0000 (14:03 -0000)
Optimize config.setcpv so that it only calls regenerate when necessary.
Thanks to Jason Stubbs for the initial patch from bug #17367.

Use reset instead of regenerate (revert part of the previous commit) in
order to properly clear the env layer of the config.

Fix visibility checks so that binary packages aren't masked just because
there is no matching ebuild in the tree.

Call load_infodir before the setup phase for binary packages so that USE
is properly set.

Don't put empty incrementals in the environment, unless they are already
set.

Add support for masking of packages via ACCEPT_LICENSE and
/etc/portage/package.license.  Thanks to Jason Stubbs for the initial
patch from bug #17367.

s/str_matches/acceptable_licenses/ typo

Fix gcc version parsing once again for bug #137786. sigh. :)

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

bin/emerge
bin/repoman
pym/portage.py
pym/portage_const.py

index 4efc819dec1351a9bb06992fd27bc2be39fe32fe..aed9c1be65746ae31c1a9e2f3068d122c804bc52 100755 (executable)
@@ -298,8 +298,8 @@ def getgccversion(chost):
                        return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
 
        mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
-       if mystatus == os.EX_OK and len(myoutput.split("-")) > 0:
-               return gcc_ver_prefix + myoutput.split("-")[-1]
+       if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
+               return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
 
        mystatus, myoutput = commands.getstatusoutput(
                chost + "-" + gcc_ver_command)
@@ -968,7 +968,9 @@ class depgraph:
                pkgsettings = self.pkgsettings[myroot]
                arg_atoms = []
                def visible(mylist):
-                       return portdb.gvisible(portdb.visible(mylist))
+                       matches = portdb.gvisible(portdb.visible(mylist))
+                       return [x for x in mylist \
+                               if x in matches or not portdb.cpv_exists(x)]
                for x in myfiles:
                        ext = os.path.splitext(x)[1]
                        if ext==".tbz2":
@@ -1570,7 +1572,9 @@ class depgraph:
                portdb = self.trees[self.target_root]["porttree"].dbapi
                bindb = self.trees[self.target_root]["bintree"].dbapi
                def visible(mylist):
-                       return portdb.gvisible(portdb.visible(mylist))
+                       matches = portdb.gvisible(portdb.visible(mylist))
+                       return [x for x in mylist \
+                               if x in matches or not portdb.cpv_exists(x)]
                world_problems = False
                if mode=="system":
                        mylist = getlist(self.settings, "system")
index 6548f92a6648eb54f7319de0bdeef0a822b06091..b4a108da53ced4d74ee958c0e8e248a9bd5c1c1e 100755 (executable)
@@ -543,6 +543,7 @@ if quiet < 2:
        print "PORTDIR_OVERLAY = \""+os.environ["PORTDIR_OVERLAY"]+"\""
 
 # Now that PORTDIR_OVERLAY is properly overridden, create the portdb.
+os.environ["ACCEPT_LICENSE"] = "*"
 repoman_settings = portage.config(local_config=False,
        config_incrementals=portage_const.INCREMENTALS)
 trees = portage.create_trees()
index 9ec4863bc9e2dd42d1b0b7361b74d5e5e7d4aa4a..1b8222ac6a8d82893d2ff53b7a6b9938600ba546 100644 (file)
@@ -916,6 +916,9 @@ class config:
                        self.dirVirtuals = copy.deepcopy(clone.dirVirtuals)
                        self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
                        self.features = copy.deepcopy(clone.features)
+
+                       self._accept_license = copy.deepcopy(clone._accept_license)
+                       self._plicensedict = copy.deepcopy(clone._plicensedict)
                else:
 
                        # backupenv is for calculated incremental variables.
@@ -1182,6 +1185,7 @@ class config:
 
                        self.pusedict = {}
                        self.pkeywordsdict = {}
+                       self._plicensedict = {}
                        self.punmaskdict = {}
                        abs_user_config = os.path.join(config_root,
                                USER_CONFIG_PATH.lstrip(os.path.sep))
@@ -1234,6 +1238,14 @@ class config:
                                        if not self.pkeywordsdict.has_key(cp):
                                                self.pkeywordsdict[cp] = {}
                                        self.pkeywordsdict[cp][key] = pkgdict[key]
+                               
+                               #package.license
+                               licdict = grabdict_package(
+                                       os.path.join(abs_user_config, "package.license"),
+                                       recursive=1)
+                               for k, v in licdict.iteritems():
+                                       self._plicensedict.setdefault(
+                                               dep_getkey(k), {})[k] = v
 
                                #package.unmask
                                pkgunmasklines = grabfile_package(
@@ -1327,6 +1339,8 @@ class config:
 
                        self.regenerate()
                        self.features = portage_util.unique_array(self["FEATURES"].split())
+                       
+                       self._accept_license = set(self.get("ACCEPT_LICENSE", "*").split())
 
                        if "gpg" in self.features:
                                if not os.path.exists(self["PORTAGE_GPG_DIR"]) or \
@@ -1509,6 +1523,7 @@ class config:
                self.modifying()
                if self.mycpv == mycpv:
                        return
+               has_changed = False
                self.mycpv = mycpv
                cp = dep_getkey(mycpv)
                pkginternaluse = ""
@@ -1516,7 +1531,9 @@ class config:
                        pkginternaluse = " ".join([x[1:] \
                                for x in mydb.aux_get(mycpv, ["IUSE"])[0].split() \
                                if x.startswith("+")])
-               self.configdict["pkginternal"]["USE"] = pkginternaluse
+               if pkginternaluse != self.configdict["pkginternal"].get("USE", ""):
+                       self.configdict["pkginternal"]["USE"] = pkginternaluse
+                       has_changed = True
                defaults = []
                for i in xrange(len(self.profiles)):
                        defaults.append(self.make_defaults_use[i])
@@ -1525,7 +1542,10 @@ class config:
                                best_match = best_match_to_list(self.mycpv, cpdict.keys())
                                if best_match:
                                        defaults.append(cpdict[best_match])
-               self.configdict["defaults"]["USE"] = " ".join(defaults)
+               defaults = " ".join(defaults)
+               if defaults != self.configdict["defaults"]["USE"]:
+                       self.configdict["defaults"]["USE"] = defaults
+                       has_changed = True
                useforce = []
                for i in xrange(len(self.profiles)):
                        useforce.append(self.useforce_list[i])
@@ -1534,7 +1554,10 @@ class config:
                                best_match = best_match_to_list(self.mycpv, cpdict.keys())
                                if best_match:
                                        useforce.append(cpdict[best_match])
-               self.useforce = set(stack_lists(useforce, incremental=True))
+               useforce = set(stack_lists(useforce, incremental=True))
+               if useforce != self.useforce:
+                       self.useforce = useforce
+                       has_changed = True
                usemask = []
                for i in xrange(len(self.profiles)):
                        usemask.append(self.usemask_list[i])
@@ -1543,17 +1566,34 @@ class config:
                                best_match = best_match_to_list(self.mycpv, cpdict.keys())
                                if best_match:
                                        usemask.append(cpdict[best_match])
-               self.usemask = set(stack_lists(usemask, incremental=True))
+               usemask = set(stack_lists(usemask, incremental=True))
+               if usemask != self.usemask:
+                       self.usemask = usemask
+                       has_changed = True
+               oldpuse = self.puse
                self.puse = ""
                if self.pusedict.has_key(cp):
                        self.pusekey = best_match_to_list(self.mycpv, self.pusedict[cp].keys())
                        if self.pusekey:
                                self.puse = " ".join(self.pusedict[cp][self.pusekey])
+               if oldpuse != self.puse:
+                       has_changed = True
                self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
                self.configdict["pkg"]["USE"]    = self.puse[:] # this gets appended to USE
                # CATEGORY is essential for doebuild calls
                self.configdict["pkg"]["CATEGORY"] = mycpv.split("/")[0]
-               self.reset(keeping_pkg=1,use_cache=use_cache)
+               if has_changed:
+                       self.reset(keeping_pkg=1,use_cache=use_cache)
+
+       def acceptable_licenses(self, cpv):
+               cpdict = self._plicensedict.get(dep_getkey(cpv), None)
+               if not cpdict:
+                       return self._accept_license.copy()
+               plicenses = self._accept_license.copy()
+               matches = match_to_list(cpv, cpdict.keys())
+               for atom in matches:
+                       plicenses.update(cpdict[atom])
+               return plicenses
 
        def setinst(self,mycpv,mydbapi):
                self.modifying()
@@ -1648,7 +1688,8 @@ class config:
 
                        myflags.sort()
                        #store setting in last element of configlist, the original environment:
-                       self.configlist[-1][mykey]=string.join(myflags," ")
+                       if myflags or mykey in self:
+                               self.configlist[-1][mykey] = " ".join(myflags)
                        del myflags
 
                # Do the USE calculation last because it depends on USE_EXPAND.
@@ -2574,8 +2615,10 @@ def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, m
                        "Invalid ebuild path: '%s'" % myebuild)
 
        if mydo != "depend":
-               # XXX: We're doing a little hack here to curtain the gvisible locking
-               # XXX: that creates a deadlock... Really need to isolate that.
+               """For performance reasons, setcpv only triggers reset when it
+               detects a package-specific change in config.  For the ebuild
+               environment, a reset call is forced in order to ensure that the
+               latest env.d variables are used."""
                mysettings.reset(use_cache=use_cache)
                mysettings.setcpv(mycpv, use_cache=use_cache, mydb=mydbapi)
 
@@ -2941,6 +2984,12 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                        return spawn(EBUILD_SH_BINARY + " " + mydo, mysettings,
                                debug=debug, free=1, logfile=logfile)
                elif mydo == "setup":
+                       infodir = os.path.join(
+                               mysettings["PORTAGE_BUILDDIR"], "build-info")
+                       if os.path.isdir(infodir):
+                               """Load USE flags for setup phase of a binary package.
+                               Ideally, the environment.bz2 would be used instead."""
+                               mysettings.load_infodir(infodir)
                        retval = spawn(EBUILD_SH_BINARY + " " + mydo, mysettings,
                                debug=debug, free=1, logfile=logfile)
                        if secpass >= 2:
@@ -3429,9 +3478,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
        return_all_deps=False):
        """Takes an unreduced and reduced deplist and removes satisfied dependencies.
        Returned deplist contains steps that must be taken to satisfy dependencies."""
-       if trees is None:
-               global db
-               trees = db
+
        writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
        if not reduced or unreduced == ["||"] or \
                (not return_all_deps and dep_eval(reduced)):
@@ -3452,6 +3499,17 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
        deps = unreduced[1:]
        satisfieds = reduced[1:]
 
+       if trees is None:
+               # We don't have trees to check availability against, so we
+               # just default to the first choice.
+               if isinstance(deps[0], list):
+                       atoms = dep_zapdeps(deps[0], satisfieds[0], myroot,
+                               use_binaries=use_binaries, trees=trees,
+                               return_all_deps=return_all_deps)
+               else:
+                       atoms = [deps[0]]
+               return atoms
+
        # Our preference order is for an the first item that:
        # a) contains all unmasked packages with the same key as installed packages
        # b) contains all unmasked packages
@@ -3556,7 +3614,8 @@ def dep_expand(mydep, mydb=None, use_cache=1, settings=None):
                mydep, mydb=mydb, use_cache=use_cache, settings=settings) + postfix
 
 def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
-       use_cache=1, use_binaries=0, myroot="/", trees=None, return_all_deps=False):
+       use_cache=1, use_binaries=0, myroot="/", trees=None, str_matches=None,
+       return_all_deps=False):
        """Takes a depend string and parses the condition."""
 
        #check_config_instance(mysettings)
@@ -3613,7 +3672,8 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
                #dependencies were reduced to nothing
                return [1,[]]
        mysplit2=mysplit[:]
-       mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
+       mysplit2 = dep_wordreduce(mysplit2, mysettings, mydbapi, mode,
+               str_matches=str_matches, use_cache=use_cache)
        if mysplit2 is None:
                return [0,"Invalid token"]
 
@@ -3634,19 +3694,24 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
        writemsg("mydict:   %s\n" % (mydict), 1)
        return [1,mydict.keys()]
 
-def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
+def dep_wordreduce(mydeplist, mysettings, mydbapi, mode, str_matches=None,
+       use_cache=1):
        "Reduces the deplist to ones and zeros"
        mypos=0
        deplist=mydeplist[:]
        while mypos<len(deplist):
                if type(deplist[mypos])==types.ListType:
                        #recurse
-                       deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
+                       deplist[mypos] = dep_wordreduce(deplist[mypos], mysettings,
+                               mydbapi, mode, str_matches=str_matches, use_cache=use_cache)
                elif deplist[mypos]=="||":
                        pass
                else:
                        mykey = dep_getkey(deplist[mypos])
-                       if mysettings and mysettings.pprovideddict.has_key(mykey) and \
+                       if str_matches is not None:
+                               mykey = deplist[mypos]
+                               deplist[mypos] = str_matches(mykey)
+                       elif mysettings and mysettings.pprovideddict.has_key(mykey) and \
                                match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
                                deplist[mypos]=True
                        else:
@@ -3851,7 +3916,8 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
                                        rValue.append("package.mask")
 
        # keywords checking
-       mygroups, eapi = portdb.aux_get(mycpv, ["KEYWORDS", "EAPI"])
+       mygroups, mylicense, eapi = portdb.aux_get(mycpv,
+               ["KEYWORDS", "LICENSE", "EAPI"])
        if not eapi_is_supported(eapi):
                return ["required EAPI %s, supported EAPI %s" % (eapi, portage_const.EAPI)]
        mygroups = mygroups.split()
@@ -3886,6 +3952,16 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
 
        if kmask:
                rValue.append(kmask+" keyword")
+
+       settings.setcpv(mycpv, mydb=portdb)
+       acceptable_licenses = settings.acceptable_licenses(mycpv)
+       def str_matches(myatom):
+               return myatom in acceptable_licenses
+       license_req = dep_check(mylicense, None, settings,
+               str_matches=str_matches)[1]
+       if license_req:
+               rValue.append(" ".join(license_req) + " license(s)")
+       
        return rValue
 
 class packagetree:
@@ -5336,16 +5412,17 @@ class portdbapi(dbapi):
                newlist=[]
 
                pkgdict = self.mysettings.pkeywordsdict
+               aux_keys = ["KEYWORDS", "LICENSE", "EAPI"]
                for mycpv in mylist:
                        #we need to update this next line when we have fully integrated the new db api
                        auxerr=0
                        keys = None
                        try:
-                               keys, eapi = self.aux_get(mycpv, ["KEYWORDS", "EAPI"])
+                               keys, license, eapi = self.aux_get(mycpv, aux_keys)
                        except KeyError:
                                pass
                        except portage_exception.PortageException, e:
-                               writemsg("!!! Error: aux_get('%s', ['KEYWORDS', 'EAPI'])\n" % mycpv,
+                               writemsg("!!! Error: aux_get('%s', %s)\n" % (mycpv, aux_keys),
                                        noiselevel=-1)
                                writemsg("!!! %s\n" % str(e),
                                        noiselevel=-1)
@@ -5382,6 +5459,16 @@ class portdbapi(dbapi):
                                        hasstable = True
                        if not match and ((hastesting and "~*" in pgroups) or (hasstable and "*" in pgroups)):
                                match=1
+                       acceptable_licenses = self.mysettings.acceptable_licenses(mycpv)
+                       if "*" not in acceptable_licenses:
+                               def str_matches(myatom):
+                                       return myatom in acceptable_licenses
+                               if "?" in license:
+                                       self.mysettings.setcpv(mycpv, mydb=self)
+                               reqd = dep_check(license, None, self.mysettings,
+                                       str_matches=str_matches)[1]
+                               if reqd:
+                                       match = 0
                        if match and eapi_is_supported(eapi):
                                newlist.append(mycpv)
                return newlist
index 7b53e9b26d7195d546a2ab67f959199e21723ecc..11259e4e2a697a99037bf13fdf5ff9140bd59bc1 100644 (file)
@@ -47,7 +47,9 @@ CUSTOM_MIRRORS_FILE     = USER_CONFIG_PATH+"/mirrors"
 CONFIG_MEMORY_FILE      = PRIVATE_PATH + "/config"
 COLOR_MAP_FILE          = USER_CONFIG_PATH + "/color.map"
 
-INCREMENTALS=["USE","USE_EXPAND","USE_EXPAND_HIDDEN","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"]
+INCREMENTALS = ["USE", "USE_EXPAND", "USE_EXPAND_HIDDEN", "FEATURES",
+       "ACCEPT_KEYWORDS", "CONFIG_PROTECT_MASK", "CONFIG_PROTECT", "PRELINK_PATH",
+       "PRELINK_PATH_MASK"]
 EBUILD_PHASES           = ["setup", "unpack", "compile", "test", "install",
                           "preinst", "postinst", "prerm", "postrm", "other"]