From b7675a953002139ea2547d6df70ebd95189f803e Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Sun, 12 Nov 2006 08:17:34 +0000 Subject: [PATCH] Merged from trunk 4998:5012 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 | 53 ++++++++----- pym/portage.py | 32 +++++++- pym/portage_dep.py | 185 +++++++++++++++++++++++++++++++++++++++------ tarball.sh | 2 +- 4 files changed, 225 insertions(+), 47 deletions(-) diff --git a/bin/emerge b/bin/emerge index 426a29439..ee3dab027 100755 --- a/bin/emerge +++ b/bin/emerge @@ -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: diff --git a/pym/portage.py b/pym/portage.py index 68bf31953..4465df73d 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -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") diff --git a/pym/portage_dep.py b/pym/portage_dep.py index d28d79428..45467397c 100644 --- a/pym/portage_dep.py +++ b/pym/portage_dep.py @@ -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 - 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 + - 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:] diff --git a/tarball.sh b/tarball.sh index 1833a8009..415913324 100755 --- a/tarball.sh +++ b/tarball.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # $Id: $ if [ -z "$1" ]; then -- 2.26.2