Merged from trunk 4998:5012
authorFabian Groffen <grobian@gentoo.org>
Sun, 12 Nov 2006 08:17:34 +0000 (08:17 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sun, 12 Nov 2006 08:17:34 +0000 (08:17 -0000)
Thanks again to Chris White for these additional portage_dep docstrings.

Make digestcheck() fail if an ebuild isn't listed in the Manifest.
Thanks to pva for reporting.

Fix emerge --sync with a cvs:// uri so that it runs
/etc/portage/bin/post_sync  like it would with a normal rsync:// uri.
Thanks to drizzt for reporting.

Fix initial cvs checkout logic for bug #100478.

For initial gentoo-x86 checkout, if $PORTDIR exists and is empty then
remove it so that the gentoo-x86 checkout can replace it.

For bug #154554, validate all profile virtuals atoms.

Fix depgraph.pkg_node_map so that it properly supports $ROOT.

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

bin/emerge
pym/portage.py
pym/portage_dep.py
tarball.sh

index 426a29439e42dde7e623c06dee309a5bd176cd2a..ee3dab027887986977c225ade5a778b4f93bef25 100755 (executable)
@@ -722,9 +722,11 @@ class depgraph:
                        self.edebug = 1
                self.spinner = spinner
                self.pkgsettings = {}
+               self.pkg_node_map = {}
                for myroot in self.trees:
                        self.pkgsettings[myroot] = portage.config(
                                clone=trees[myroot]["vartree"].settings)
+                       self.pkg_node_map[myroot] = {}
                self.useFlags = {}
                self.useFlags[self.target_root] = {}
                if self.target_root != "/":
@@ -760,7 +762,6 @@ class depgraph:
                                        "--getbinpkgonly" in self.myopts)
                self.args_keys = []
                self.global_updates = {}
-               self.pkg_node_map = {}
                self.blocker_digraph = digraph()
                self.blocker_parents = {}
 
@@ -778,32 +779,31 @@ class depgraph:
                #"no downgrade" emerge
                """
                jbigkey = " ".join(mybigkey) + " merge"
+               mytype, myroot, mykey = mybigkey
                if self.digraph.hasnode(jbigkey):
                        if addme and jbigkey != myparent:
                                # Refuse to make a node depend on itself so that the we don't
                                # don't create a bogus circular dependency in self.altlist().
+                               self.pkg_node_map[myroot][mykey] = jbigkey
                                if rev_dep and myparent:
-                                       self.pkg_node_map[myparent.split()[2]] = myparent
+                                       ptype, proot, pkey, pstatus = myparent.split()
+                                       self.pkg_node_map[proot][pkey] = myparent
                                        self.digraph.addnode(myparent, jbigkey, priority=priority)
                                else:
-                                       self.pkg_node_map[mybigkey[2]] = jbigkey
                                        self.digraph.addnode(jbigkey, myparent, priority=priority)
                        return 1
                jbigkey = " ".join(mybigkey) + " nomerge"
                if self.digraph.hasnode(jbigkey):
-                       """XXX: It's possible that this package has been explicitly
-                       requested as a command line argument.  This can be solved by
-                       checking all args prior to marking packages as nomerge"""
+                       self.pkg_node_map[myroot][mykey] = jbigkey
                        if rev_dep and myparent:
-                               self.pkg_node_map[myparent.split()[2]] = myparent
+                               ptype, proot, pkey, pstatus = myparent.split()
+                               self.pkg_node_map[proot][pkey] = myparent
                                self.digraph.addnode(myparent, jbigkey, priority=priority)
                        else:
-                               self.pkg_node_map[mybigkey[2]] = jbigkey
                                self.digraph.addnode(jbigkey, myparent, priority=priority)
                        return 1
                
                self.spinner.update()
-               mytype,myroot,mykey=mybigkey
                if mytype == "blocks":
                        if addme and "--buildpkgonly" not in self.myopts and myparent:
                                mybigkey[1] = myparent.split()[1]
@@ -872,12 +872,13 @@ class depgraph:
                    depgraph already and returned, or we are here.  Whether we are merging or not; we must
                    add the package to the depgraph; so we do that here. """
                jbigkey = " ".join(mybigkey)
+               self.pkg_node_map[myroot][mykey] = jbigkey
                if rev_dep and myparent:
-                       self.pkg_node_map[myparent.split()[2]] = myparent
+                       ptype, proot, pkey, pstatus = myparent.split()
+                       self.pkg_node_map[proot][pkey] = myparent
                        self.digraph.addnode(myparent, jbigkey,
                                priority=priority)
                else:
-                       self.pkg_node_map[mybigkey[2]] = jbigkey
                        self.digraph.addnode(jbigkey, myparent,
                                priority=priority)
 
