--- portage_contents.py.orig 2004-11-26 01:32:48.019058360 +0000 +++ portage_contents.py.orig 2004-11-26 01:32:28.029097296 +0000 @@ -1,11 +1,12 @@ # portage_contents.py -- (Persistent) Contents File Management # Copyright 1998-2004 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_contents.py,v 1.3 2004/10/04 14:07:40 vapier Exp $ +# $Header: $ -import os,string,types,sys,copy +import os,string,types,sys,copy,stat,re import portage_exception import portage_const +import portage_checksum #import gettext #gettext_t = gettext.translation('portage.contents', portage_const.LOCALE_DATA_PATH) @@ -16,7 +17,176 @@ FILES_KEY = "\0FILES\0" OWNER_KEY = "\0OWNER\0" +ATTRIBUTES_KEY = "\0ATTRIBUTES\0" +class ContentsManager: + """Manage a CONTENTS file.""" + def __init__(self,filename): + + self.contents = {} + + self.filename = filename + self.readFile(filename) + + def readFile(self,filename): + contents = self.contents + pkgfiles = {} + + try: + myc=open(filename,"r") + except OSError, details: + return (None, str(details)) + except IOError, details: + return (None, str(details)) + mylines=myc.readlines() + myc.close() + pos=1 + root="/" + for line in mylines: + mydat = string.split(line) + # we do this so we can remove from non-root filesystems + # (use the ROOT var to allow maintenance on other partitions) + try: + mydat[1]=os.path.normpath(root+mydat[1][1:]) + if mydat[0]=="obj": + #format: type, mtime, md5sum + pkgfiles[string.join(mydat[1:-2]," ")]={'type' : mydat[0], 'md5' : mydat[-2], 'mtime' : mydat[-1]} + elif mydat[0]=="dir": + #format: type + pkgfiles[string.join(mydat[1:])]={'type' : mydat[0] } + elif mydat[0]=="sym": + #format: type, mtime, dest + x=len(mydat)-1 + if (x >= 13) and (mydat[-1][-1]==')'): # Old/Broken symlink entry + mydat = mydat[:-10]+[mydat[-10:][stat.ST_MTIME][:-1]] + writemsg("FIXED SYMLINK LINE: %s\n" % mydat, 1) + x=len(mydat)-1 + splitter=-1 + while(x>=0): + if mydat[x]=="->": + splitter=x + break + x=x-1 + if splitter==-1: + return None + pkgfiles[string.join(mydat[1:splitter]," ")]={'type' : mydat[0], 'mtime' : mydat[-1], 'target' : string.join(mydat[(splitter+1):-1]," ")} + elif mydat[0]=="dev": + #format: type + pkgfiles[string.join(mydat[1:]," ")]={'type' : mydat[0]} + elif mydat[0]=="fif": + #format: type + pkgfiles[string.join(mydat[1:]," ")]={'type' : mydat[0]} + else: + return None + except (KeyError,IndexError): + print "portage: CONTENTS line",pos,"corrupt!" + pos += 1 + + files = pkgfiles.keys() + for file in files: + elements = re.sub("^/*", "", file).split("/") + subcontent = self.contents + for element in elements: + if not subcontent.has_key(element): + subcontent[element] = {} + subcontent = subcontent[element] + subcontent[ATTRIBUTES_KEY] = pkgfiles[file] + + def writeContents(self, subcontent, key, path, outfile): + + if key == ATTRIBUTES_KEY: + if subcontent['type'] in ["dir","dev","fif"]: + outfile.write("%s\t%s\n" % (subcontent['type'], path)) + elif subcontent['type'] == "obj": + outfile.write("%s\t%s\t%s\t%s\n" % (subcontent['type'], path, subcontent['md5'], subcontent['mtime'])) + elif subcontent['type'] == "sym": + outfile.write("%s\t%s\t->\t%s\t%s\n" % (subcontent['type'], path, subcontent['target'], subcontent['mtime'])) + else: + if key != "": + path = path+"/"+key + keys = subcontent.keys() + keys.sort() + for key in keys: + self.writeContents(subcontent[key], key, path, outfile) + + def writeFile(self,filename=""): + contents=self.contents + if filename == "": + filename = self.filename + + newfilename = filename+".new" + + mykeys=contents.keys() + mykeys.sort() + + outfile=open(newfilename,"w") + self.writeContents(contents, "", "", outfile) + outfile.close() + os.rename(newfilename, filename) + return + + def __getitem__(self, key): + if re.match("^/", key): + elements = re.sub("^/*", "", key).split("/") + subcontent = self.contents + for element in elements: + subcontent = subcontent[element] + return subcontent[ATTRIBUTES_KEY] + else: + return self.contents[key] + + def __setitem__(self, key, value): + if re.match("^/", key): + elements = re.sub("^/*", "", key).split("/") + subcontent = self.contents + for element in elements: + if not subcontent.has_key(element): + subcontent[element] = {} + subcontent = subcontent[element] + subcontent[ATTRIBUTES_KEY] = value + + def getMD5(self,filename): + contents = self.contents + return self.getAttribute(filename, 'md5') + + def getMtime(self,filename): + contents = self.contents + return self.getAttribute(filename, 'mtime') + + def getAttribute(self,filename, attribute): + elements = re.sub("^/*", "", filename).split("/") + subcontent = self.contents + for element in elements: + subcontent = subcontent[element] + return subcontent[ATTRIBUTES_KEY][attribute] + + def setAttribute(self,filename, attribute, value): + elements = re.sub("^/*", "", filename).split("/") + subcontent = self.contents + for element in elements: + subcontent = subcontent[element] + subcontent[ATTRIBUTES_KEY][attribute] = value + + def updateAllAttributes(self,filename): + self.setMD5(filename) + self.setMtime(filename) + + def setMD5(self,filename, newmd5=""): + contents = self.contents + if newmd5 == "": + newmd5=portage_checksum.perform_md5(filename, calc_prelink=1) + + self.setAttribute(filename, 'md5', newmd5) + + def setMtime(self, filename, newmtime=""): + contents = self.contents + if newmtime == "": + pathstat = os.lstat(filename) + newmtime = pathstat[stat.ST_MTIME] + + self.setAttribute(filename, 'mtime', str(newmtime)) + + def ContentsHandler(filename): infile = open(filename)