| # cvstree.py -- cvs tree utilities |
| # Copyright 1998-2004 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| # $Id$ |
| |
| |
| import os,time,sys,re |
| from stat import * |
| |
| # [D]/Name/Version/Date/Flags/Tags |
| |
| def pathdata(entries, path): |
| """(entries,path) |
| Returns the data(dict) for a specific file/dir at the path specified.""" |
| mysplit=path.split("/") |
| myentries=entries |
| mytarget=mysplit[-1] |
| mysplit=mysplit[:-1] |
| for mys in mysplit: |
| if mys in myentries["dirs"]: |
| myentries=myentries["dirs"][mys] |
| else: |
| return None |
| if mytarget in myentries["dirs"]: |
| return myentries["dirs"][mytarget] |
| elif mytarget in myentries["files"]: |
| return myentries["files"][mytarget] |
| else: |
| return None |
| |
| def fileat(entries, path): |
| return pathdata(entries,path) |
| |
| def isadded(entries, path): |
| """(entries,path) |
| Returns true if the path exists and is added to the cvs tree.""" |
| mytarget=pathdata(entries, path) |
| if mytarget: |
| if "cvs" in mytarget["status"]: |
| return 1 |
| |
| basedir=os.path.dirname(path) |
| filename=os.path.basename(path) |
| |
| try: |
| myfile=open(basedir+"/CVS/Entries","r") |
| except IOError: |
| return 0 |
| mylines=myfile.readlines() |
| myfile.close() |
| |
| rep=re.compile("^\/"+re.escape(filename)+"\/"); |
| for x in mylines: |
| if rep.search(x): |
| return 1 |
| |
| return 0 |
| |
| def findnew(entries,recursive=0,basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all elements that have been added but |
| have not yet been committed. Returns a list of paths, optionally prepended |
| with a basedir.""" |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mylist=[] |
| for myfile in entries["files"]: |
| if "cvs" in entries["files"][myfile]["status"]: |
| if "0" == entries["files"][myfile]["revision"]: |
| mylist.append(basedir+myfile) |
| if recursive: |
| for mydir in entries["dirs"]: |
| mylist+=findnew(entries["dirs"][mydir],recursive,basedir+mydir) |
| return mylist |
| |
| def findoption(entries, pattern, recursive=0, basedir=""): |
| """(entries, pattern, recursive=0, basedir="") |
| Iterate over paths of cvs entries for which the pattern.search() method |
| finds a match. Returns a list of paths, optionally prepended with a |
| basedir.""" |
| if not basedir.endswith("/"): |
| basedir += "/" |
| for myfile, mydata in entries["files"].iteritems(): |
| if "cvs" in mydata["status"]: |
| if pattern.search(mydata["flags"]): |
| yield basedir+myfile |
| if recursive: |
| for mydir, mydata in entries["dirs"].iteritems(): |
| for x in findoption(mydata, pattern, |
| recursive, basedir+mydir): |
| yield x |
| |
| def findchanged(entries,recursive=0,basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all elements that exist in the cvs tree |
| and differ from the committed version. Returns a list of paths, optionally |
| prepended with a basedir.""" |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mylist=[] |
| for myfile in entries["files"]: |
| if "cvs" in entries["files"][myfile]["status"]: |
| if "current" not in entries["files"][myfile]["status"]: |
| if "exists" in entries["files"][myfile]["status"]: |
| if entries["files"][myfile]["revision"]!="0": |
| mylist.append(basedir+myfile) |
| if recursive: |
| for mydir in entries["dirs"]: |
| mylist+=findchanged(entries["dirs"][mydir],recursive,basedir+mydir) |
| return mylist |
| |
| def findmissing(entries,recursive=0,basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all elements that are listed in the cvs |
| tree but do not exist on the filesystem. Returns a list of paths, |
| optionally prepended with a basedir.""" |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mylist=[] |
| for myfile in entries["files"]: |
| if "cvs" in entries["files"][myfile]["status"]: |
| if "exists" not in entries["files"][myfile]["status"]: |
| if "removed" not in entries["files"][myfile]["status"]: |
| mylist.append(basedir+myfile) |
| if recursive: |
| for mydir in entries["dirs"]: |
| mylist+=findmissing(entries["dirs"][mydir],recursive,basedir+mydir) |
| return mylist |
| |
| def findunadded(entries,recursive=0,basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all elements that are in valid cvs |
| directories but are not part of the cvs tree. Returns a list of paths, |
| optionally prepended with a basedir.""" |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mylist=[] |
| |
| #ignore what cvs ignores. |
| for myfile in entries["files"]: |
| if "cvs" not in entries["files"][myfile]["status"]: |
| mylist.append(basedir+myfile) |
| if recursive: |
| for mydir in entries["dirs"]: |
| mylist+=findunadded(entries["dirs"][mydir],recursive,basedir+mydir) |
| return mylist |
| |
| def findremoved(entries,recursive=0,basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all elements that are in flagged for cvs |
| deletions. Returns a list of paths, optionally prepended with a basedir.""" |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mylist=[] |
| for myfile in entries["files"]: |
| if "removed" in entries["files"][myfile]["status"]: |
| mylist.append(basedir+myfile) |
| if recursive: |
| for mydir in entries["dirs"]: |
| mylist+=findremoved(entries["dirs"][mydir],recursive,basedir+mydir) |
| return mylist |
| |
| def findall(entries, recursive=0, basedir=""): |
| """(entries,recursive=0,basedir="") |
| Recurses the entries tree to find all new, changed, missing, and unadded |
| entities. Returns a 4 element list of lists as returned from each find*().""" |
| |
| if basedir and basedir[-1]!="/": |
| basedir=basedir+"/" |
| mynew = findnew(entries,recursive,basedir) |
| mychanged = findchanged(entries,recursive,basedir) |
| mymissing = findmissing(entries,recursive,basedir) |
| myunadded = findunadded(entries,recursive,basedir) |
| myremoved = findremoved(entries,recursive,basedir) |
| return [mynew, mychanged, mymissing, myunadded, myremoved] |
| |
| ignore_list = re.compile("(^|/)(RCS(|LOG)|SCCS|CVS(|\.adm)|cvslog\..*|tags|TAGS|\.(make\.state|nse_depinfo)|.*~|(\.|)#.*|,.*|_$.*|.*\$|\.del-.*|.*\.(old|BAK|bak|orig|rej|a|olb|o|obj|so|exe|Z|elc|ln)|core)$") |
| def apply_cvsignore_filter(list): |
| x=0 |
| while x < len(list): |
| if ignore_list.match(list[x].split("/")[-1]): |
| list.pop(x) |
| else: |
| x+=1 |
| return list |
| |
| def getentries(mydir,recursive=0): |
| """(basedir,recursive=0) |
| Scans the given directory and returns an datadict of all the entries in |
| the directory seperated as a dirs dict and a files dict.""" |
| myfn=mydir+"/CVS/Entries" |
| # entries=[dirs, files] |
| entries={"dirs":{},"files":{}} |
| if not os.path.exists(mydir): |
| return entries |
| try: |
| myfile=open(myfn, "r") |
| mylines=myfile.readlines() |
| myfile.close() |
| except SystemExit, e: |
| raise |
| except: |
| mylines=[] |
| for line in mylines: |
| if line and line[-1]=="\n": |
| line=line[:-1] |
| if not line: |
| continue |
| if line=="D": # End of entries file |
| break |
| mysplit=line.split("/") |
| if len(mysplit)!=6: |
| print "Confused:",mysplit |
| continue |
| if mysplit[0]=="D": |
| entries["dirs"][mysplit[1]]={"dirs":{},"files":{},"status":[]} |
| entries["dirs"][mysplit[1]]["status"]=["cvs"] |
| if os.path.isdir(mydir+"/"+mysplit[1]): |
| entries["dirs"][mysplit[1]]["status"]+=["exists"] |
| entries["dirs"][mysplit[1]]["flags"]=mysplit[2:] |
| if recursive: |
| rentries=getentries(mydir+"/"+mysplit[1],recursive) |
| #print rentries.keys() |
| #print entries["files"].keys() |
| #print entries["files"][mysplit[1]] |
| entries["dirs"][mysplit[1]]["dirs"]=rentries["dirs"] |
| entries["dirs"][mysplit[1]]["files"]=rentries["files"] |
| else: |
| # [D]/Name/revision/Date/Flags/Tags |
| entries["files"][mysplit[1]]={} |
| entries["files"][mysplit[1]]["revision"]=mysplit[2] |
| entries["files"][mysplit[1]]["date"]=mysplit[3] |
| entries["files"][mysplit[1]]["flags"]=mysplit[4] |
| entries["files"][mysplit[1]]["tags"]=mysplit[5] |
| entries["files"][mysplit[1]]["status"]=["cvs"] |
| if entries["files"][mysplit[1]]["revision"][0]=="-": |
| entries["files"][mysplit[1]]["status"]+=["removed"] |
| |
| for file in apply_cvsignore_filter(os.listdir(mydir)): |
| if file=="CVS": |
| continue |
| if file=="digest-framerd-2.4.3": |
| print mydir,file |
| if os.path.isdir(mydir+"/"+file): |
| if file not in entries["dirs"]: |
| entries["dirs"][file]={"dirs":{},"files":{}} |
| if "status" in entries["dirs"][file]: |
| if "exists" not in entries["dirs"][file]["status"]: |
| entries["dirs"][file]["status"]+=["exists"] |
| else: |
| entries["dirs"][file]["status"]=["exists"] |
| elif os.path.isfile(mydir+"/"+file): |
| if file=="digest-framerd-2.4.3": |
| print "isfile" |
| if file not in entries["files"]: |
| entries["files"][file]={"revision":"","date":"","flags":"","tags":""} |
| if "status" in entries["files"][file]: |
| if file=="digest-framerd-2.4.3": |
| print "has status" |
| if "exists" not in entries["files"][file]["status"]: |
| if file=="digest-framerd-2.4.3": |
| print "no exists in status" |
| entries["files"][file]["status"]+=["exists"] |
| else: |
| if file=="digest-framerd-2.4.3": |
| print "no status" |
| entries["files"][file]["status"]=["exists"] |
| try: |
| if file=="digest-framerd-2.4.3": |
| print "stat'ing" |
| mystat=os.stat(mydir+"/"+file) |
| mytime=time.asctime(time.gmtime(mystat[ST_MTIME])) |
| if "status" not in entries["files"][file]: |
| if file=="digest-framerd-2.4.3": |
| print "status not set" |
| entries["files"][file]["status"]=[] |
| if file=="digest-framerd-2.4.3": |
| print "date:",entries["files"][file]["date"] |
| print "sdate:",mytime |
| if mytime==entries["files"][file]["date"]: |
| entries["files"][file]["status"]+=["current"] |
| if file=="digest-framerd-2.4.3": |
| print "stat done" |
| |
| del mystat |
| except SystemExit, e: |
| raise |
| except Exception, e: |
| print "failed to stat",file |
| print e |
| return |
| |
| else: |
| print |
| print "File of unknown type:",mydir+"/"+file |
| print |
| return entries |
| |
| #class cvstree: |
| # def __init__(self,basedir): |
| # self.refdir=os.cwd() |
| # self.basedir=basedir |
| # self.entries={} |
| # self.entries["dirs"]={} |
| # self.entries["files"]={} |
| # self.entries["dirs"][self.basedir]=getentries(self.basedir) |
| # self.getrealdirs(self.dirs, self.files) |
| # def getrealdirs(self,dirs,files): |
| # for mydir in dirs.keys(): |
| # list = os.listdir( |
| |
| |