@@ -1484,7 +1485,7 @@ class depgraph:
                                                        unresolvable = True
                                                        break
                                                # Enforce correct merge order with a hard dep.
-                                               node = self.pkg_node_map[pkg]
+                                               node = self.pkg_node_map[proot][pkg]
                                                self.digraph.addnode(node, parent,
                                                        priority=DepPriority(buildtime=True))
                                                """Count references to this blocker so that it can be
@@ -1519,7 +1520,7 @@ class depgraph:
                        get_nodes = mygraph.root_nodes
                else:
                        get_nodes = mygraph.leaf_nodes
-                       for cpv, node in self.pkg_node_map.iteritems():
+                       for cpv, node in self.pkg_node_map["/"].iteritems():
                                if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
                                        asap_nodes.append(node)
                                        break
@@ -3095,6 +3096,7 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                os.makedirs(myportdir,0755)
        syncuri=string.rstrip(settings["SYNC"])
        os.umask(0022)
+       updatecache_flg = False
        if myaction == "metadata":
                print "skipping sync"
                updatecache_flg = True
@@ -3413,16 +3415,26 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                        if os.path.exists(cvsdir+"/gentoo-x86"):
                                print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
                                sys.exit(1)
+                       try:
+                               os.rmdir(myportdir)
+                       except OSError, e:
+                               if e.errno != errno.ENOENT:
+                                       sys.stderr.write(
+                                               "!!! existing '%s' directory; exiting.\n" % myportdir)
+                                       sys.exit(1)
+                               del e
                        if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
                                print "!!! cvs checkout error; exiting."
                                sys.exit(1)
-                       if cvsdir!=myportdir:
-                               portage.movefile(cvsdir,settings["PORTDIR"])
-                       sys.exit(0)
+                       os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
                else:
                        #cvs update
                        print ">>> Starting cvs update with "+syncuri+"..."
-                       sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",settings,free=1))
+                       retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
+                               myportdir, settings, free=1)
+                       if retval != os.EX_OK:
+                               sys.exit(retval)
+               dosyncuri = syncuri
        else:
                print "!!! rsync setting: ",syncuri,"not recognized; exiting."
                sys.exit(1)
@@ -3454,9 +3466,10 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
 
        if myaction != "metadata":
                if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
-                       try:
-                               portage.spawn(portage.USER_CONFIG_PATH + "/bin/post_sync " + dosyncuri, settings, free=1)
-                       except:
+                       retval = portage.portage_exec.spawn(
+                               [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
+                               dosyncuri], env=settings.environ())
+                       if retval != os.EX_OK:
                                print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
 
        if(mybestpv != mypvs) and not "--quiet" in myopts:
index 68bf31953d9eaa400e434a1d97cb2dc0f4b4c440..4465df73dc9ab513107e412bc95cee03fbdc25e4 100644 (file)
@@ -1829,9 +1829,29 @@ class config:
                if self.virtuals:
                        return self.virtuals
 
-               self.dirVirtuals = stack_dictlist(
-                       [grabdict_package(os.path.join(x, "virtuals")) \
-                       for x in self.profiles], incremental=True)
+               virtuals_list = []
+               for x in self.profiles:
+                       virtuals_file = os.path.join(x, "virtuals")
+                       virtuals_dict = grabdict(virtuals_file)
+                       for k in virtuals_dict.keys():
+                               if not isvalidatom(k) or dep_getkey(k) != k:
+                                       writemsg("--- Invalid virtuals atom in %s: %s\n" % \
+                                               (virtuals_file, k), noiselevel=-1)
+                                       del virtuals_dict[k]
+                                       continue
+                               myvalues = virtuals_dict[k]
+                               for x in myvalues:
+                                       if not isvalidatom(x):
+                                               writemsg("--- Invalid atom in %s: %s\n" % \
+                                                       (virtuals_file, x), noiselevel=-1)
+                                               myvalues.remove(x)
+                               if not myvalues:
+                                       del virtuals_dict[k]
+                       if virtuals_dict:
+                               virtuals_list.append(virtuals_dict)
+
+               self.dirVirtuals = stack_dictlist(virtuals_list, incremental=True)
+               del virtuals_list
 
                for virt in self.dirVirtuals:
                        # Preference for virtuals decreases from left to right.
@@ -2566,6 +2586,12 @@ def digestcheck(myfiles, mysettings, strict=0, justmanifest=0):
                writemsg("!!! Got: %s\n" % e.value[2], noiselevel=-1)
                writemsg("!!! Expected: %s\n" % e.value[3], noiselevel=-1)
                return 0
+       # Make sure that all of the ebuilds are actually listed in the Manifest.
+       for f in os.listdir(pkgdir):
+               if f.endswith(".ebuild") and not mf.hasFile("EBUILD", f):
+                       writemsg("!!! A file is not listed in the Manifest: '%s'\n" % \
+                               os.path.join(pkgdir, f), noiselevel=-1)
+                       return 0
        """ epatch will just grab all the patches out of a directory, so we have to
        make sure there aren't any foreign files that it might grab."""
        filesdir = os.path.join(pkgdir, "files")
