From: Kito Date: Wed, 29 Mar 2006 03:45:29 +0000 (-0000) Subject: merge from trunk -r 3004:3030 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=24871f48ac4f0d4bb0a2294f6ed6743dccd27e10;p=portage.git merge from trunk -r 3004:3030 svn path=/main/branches/prefix/; revision=3031 --- diff --git a/AUTHORS b/AUTHORS index e69de29bb..41d3e4a26 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1,8 @@ +In addition to the the long list of regular portage contributors, these folks have put their hard work into this. + +Michael Haubenwallner +Brian Harring +Kito Dietrich +Fabian Groffen +Emanuele Giaquinta + diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 68ec8655c..307339264 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -320,7 +320,26 @@ with_localstatedir() { echo "--localstatedir=${mylocalstatedir}" return 0 } - + +with_tmpdir() { + local mytmpdir + if [ -z "${1}" ]; then + if [ ! -z "${EPREFIX}" ]; then + mytmpdir="${EPREFIX}/tmp" + else + mytmpdir="/tmp" + fi + else + if [ ! -z "${EPREFIX}" ]; then + mytmpdir="${EPREFIX}${1}" + else + mytmpdir="${1}" + fi + fi + echo "--with-tmpdir=${mytmpdir}" + return 0 +} + use_with() { if [ -z "$1" ]; then echo "!!! use_with() called without a parameter." >&2 @@ -540,6 +559,7 @@ unpack() { ;; esac done + chmod -Rf a+rX,u+w,g-w,o-w . } strip_duplicate_slashes () { diff --git a/bin/emerge b/bin/emerge index aa1110eff..669c3df40 100755 --- a/bin/emerge +++ b/bin/emerge @@ -612,16 +612,23 @@ if portage.wheelgid == portage.portage_gid: print "emerge: wheel group use is being deprecated. Please update group and passwd to" print " include the portage user as noted above, and then use group portage." +if "--debug" in myopts: + print "myaction", myaction + print "myopts", myopts + # check if root user is the current user for the actions where emerge needs this if portage.secpass < 2: # We've already allowed "--version" and "--help" above. if "--pretend" not in myopts and \ myaction not in ("search","info"): - if "--debug" in myopts: - print "myaction",myaction - print "myopts",myopts - print "emerge: root access required." - sys.exit(1) + if portage.secpass >= 1: + if "--fetchonly" not in myopts and \ + "--fetch-all-uri" not in myopts: + print "emerge: root access required." + sys.exit(1) + else: + print "emerge: root access required." + sys.exit(1) if not "--pretend" in myopts: emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime())) @@ -2559,7 +2566,7 @@ if myaction in ["sync","metadata"] and (not "--help" in myopts): if portage.settings["RSYNC_TIMEOUT"] != "": portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \ - "use PORTAGE_RSYNC_OPTS instead\n") + "use PORTAGE_RSYNC_EXTRA_OPTS instead\n") try: mytimeout = int(portage.settings["RSYNC_TIMEOUT"]) rsync_opts.append("--timeout=%d" % mytimeout) diff --git a/bin/repoman b/bin/repoman index b1babde77..c54ffbd42 100755 --- a/bin/repoman +++ b/bin/repoman @@ -1714,7 +1714,7 @@ else: del myfiles[x] mydone=[] if repolevel==3: # In a package dir - repoman_settings["O"]="./" + repoman_settings["O"]=os.getcwd() portage.digestgen([],repoman_settings,manifestonly=1) elif repolevel==2: # In a category dir for x in myfiles: @@ -1724,7 +1724,7 @@ else: if xs[0] in mydone: continue mydone.append(xs[0]) - repoman_settings["O"]="./"+xs[0] + repoman_settings["O"]=os.path.join(os.getcwd(), xs[0]) portage.digestgen([],repoman_settings,manifestonly=1) elif repolevel==1: # repo-cvsroot print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n" @@ -1735,7 +1735,7 @@ else: if string.join(xs[:2],"/") in mydone: continue mydone.append(string.join(xs[:2],"/")) - repoman_settings["O"]="./"+string.join(xs[:2],"/") + repoman_settings["O"]=os.path.join(os.getcwd(), x[0], x[1]) portage.digestgen([],repoman_settings,manifestonly=1) else: print red("I'm confused... I don't know where I am!") diff --git a/cnf/make.conf b/cnf/make.conf index 37e2603eb..d7f22c4a3 100644 --- a/cnf/make.conf +++ b/cnf/make.conf @@ -313,7 +313,8 @@ PORTAGE_ELOG_CLASSES="warn error log" # PORTAGE_ELOG_SYSTEM: selects the module(s) to process the log messages. Modules # included in portage are (empty means logging is disabled): -# save (saves one log per package in $PORTAGE_TMPDIR/elogs) +# save (saves one log per package in $PORT_LOGDIR/elog, +# /var/log/portage/elog if $PORT_LOGDIR is unset) # custom (passes all messages to $PORTAGE_LOG_COMMAND) # syslog (sends all messages to syslog) # mail (send all messages to the mailserver defined @@ -345,3 +346,14 @@ PORTAGE_ELOG_CLASSES="warn error log" #PORTAGE_ELOG_MAILURI="root@localhost localhost" (this is also the default setting) #PORTAGE_ELOG_MAILURI="user@some.domain mail.some.domain" (sends mails to user@some.domain using the mailserver mail.some.domain) #PORTAGE_ELOG_MAILURI="user@some.domain user:secret@mail.some.domain:100465" (this is left uncommented as a reader excercise ;) + +# PORTAGE_ELOG_MAILFROM: you can set the from-address of logmails with this variable, +# if unset mails are sent by "portage" (this default may fail +# in some environments). +#PORTAGE_ELOG_MAILFROM="portage@some.domain" + +# PORTAGE_ELOG_MAILSUBJECT: template string to be used as subject for logmails. The following +# variables are exanded: +# ${PACKAGE} - see description of PORTAGE_ELOG_COMMAND +# ${HOST} - FQDN of the host portage is running on +#PORTAGE_ELOG_MAILSUBJECT="package ${PACKAGE} merged on ${HOST} with notice" diff --git a/cnf/make.globals b/cnf/make.globals index bafa508c1..91dfb121c 100644 --- a/cnf/make.globals +++ b/cnf/make.globals @@ -77,6 +77,12 @@ DEFAULT_PATH="@DOMAIN_PREFIX@/sbin:@DOMAIN_PREFIX@/usr/sbin:@DOMAIN_PREFIX@/bin: # Mode bits for ${WORKDIR} (see ebuild.5). PORTAGE_WORKDIR_MODE="0700" +# Some defaults for elog +PORTAGE_ELOG_CLASSES="log warn error" + +PORTAGE_ELOG_MAILURI="@rootuser@" +PORTAGE_ELOG_MAILSUBJECT="[portage] ebuild log for \${PACKAGE} on \${HOST}" +PORTAGE_ELOG_MAILFROM="portage" # ***************************** # ** DO NOT EDIT THIS FILE ** diff --git a/pym/elog_modules/mod_mail.py b/pym/elog_modules/mod_mail.py index 59fd56a8e..68771ba51 100644 --- a/pym/elog_modules/mod_mail.py +++ b/pym/elog_modules/mod_mail.py @@ -14,29 +14,35 @@ def process(mysettings, cpv, logentries, fulltext): # passwd: password for smtp auth (defaults to none) # mailserver: smtp server that should be used to deliver the mail (defaults to localhost) # port: port to use on the given smtp server (defaults to 25, values > 100000 indicate that starttls should be used on (port-100000)) - if "PORTAGE_ELOG_MAILURI" in mysettings.keys(): - if " " in mysettings["PORTAGE_ELOG_MAILURI"]: - myrecipient, mymailuri = mysettings["PORTAGE_ELOG_MAILURI"].split() - if "@" in mymailuri: - myauthdata, myconndata = mymailuri.rsplit("@", 1) - try: - mymailuser,mymailpasswd = myauthdata.split(":") - except ValueError: - print "!!! invalid SMTP AUTH configuration, trying unauthenticated ..." - else: - myconndata = mymailuri - if ":" in myconndata: - mymailhost,mymailport = myconndata.split(":") - else: - mymailhost = myconndata + if " " in mysettings["PORTAGE_ELOG_MAILURI"]: + myrecipient, mymailuri = mysettings["PORTAGE_ELOG_MAILURI"].split() + if "@" in mymailuri: + myauthdata, myconndata = mymailuri.rsplit("@", 1) + try: + mymailuser,mymailpasswd = myauthdata.split(":") + except ValueError: + print "!!! invalid SMTP AUTH configuration, trying unauthenticated ..." else: - myrecipient = mysettings["PORTAGE_ELOG_MAILURI"] + myconndata = mymailuri + if ":" in myconndata: + mymailhost,mymailport = myconndata.split(":") + else: + mymailhost = myconndata + else: + myrecipient = mysettings["PORTAGE_ELOG_MAILURI"] try: + myfrom = mysettings["PORTAGE_ELOG_MAILFROM"] + mymessage = email.Message.Message() - mymessage.set_unixfrom("portage") + mymessage.set_unixfrom(myfrom) mymessage.set_payload(fulltext) mymessage["To"] = myrecipient - mymessage["Subject"] = "[portage] Ebuild log for %s" % cpv + + mysubject = mysettings["PORTAGE_ELOG_MAILSUBJECT"] + mysubject = mysubject.replace("${PACKAGE}", cpv) + mysubject = mysubject.replace("${HOST}", socket.getfqdn()) + + mymessage["Subject"] = mysubject if int(mymailport) > 100000: myconn = smtplib.SMTP(mymailhost, int(mymailport) - 100000) @@ -45,10 +51,10 @@ def process(mysettings, cpv, logentries, fulltext): myconn = smtplib.SMTP(mymailhost, mymailport) if mymailuser != "" and mymailpasswd != "": myconn.login(mymailuser, mymailpasswd) - myconn.sendmail("portage", myrecipient, mymessage.as_string()) + myconn.sendmail(myfrom, myrecipient, mymessage.as_string()) myconn.quit() except smtplib.SMTPException, e: raise portage_exception.PortageException("!!! An error occured while trying to send logmail:\n"+str(e)) except socket.error, e: - raise portage_exception.PortageException("!!! A network error occured while trying to send logmail:\n"+str(e)+"\nSure you configured PORTAGE_LOG_MAILURI correctly?") + raise portage_exception.PortageException("!!! A network error occured while trying to send logmail:\n"+str(e)+"\nSure you configured PORTAGE_ELOG_MAILURI correctly?") return diff --git a/pym/elog_modules/mod_save.py b/pym/elog_modules/mod_save.py index 106e8800a..6c16c2041 100644 --- a/pym/elog_modules/mod_save.py +++ b/pym/elog_modules/mod_save.py @@ -4,7 +4,10 @@ from portage_data import portage_uid, portage_gid def process(mysettings, cpv, logentries, fulltext): cpv_path = cpv.replace("/", ":") - elogdir = mysettings["PORTAGE_TMPDIR"]+"/elogs" + if mysettings["PORT_LOGDIR"] != "": + elogdir = os.path.join(mysettings["PORT_LOGDIR"], "elog") + else: + elogdir = os.path.join(os.sep, "var", "log", "portage", "elog") if not os.path.exists(elogdir): os.makedirs(elogdir) os.chown(elogdir, portage_uid, portage_gid) diff --git a/pym/output.py b/pym/output.py index f23bac263..e735d4d47 100644 --- a/pym/output.py +++ b/pym/output.py @@ -132,47 +132,24 @@ def nocolor(): def resetColor(): return codes["reset"] -def ctext(color,text): - return codes[ctext]+text+codes["reset"] - -def bold(text): - return codes["bold"]+text+codes["reset"] -def white(text): - return bold(text) - -def teal(text): - return codes["teal"]+text+codes["reset"] -def turquoise(text): - return codes["turquoise"]+text+codes["reset"] -def darkteal(text): - return turquoise(text) - -def fuscia(text): # Don't use this one. It's spelled wrong! - return codes["fuchsia"]+text+codes["reset"] -def fuchsia(text): - return codes["fuchsia"]+text+codes["reset"] -def purple(text): - return codes["purple"]+text+codes["reset"] - -def blue(text): - return codes["blue"]+text+codes["reset"] -def darkblue(text): - return codes["darkblue"]+text+codes["reset"] - -def green(text): - return codes["green"]+text+codes["reset"] -def darkgreen(text): - return codes["darkgreen"]+text+codes["reset"] - -def yellow(text): - return codes["yellow"]+text+codes["reset"] -def brown(text): - return codes["brown"]+text+codes["reset"] -def darkyellow(text): - return brown(text) - -def red(text): - return codes["red"]+text+codes["reset"] -def darkred(text): - return codes["darkred"]+text+codes["reset"] - +def colorize(color_key, text): + return codes[color_key] + text + codes["reset"] + +codes["darkteal"] = codes["turquoise"] +codes["darkyellow"] = codes["brown"] +codes["fuscia"] = codes["fuchsia"] +codes["white"] = codes["bold"] + +compat_functions_colors = ["bold","white","teal","turquoise","darkteal", + "fuscia","fuchsia","purple","blue","darkblue","green","darkgreen","yellow", + "brown","darkyellow","red","darkred"] + +def create_color_func(color_key): + def derived_func(*args): + newargs = list(args) + newargs.insert(0, color_key) + return colorize(*newargs) + return derived_func + +for c in compat_functions_colors: + setattr(sys.modules[__name__], c, create_color_func(c)) diff --git a/pym/portage.py b/pym/portage.py index f7341ce86..b3518ebf1 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -215,7 +215,7 @@ def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymli if stat.S_ISDIR(pathstat[stat.ST_MODE]): mtime = pathstat[stat.ST_MTIME] else: - raise portage_exception.PortageException + raise portage_exception.DirectoryNotFound(mypath) except (IOError,OSError,portage_exception.PortageException): if EmptyOnError: return [], [] @@ -2505,70 +2505,72 @@ def prepare_build_dirs(myroot, mysettings, cleanup): writemsg("File Not Found: '%s'\n" % str(e)) return 1 - if "ccache" in features: - ccache_enabled = True - if "CCACHE_DIR" not in mysettings or "" == mysettings["CCACHE_DIR"]: - mysettings["CCACHE_DIR"] = os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache") - - ccache_enabled = makedirs(mysettings["CCACHE_DIR"]) - - if ccache_enabled: - ccache_enabled = apply_recursive_permissions( - mysettings["CCACHE_DIR"], gid=portage_gid, - dirmode=02070, dirmask=02, - filemode=060, filemask=02) - - if not ccache_enabled: - writemsg("!!! Failed resetting perms on CCACHE_DIR='%s'\n" % mysettings["CCACHE_DIR"]) - features.remove("ccache") - mysettings["FEATURES"] = " ".join(features) - - del ccache_enabled - - if "confcache" in features: - confcache_enabled = True - if "CONFCACHE_DIR" not in mysettings: - mysettings["CONFCACHE_DIR"] = os.path.join(mysettings["PORTAGE_TMPDIR"], "confcache") - - confcache_enabled = makedirs(mysettings["CONFCACHE_DIR"]) - - if confcache_enabled: - confcache_enabled = apply_recursive_permissions( - mysettings["CONFCACHE_DIR"], gid=portage_gid, - dirmode=02070, dirmask=02, - filemode=060, filemask=02) - - if not confcache_enabled: - writemsg("!!! Failed resetting perms on confcachedir %s\n" % mysettings["CONFCACHE_DIR"]) - features.remove("confcache") - mysettings["FEATURES"] = " ".join(features) - - del confcache_enabled - - if "distcc" in features: - - distcc_enabled = True - - if "DISTCC_DIR" not in mysettings or "" == mysettings["DISTCC_DIR"]: - mysettings["DISTCC_DIR"] = os.path.join(mysettings["BUILD_PREFIX"], ".distcc") - for x in ("", "lock", "state"): - mydir = os.path.join(mysettings["DISTCC_DIR"], x) - if not makedirs(mydir): - distcc_enabled = False - break - - if distcc_enabled: - distcc_enabled = apply_recursive_permissions( - mysettings["DISTCC_DIR"], gid=portage_gid, - dirmode=02070, dirmask=02, filemode=060, filemask=02) - - if not distcc_enabled: - writemsg("\n!!! File system problem when setting DISTCC_DIR directory permissions.\n") - writemsg( "!!! DISTCC_DIR="+str(mysettings["DISTCC_DIR"]+"\n")) - time.sleep(5) - features.remove("distcc") - mysettings["FEATURES"] = " ".join(features) - mysettings["DISTCC_DIR"]="" + features_dirs = { + "ccache":{ + "basedir_var":"CCACHE_DIR", + "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"), + "always_recurse":False}, + "confcache":{ + "basedir_var":"CONFCACHE_DIR", + "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "confcache"), + "always_recurse":True}, + "distcc":{ + "basedir_var":"DISTCC_DIR", + "default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"), + "subdirs":("lock", "state"), + "always_recurse":True} + } + dirmode = 02070 + filemode = 060 + modemask = 02 + for myfeature, kwargs in features_dirs.iteritems(): + if myfeature in features: + basedir = mysettings[kwargs["basedir_var"]] + if basedir == "": + basedir = kwargs["default_dir"] + mysettings[kwargs["basedir_var"]] = basedir + try: + mydirs = [mysettings[kwargs["basedir_var"]]] + if "subdirs" in kwargs: + for subdir in kwargs["subdirs"]: + mydirs.append(os.path.join(basedir, subdir)) + for mydir in mydirs: + if not makedirs(mydir): + raise portage_exception.DirectoryNotFound( + "Failed to create directory.") + try: + initial_stat = os.stat(mydir) + apply_secpass_permissions(mydir, + gid=portage_gid, mode=dirmode, mask=modemask, stat_cached=initial_stat) + result_stat = os.stat(mydir) + except OSError, oe: + if errno.EPERM == oe.errno: + writemsg("!!! %s\n" % oe) + raise portage_exception.OperationNotPermitted("stat('%s')" % mydir) + raise + # To avoid excessive recursive stat calls, we trigger + # recursion when the top level directory does not initially + # match our permission requirements. + if kwargs["always_recurse"] or \ + result_stat.st_gid != initial_stat.st_gid or \ + result_stat.st_mode & 07777 != initial_stat.st_mode & 07777: + if not kwargs["always_recurse"]: + writemsg("Adjusting permissions recursively: '%s'" % mydir) + def onerror(e): + raise # The feature is disabled if a single error + # occurs during permissions adjustment. + if not apply_recursive_permissions(mydir, + gid=portage_gid, dirmode=dirmode, dirmask=modemask, + filemode=filemode, filemask=modemask, onerror=onerror): + raise portage_exception.OperationNotPermitted( + "Failed to apply recursive permissions for the portage group.") + except portage_exception.PortageException, e: + features.remove(myfeature) + mysettings["FEATURES"] = " ".join(features) + writemsg("!!! %s\n" % str(e)) + writemsg("!!! Failed resetting perms on %s='%s'\n" % (kwargs["basedir_var"], basedir)) + writemsg("!!! Disabled FEATURES='%s'\n" % myfeature) + time.sleep(5) workdir_mode = 0700 try: @@ -5875,9 +5877,11 @@ class dblink: if self.pkg in otherversions: otherversions.remove(self.pkg) # we already checked this package + myslot = self.settings["SLOT"] for v in otherversions: - # should we check for same SLOT here ? - mypkglist.append(dblink(self.cat,v,destroot,self.settings)) + # only allow versions with same slot to overwrite files + if myslot == db[self.myroot]["vartree"].dbapi.aux_get(self.mycpv, ["SLOT"])[0]: + mypkglist.append(dblink(self.cat,v,destroot,self.settings)) print green("*")+" checking "+str(len(myfilelist))+" files for package collisions" for f in myfilelist: diff --git a/pym/portage_manifest.py b/pym/portage_manifest.py index 31b77ed1a..a9df1cc68 100644 --- a/pym/portage_manifest.py +++ b/pym/portage_manifest.py @@ -1,15 +1,16 @@ -import os, sets +import errno, os, sets import portage, portage_exception, portage_versions, portage_const from portage_checksum import * from portage_exception import * +from portage_util import write_atomic class FileNotInManifestException(PortageException): pass def manifest2AuxfileFilter(filename): filename = filename.strip(os.sep) - return not (filename in ["CVS", ".svn"] or filename.startswith("digest-") or filename.startswith(".svn")) + return not (filename in [".svn", "CVS"] or filename.startswith("CVS"+os.sep) or filename.startswith(".svn"+os.sep) or filename.startswith("digest-")) def manifest2MiscfileFilter(filename): filename = filename.strip(os.sep) @@ -83,6 +84,11 @@ class Manifest(object): mylines = fd.readlines() fd.close() mylines.extend(self._readDigests().split("\n")) + self._parseDigests(mylines, myhashdict=self.fhashdict) + + def _parseDigests(self, mylines, myhashdict=None): + if myhashdict is None: + myhashdict = {} for l in mylines: myname = "" mysplit = l.split() @@ -102,32 +108,71 @@ class Manifest(object): myhashes = dict(zip(mysplit[3::2], mysplit[4::2])) if len(myname) == 0: continue - if not self.fhashdict[mytype].has_key(myname): - self.fhashdict[mytype][myname] = {} - self.fhashdict[mytype][myname].update(myhashes) - self.fhashdict[mytype][myname]["size"] = mysize + myhashdict.setdefault(mytype, {}) + myhashdict[mytype].setdefault(myname, {}) + myhashdict[mytype][myname].update(myhashes) + myhashdict[mytype][myname]["size"] = mysize + return myhashdict - def _writeDigests(self): + def _writeDigests(self, force=False): """ Create old style digest files for this Manifest instance """ cpvlist = [os.path.join(self.pkgdir.rstrip(os.sep).split(os.sep)[-2], x[:-7]) for x in portage.listdir(self.pkgdir) if x.endswith(".ebuild")] rval = [] for cpv in cpvlist: dname = os.path.join(self.pkgdir, "files", "digest-"+portage.catsplit(cpv)[1]) - mylines = [] distlist = self._getCpvDistfiles(cpv) - for f in self.fhashdict["DIST"].keys(): - if f in distlist: - for h in self.fhashdict["DIST"][f].keys(): - if h not in portage_const.MANIFEST1_HASH_FUNCTIONS: - continue - myline = " ".join([h, str(self.fhashdict["DIST"][f][h]), f, str(self.fhashdict["DIST"][f]["size"])]) - mylines.append(myline) - fd = open(dname, "w") - fd.write("\n".join(mylines)) - fd.write("\n") - fd.close() + update_digest = True + if not force: + try: + f = open(dname, "r") + old_data = self._parseDigests(f.readlines()) + f.close() + if len(old_data) == 1 and "DIST" in old_data: + new_data = self._getDigestData(distlist) + for myfile in new_data["DIST"]: + for hashname in new_data["DIST"][myfile].keys(): + if hashname != "size" and \ + hashname not in portage_const.MANIFEST1_HASH_FUNCTIONS: + del new_data["DIST"][myfile][hashname] + if new_data["DIST"] == old_data["DIST"]: + update_digest = False + except (IOError, OSError), e: + if errno.ENOENT == e.errno: + pass + else: + raise + if update_digest: + write_atomic(dname, + "\n".join(self._createDigestLines1(distlist, self.fhashdict))+"\n") rval.append(dname) return rval + + def _getDigestData(self, distlist): + """create a hash dict for a specific list of files""" + myhashdict = {} + for myname in distlist: + for mytype in self.fhashdict: + if myname in self.fhashdict[mytype]: + myhashdict.setdefault(mytype, {}) + myhashdict[mytype].setdefault(myname, {}) + myhashdict[mytype][myname] = self.fhashdict[mytype][myname] + return myhashdict + + def _createDigestLines1(self, distlist, myhashdict): + """ Create an old style digest file.""" + mylines = [] + myfiles = myhashdict["DIST"].keys() + myfiles.sort() + for f in myfiles: + if f in distlist: + myhashkeys = myhashdict["DIST"][f].keys() + myhashkeys.sort() + for h in myhashkeys: + if h not in portage_const.MANIFEST1_HASH_FUNCTIONS: + continue + myline = " ".join([h, str(myhashdict["DIST"][f][h]), f, str(myhashdict["DIST"][f]["size"])]) + mylines.append(myline) + return mylines def _addDigestsToManifest(self, digests, fd): """ Add entries for old style digest files to Manifest file """ @@ -142,8 +187,12 @@ class Manifest(object): def _write(self, fd): """ Actual Manifest file generator """ mylines = [] - for t in self.fhashdict.keys(): - for f in self.fhashdict[t].keys(): + mytypes = self.fhashdict.keys() + mytypes.sort() + for t in mytypes: + myfiles = self.fhashdict[t].keys() + myfiles.sort() + for f in myfiles: # compat hack for v1 manifests if t == "AUX": f2 = os.path.join("files", f) @@ -151,13 +200,15 @@ class Manifest(object): f2 = f myline = " ".join([t, f, str(self.fhashdict[t][f]["size"])]) myhashes = self.fhashdict[t][f] - for h in myhashes.keys(): + myhashkeys = myhashes.keys() + myhashkeys.sort() + for h in myhashkeys: if h not in portage_const.MANIFEST2_HASH_FUNCTIONS: continue myline += " "+h+" "+str(myhashes[h]) mylines.append(myline) if self.compat and t != "DIST": - for h in myhashes.keys(): + for h in myhashkeys: if h not in portage_const.MANIFEST1_HASH_FUNCTIONS: continue mylines.append((" ".join([h, str(myhashes[h]), f2, str(myhashes["size"])])))