Merged from trunk 5091:5107
authorFabian Groffen <grobian@gentoo.org>
Mon, 20 Nov 2006 17:51:48 +0000 (17:51 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 20 Nov 2006 17:51:48 +0000 (17:51 -0000)
Use mydbapi is None to eliminate the return_all_deps parameter from
dep_check and dep_zapdeps.  The result is the same and this way we
avoid having an additional parameter with overlapping meaning.

Allow dep_wordreduce to mark things satisfied by package.provided even
when mydbapi is None.

For depclean, just pass in None for mydbapi (instead of an empty
fakedbapi instance) since that's now supported.

Remove redundant package.provided handling that is now covered by
dep_wordreduce.

Allow the ROOT setting to come from make.conf.  Thanks to Daniel
Barkalow <barkalow@iabervon.org> for this patch (submitted on the
gentoo-portage-dev mailing list).

For bug #155739, only check if a dep is in the args when myroot ==
self.target_root.

Print a warning message if a user requests a package from
package.provided (since it won't be merged).

Enable PORTAGE_CONFIGROOT to be set via an new --config-root option.
Thanks to Daniel Barkalow <barkalow@iabervon.org> for the initial patch
(submitted on the gentoo-portage-dev mailing list).

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

bin/emerge
pym/portage.py

index aa6c707ed35c15ba5cd31d044bd07bd70b52ee7b..6a4f70dc34853645af860602e8c18dd90bb8a6e2 100755 (executable)
@@ -585,17 +585,6 @@ def getlist(settings, mode):
                        myline=myline[1:]
                mynewlines.append(myline.strip())
 
-       # Remove everything that is package.provided from our list
-       for atom in mynewlines[:]:
-               for expanded_atom in portage.flatten(
-                       portage.dep_virtual([atom], settings)):
-                       mykey = portage.dep_getkey(expanded_atom)
-                       if mykey in settings.pprovideddict and \
-                               portage.match_from_list(
-                                       expanded_atom, settings.pprovideddict[mykey]):
-                                       mynewlines.remove(atom)
-                                       break
-
        return mynewlines
 
 def clean_world(vardb, cpv):
@@ -768,6 +757,7 @@ class depgraph:
                self.blocker_digraph = digraph()
                self.blocker_parents = {}
                self._altlist_cache = {}
+               self._pprovided_args = []
 
        def create(self, mybigkey, myparent=None, addme=1, myuse=None,
                priority=DepPriority(), rev_dep=False, arg=None):
@@ -814,7 +804,7 @@ class depgraph:
                                self.blocker_parents.setdefault(
                                        " ".join(mybigkey), set()).add(myparent)
                        return 1
-               if not arg:
+               if not arg and myroot == self.target_root:
                        arg = portage.best_match_to_list(mykey, self.args_keys)
                # select the correct /var database that we'll be checking against
                vardbapi = self.trees[myroot]["vartree"].dbapi
@@ -1196,10 +1186,10 @@ class depgraph:
                #processing dependencies
                """ Call portage.dep_check to evaluate the use? conditionals and make sure all
                dependencies are satisfiable. """
-               mycheck = portage.dep_check(depstring, self.mydbapi[myroot],
+               mycheck = portage.dep_check(depstring, None,
                        pkgsettings, myuse=myuse,
                        use_binaries=("--usepkgonly" in self.myopts),
-                       myroot=myroot, trees=self.trees, return_all_deps=True)
+                       myroot=myroot, trees=self.trees)
 
                if not mycheck[0]:
                        sys.stderr.write("\n\n%s\n\n" % mycheck[1])
@@ -1207,6 +1197,12 @@ class depgraph:
                        return 0
                mymerge = mycheck[1]
 
+               if not mymerge and arg and \
+                       portage.best_match_to_list(depstring, self.args_keys):
+                       # A provided package has been specified on the command line.  The
+                       # package will not be merged and a warning will be displayed.
+                       self._pprovided_args.append(arg)
+
                if myparent:
                        # The parent is added after it's own dep_check call so that it
                        # isn't allowed to satisfy a direct bootstrap dependency on itself
@@ -1239,12 +1235,6 @@ class depgraph:
                                                vardb.match(x):
                                                continue
 
-                                       pkg_key = portage.dep_getkey(x)
-                                       if pkg_key in pkgsettings.pprovideddict and \
-                                               portage.match_from_list(
-                                                       x, pkgsettings.pprovideddict[pkg_key]):
-                                                       continue
-
                                # List of acceptable packages, ordered by type preference.
                                matched_packages = []
                                myeb_matches = portdb.xmatch("match-visible", x)
@@ -2178,6 +2168,21 @@ class depgraph:
                                print bold('*'+revision)
                                sys.stdout.write(text)
 
+               if self._pprovided_args:
+                       msg = []
+                       msg.append(bad("\nWARNING: "))
+                       if len(self._pprovided_args) > 1:
+                               msg.append("Requested packages will not be " + \
+                                       "merged because they are listed in\n")
+                       else:
+                               msg.append("A requested package will not be " + \
+                                       "merged because it is listed in\n")
+                       msg.append("         package.provided:\n\n")
+                       for arg in self._pprovided_args:
+                               msg.append("             " + arg + "\n")
+                       msg.append("\n")
+                       sys.stderr.write("".join(msg))
+
        def calc_changelog(self,ebuildpath,current,next):
                current = '-'.join(portage.catpkgsplit(current)[1:])
                if current.endswith('-r0'): current = current[:-3]
@@ -3893,7 +3898,6 @@ def action_depclean(settings, trees, ldpath_mtimes,
        syslist = getlist(settings, "system")
        worldlist = getlist(settings, "world")
        fakedb = portage.fakedbapi(settings=settings)
-       emptydb = portage.fakedbapi(settings=settings)
        myvarlist = vardb.cpv_all()
 
        if not syslist:
@@ -3957,7 +3961,7 @@ def action_depclean(settings, trees, ldpath_mtimes,
                        mydeps.append((" ".join(myaux.values()), hard))
                        usedef = vardb.aux_get(pkg, ["USE"])[0].split()
                        for depstr, priority in mydeps:
-                               success, atoms = portage.dep_check(depstr, emptydb, settings,
+                               success, atoms = portage.dep_check(depstr, None, settings,
                                        myuse=usedef, trees=trees, myroot=settings["ROOT"])
                                if not success:
                                        print "\n\n"
@@ -4228,7 +4232,7 @@ def multiple_actions(action1, action2):
        sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
        sys.exit(1)
 
-def parse_opts(tmpcmdline):
+def parse_opts(tmpcmdline, silent=False):
        myaction=None
        myopts = {}
        myfiles=[]
@@ -4237,6 +4241,10 @@ def parse_opts(tmpcmdline):
 
        longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
        argument_options = {
+               "--config-root": {
+                       "help":"specify the location for portage configuration files",
+                       "action":"store"
+               },
                "--color": {
                        "help":"enable or disable color output",
                        "type":"choice",
@@ -4303,7 +4311,9 @@ def parse_opts(tmpcmdline):
                        myfiles.append(x)
 
        if "--nocolor" in myopts:
-               print "*** Deprecated use of '--nocolor', use '--color=n' instead."
+               if not silent:
+                       sys.stderr.write("*** Deprecated use of '--nocolor', " + \
+                               "use '--color=n' instead.\n")
                del myopts["--nocolor"]
                myopts["--color"] = "n"
 
@@ -4324,7 +4334,7 @@ def validate_ebuild_environment(trees):
 def load_emerge_config(trees=None):
        kwargs = {}
        for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
-               kwargs[k] = os.environ.get(envvar, "/")
+               kwargs[k] = os.environ.get(envvar, None)
        trees = portage.create_trees(trees=trees, **kwargs)
 
        settings = trees["/"]["vartree"].settings
@@ -4422,6 +4432,14 @@ def adjust_config(myopts, settings):
                settings.backup_changes("NOCOLOR")
 
 def emerge_main():
+       # This first pass is just for options that need to be known as early as
+       # possible, such as --config-root.  They will be parsed again later,
+       # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
+       # the value of --config-root).
+       myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
+       if "--config-root" in myopts:
+               os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
+
        # Portage needs to ensure a sane umask for the files it creates.
        os.umask(022)
        settings, trees, mtimedb = load_emerge_config()
index f2d4ff85b24496e5e3a12e8b9259d0c07ff82db2..2667aff374727f7516bdb2fe8aaea0acc8724028 100644 (file)
@@ -835,7 +835,7 @@ def check_config_instance(test):
 
 class config:
        def __init__(self, clone=None, mycpv=None, config_profile_path=None,
-               config_incrementals=None, config_root="/", target_root="/",
+               config_incrementals=None, config_root=None, target_root=None,
                local_config=True):
 
                self.already_in_regenerate = 0
@@ -921,18 +921,20 @@ class config:
                        # backupenv is for calculated incremental variables.
                        self.backupenv = os.environ.copy()
 
+                       def check_var_directory(varname, var):
+                               if not os.path.isdir(var):
+                                       writemsg("!!! Error: %s='%s' is not a directory. " + \
+                                               "Please correct this.\n" % (var, varname),
+                                               noiselevel=-1)
+                                       raise portage_exception.DirectoryNotFound(var)
+
+                       if config_root is None:
+                               config_root = "/"
+
                        config_root = \
                                normalize_path(config_root).rstrip(os.path.sep) + os.path.sep
-                       target_root = \
-                               normalize_path(target_root).rstrip(os.path.sep) + os.path.sep
 
-                       for k, v in (("PORTAGE_CONFIGROOT", config_root),
-                               ("ROOT", target_root)):
-                               v = v + EPREFIX
-                               if not os.path.isdir(v):
-                                       writemsg("!!! Error: %s='%s' is not a directory. Please correct this.\n" % (k, v),
-                                               noiselevel=-1)
-                                       raise portage_exception.DirectoryNotFound(v)
+                       check_var_directory("PORTAGE_CONFIGROOT", config_root + EPREFIX)
 
                        self.depcachedir = DEPCACHE_PATH
 
@@ -1126,7 +1128,16 @@ class config:
                                        noiselevel=-1)
                                sys.exit(1)
 
-
+                       # Allow ROOT setting to come from make.conf if it's not overridden
+                       # by the constructor argument (from the calling environment).  As a
+                       # special exception for a very common use case, config_root == "/"
+                       # implies that ROOT in make.conf should be ignored.  That way, the
+                       # user can chroot into $ROOT and the ROOT setting in make.conf will
+                       # be automatically ignored (unless config_root is other than "/").
+                       if config_root != "/" and \
+                               target_root is None and "ROOT" in self.mygcfg:
+                               target_root = self.mygcfg["ROOT"]
+                       
                        self.configlist.append(self.mygcfg)
                        self.configdict["conf"]=self.configlist[-1]
 
@@ -1157,6 +1168,14 @@ class config:
                                                pass
                        del blacklisted, cfg
 
+                       if target_root is None:
+                               target_root = "/"
+
+                       target_root = \
+                               normalize_path(target_root).rstrip(os.path.sep) + os.path.sep
+
+                       check_var_directory("ROOT", target_root + EPREFIX)
+
                        env_d = getconfig(
                                os.path.join(target_root + EPREFIX, "etc", "profile.env"), expand=False)
                        # env_d will be None if profile.env doesn't exist.
@@ -3588,16 +3607,14 @@ def dep_eval(deplist):
                                return 0
                return 1
 
-def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
-       return_all_deps=False):
+def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
        """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)):
+       if not reduced or unreduced == ["||"] or dep_eval(reduced):
                return []
 
        if unreduced[0] != "||":
@@ -3605,9 +3622,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
                for (dep, satisfied) in zip(unreduced, reduced):
                        if isinstance(dep, list):
                                unresolved += dep_zapdeps(dep, satisfied, myroot,
-                                       use_binaries=use_binaries, trees=trees,
-                                       return_all_deps=return_all_deps)
-                       elif not satisfied or return_all_deps:
+                                       use_binaries=use_binaries, trees=trees)
+                       elif not satisfied:
                                unresolved.append(dep)
                return unresolved
 
@@ -3636,8 +3652,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
        for (dep, satisfied) in zip(deps, satisfieds):
                if isinstance(dep, list):
                        atoms = dep_zapdeps(dep, satisfied, myroot,
-                               use_binaries=use_binaries, trees=trees,
-                               return_all_deps=return_all_deps)
+                               use_binaries=use_binaries, trees=trees)
                else:
                        atoms = [dep]
 
@@ -3724,7 +3739,7 @@ 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):
        """Takes a depend string and parses the condition."""
        edebug = mysettings.get("PORTAGE_DEBUG", None) == "1"
        #check_config_instance(mysettings)
@@ -3779,8 +3794,7 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
        try:
                mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
                        use=use, mode=mode, myuse=myuse, use_cache=use_cache,
-                       use_binaries=use_binaries, myroot=myroot, trees=trees,
-                       return_all_deps=return_all_deps)
+                       use_binaries=use_binaries, myroot=myroot, trees=trees)
        except portage_exception.ParseError, e:
                return [0, str(e)]
 
@@ -3794,8 +3808,7 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
        writemsg("mysplit2: %s\n" % (mysplit2), 1)
 
        myzaps = dep_zapdeps(mysplit, mysplit2, myroot,
-               use_binaries=use_binaries, trees=trees,
-               return_all_deps=return_all_deps)
+               use_binaries=use_binaries, trees=trees)
        mylist = flatten(myzaps)
        writemsg("myzaps:   %s\n" % (myzaps), 1)
        writemsg("mylist:   %s\n" % (mylist), 1)
@@ -3808,9 +3821,8 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
 
 def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
        "Reduces the deplist to ones and zeros"
-       mypos=0
        deplist=mydeplist[:]
-       while mypos<len(deplist):
+       for mypos in xrange(len(deplist)):
                if type(deplist[mypos])==types.ListType:
                        #recurse
                        deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
@@ -3821,6 +3833,11 @@ def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
                        if mysettings and mysettings.pprovideddict.has_key(mykey) and \
                                match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
                                deplist[mypos]=True
+                       elif mydbapi is None:
+                               # Assume nothing is satisfied.  This forces dep_zapdeps to
+                               # return all of deps the deps that have been selected
+                               # (excluding those satisfied by package.provided).
+                               deplist[mypos] = False
                        else:
                                if mode:
                                        mydep=mydbapi.xmatch(mode,deplist[mypos])
@@ -3834,7 +3851,6 @@ def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
                                else:
                                        #encountered invalid string
                                        return None
-               mypos=mypos+1
        return deplist
 
 def cpv_getkey(mycpv):
@@ -7335,7 +7351,7 @@ class MtimeDB(dict):
                        commit_mtimedb(mydict=d, filename=self.filename)
                        self._clean_data = copy.deepcopy(d)
 
-def create_trees(config_root="/", target_root="/", trees=None):
+def create_trees(config_root=None, target_root=None, trees=None):
        if trees is None:
                trees = {}
        else:
@@ -7353,11 +7369,11 @@ def create_trees(config_root="/", target_root="/", trees=None):
 
        myroots = [(settings["ROOT"], settings)]
        if settings["ROOT"] != "/":
-               settings = config(config_root="/", target_root="/",
+               settings = config(config_root=None, target_root=None,
                        config_incrementals=portage_const.INCREMENTALS)
                settings.lock()
                settings.validate()
-               myroots.append(("/", settings))
+               myroots.append((settings["ROOT"], settings))
 
        for myroot, mysettings in myroots:
                trees[myroot] = portage_util.LazyItemsDict(trees.get(myroot, None))