index d28d79428c2c59edee28b29732947bcd0572972e..45467397c93b29e12138e57ad49c7130cfc3e28d 100644 (file)
@@ -23,13 +23,37 @@ import portage_exception
 from portage_versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify
 
 def strip_empty(myarr):
+       """
+       Strip all empty elements from an array
+
+       @param myarr: The list of elements
+       @type myarr: List
+       @rtype: Array
+       @return: The array with empty elements removed
+       """
        for x in range(len(myarr)-1, -1, -1):
                if not myarr[x]:
                        del myarr[x]
        return myarr
 
 def paren_reduce(mystr,tokenize=1):
-       "Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists"
+       """
+       Take a string and convert all paren enclosed entities into sublists, optionally
+       futher splitting the list elements by spaces.
+
+       Example usage:
+               >>> paren_reduce('foobar foo ( bar baz )',1)
+               ['foobar', 'foo', ['bar', 'baz']]
+               >>> paren_reduce('foobar foo ( bar baz )',0)
+               ['foobar foo ', [' bar baz ']]
+
+       @param mystr: The string to reduce
+       @type mystr: String
+       @param tokenize: Split on spaces to produces further list breakdown
+       @type tokenize: Integer
+       @rtype: Array
+       @return: The reduced string in an array
+       """
        mylist = []
        while mystr:
                if ("(" not in mystr) and (")" not in mystr):
@@ -61,6 +85,11 @@ def paren_enclose(mylist):
        """
        Convert a list to a string with sublists enclosed with parens.
 
+       Example usage:
+               >>> test = ['foobar','foo',['bar','baz']]
+               >>> paren_enclose(test)
+               'foobar foo ( bar baz )'
+
        @param mylist: The list
        @type mylist: List
        @rtype: String
@@ -97,7 +126,7 @@ def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
                                raise portage_exception.InvalidDependString(deparray[x]+" missing atom list in \""+paren_enclose(deparray)+"\"")
        if deparray and deparray[-1] and deparray[-1][-1] == "?":
                raise portage_exception.InvalidDependString("Conditional without target in \""+paren_enclose(deparray)+"\"")
-       
+
        mydeparray = deparray[:]
        rlist = []
        while mydeparray:
@@ -172,9 +201,9 @@ def dep_opconvert(deplist):
        list of deps that follows..
 
        Example usage:
-       >>> test = ["blah", "||", ["foo", "bar", "baz"]]
-       >>> dep_opconvert(test)
-       ['blah', ['||', 'foo', 'bar', 'baz']]
+               >>> test = ["blah", "||", ["foo", "bar", "baz"]]
+               >>> dep_opconvert(test)
+               ['blah', ['||', 'foo', 'bar', 'baz']]
 
        @param deplist: A list of deps to format
        @type mydep: List
@@ -201,15 +230,15 @@ def get_operator(mydep):
        Return the operator used in a depstring.
 
        Example usage:
-       >>> from portage_dep import *
-       >>> get_operator(">=test-1.0")
-       '>='
+               >>> from portage_dep import *
+               >>> get_operator(">=test-1.0")
+               '>='
 
        @param mydep: The dep string to check
        @type mydep: String
        @rtype: String
-       @return:
-               The operator. One of: '~', '=', '>', '<', '=*', '>=', or '<='
+       @return: The operator. One of:
+               '~', '=', '>', '<', '=*', '>=', or '<='
        """
        if mydep[0] == "~":
                operator = "~"
@@ -229,6 +258,18 @@ def get_operator(mydep):
        return operator
 
 def dep_getcpv(mydep):
+       """
+       Return the category-package-version with any operators/slot specifications stripped off
+
+       Example usage:
+               >>> dep_getcpv('>=media-libs/test-3.0')
+               'media-libs/test-3.0'
+
+       @param mydep: The depstring
+       @type mydep: String
+       @rtype: String
+       @return: The depstring with the operator removed
+       """
        if mydep and mydep[0] == "*":
                mydep = mydep[1:]
        if mydep and mydep[-1] == "*":
@@ -245,12 +286,40 @@ def dep_getcpv(mydep):
        return mydep
 
 def dep_getslot(mydep):
+       """
+       Retrieve the slot on a depend.
+
+       Example usage:
+               >>> dep_getslot('app-misc/test:3')
+               '3'
+
+       @param mydep: The depstring to retrieve the slot of
+       @type mydep: String
+       @rtype: String
+       @return: The slot
+       """
        colon = mydep.rfind(":")
        if colon != -1:
                return mydep[colon+1:]
        return None
 
 def isvalidatom(atom):
+       """
+       Check to see if a depend atom is valid
+
+       Example usage:
+               >>> isvalidatom('media-libs/test-3.0')
+               0
+               >>> isvalidatom('>=media-libs/test-3.0')
+               1
+
+       @param atom: The depend atom to check against
+       @type atom: String
+       @rtype: Integer
+       @return: One of the following:
+               1) 0 if the atom is invalid
+               2) 1 if the atom is valid
+       """
        mycpv_cps = catpkgsplit(dep_getcpv(atom))
        operator = get_operator(atom)
        if operator:
@@ -273,6 +342,24 @@ def isvalidatom(atom):
                return 0
 
 def isjustname(mypkg):
+       """
+       Checks to see if the depstring is only the package name
+
+       Example usage:
+               >>> isjustname('media-libs/test-3.0')
+               0
+               >>> isjustname('test')
+               1
+               >>> isjustname('media-libs/test')
+               1
+
+       @param mypkg: The package atom to check
+       @param mypkg: String
+       @rtype: Integer
+       @return: One of the following:
+               1) 0 if the package string is not just the package name
+               2) 1 if it is
+       """
        myparts = mypkg.split('-')
        for x in myparts:
                if ververify(x):
@@ -282,7 +369,23 @@ def isjustname(mypkg):
 iscache = {}
 
 def isspecific(mypkg):
-       "now supports packages with no category"
+       """
+       Checks to see if a package is in category/package-version or package-version format,
+       possibly returning a cached result.
+
+       Example usage:
+               >>> isspecific('media-libs/test')
+               0
+               >>> isspecific('media-libs/test-3.0')
+               1
+
+       @param mypkg: The package depstring to check against
+       @type mypkg: String
+       @rtype: Integer
+       @return: One of the following:
+               1) 0 if the package string is not specific
+               2) 1 if it is
+       """
        try:
                return iscache[mypkg]
        except KeyError:
@@ -295,6 +398,18 @@ def isspecific(mypkg):
        return 0
 
 def dep_getkey(mydep):
+       """
+       Return the category/package-name of a depstring.
+
+       Example usage:
+               >>> dep_getkey('media-libs/test-3.0')
+               'media-libs/test'
+
+       @param mydep: The depstring to retrieve the category/package-name of
+       @type mydep: String
+       @rtype: String
+       @return: The package category/package-version
+       """
        mydep = dep_getcpv(mydep)
        if mydep and isspecific(mydep):
                mysplit = catpkgsplit(mydep)
@@ -305,8 +420,15 @@ def dep_getkey(mydep):
                return mydep
 
 def match_to_list(mypkg, mylist):
-       """(pkgname, list)
+       """
        Searches list for entries that matches the package.
+
+       @param mypkg: The package atom to match
+       @type mypkg: String
+       @param mylist: The list of package atoms to compare against
+       @param mylist: List
+       @rtype: List
+       @return: A unique list of package atoms that match the given package atom
        """
        matches = []
        for x in mylist:
@@ -316,18 +438,24 @@ def match_to_list(mypkg, mylist):
        return matches
 
 def best_match_to_list(mypkg, mylist):
-       """(pkgname, list)
+       """
        Returns the most specific entry that matches the package given.
-       Type    Value
-       =cpv      6
-       ~cpv      5
-       =cpv*     4
-       cp:slot   3
-       >cpv      2
-       <cpv      2
-       >=cpv     2
-       <=cpv     2
-       cp        1
+
+       @param mypkg: The package atom to check
+       @type mypkg: String
+       @param mylist: The list of package atoms to check against
+       @type mylist: List
+       @rtype: String
+       @return: The package atom which best matches given the following ordering:
+               - =cpv      6
+               - ~cpv      5
+               - =cpv*     4
+               - cp:slot   3
+               - >cpv      2
+               - <cpv      2
+               - >=cpv     2
+               - <=cpv     2
+               - cp        1
        """
        operator_values = {'=':6, '~':5, '=*':4,
                '>':2, '<':2, '>=':2, '<=':2, None:1}
@@ -346,6 +474,17 @@ def best_match_to_list(mypkg, mylist):
        return bestm
 
 def match_from_list(mydep, candidate_list):
+       """
+       Searches list for entries that matches the package.
+
+       @param mydep: The package atom to match
+       @type mydep: String
+       @param candidate_list: The list of package atoms to compare against
+       @param candidate_list: List
+       @rtype: List
+       @return: A list of package atoms that match the given package atom
+       """
+
        from portage_util import writemsg
        if mydep[0] == "!":
                mydep = mydep[1:]
index 1833a80091d9f27398d0da2d551ac46661ce4acf..4159133248b94fa503dd2436fb0c9aeaae9a4b3b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # $Id: $
 
 if [ -z "$1" ]; then