import os import errno from fnmatch import fnmatch from gzip import GzipFile from debian_bundle import deb822 from operator import itemgetter import difflib from DiffGzHandler import DiffGzHandler class Archive: def __init__(self, dir, suitefilter=None, pkgfilter=None): self.root = None self.distsdir = None self.pkgs = {} self.root = dir self.distsdir = os.sep.join([dir, "dists"]) for s in self.parsesuites(filter=suitefilter): print "suite: ",s self.addsuite(s) for c in self.parsecomponents(s): print "\tcomponent:",c self.addcomponent(s,c) for p in self.parsesourcepackages(s,c,filter=pkgfilter): print "\t\tpackage:",p self.addsourcepackage(s,c,p) def addsuite(self, suite): self.pkgs[suite] = {} def suites(self, filter=None): return sorted(self.pkgs.iterkeys()) def parsesuites(self, filter=None): slist = os.listdir(self.distsdir) if filter: slist = set(filter).intersection(set(slist)) for s in sorted(slist): yield s def addcomponent(self, suite, component): self.pkgs[suite][component] = {} def components(self, suite): return sorted(self.pkgs[suite].iterkeys()) def parsecomponents(self, suite): f = file(self.distsdir + os.sep + os.sep.join([suite, "Release"])) rel = deb822.Release(f) for comp in rel['Components'].split(' '): yield comp def addsourcepackage(self, suite, component, package): self.pkgs[suite][component][package.name] = package def sourcepackages(self, suite, component, filter=None, namesonly=False): if not namesonly: return sorted(self.pkgs[suite][component].itervalues()) else: namer = lambda x: x.name return sorted(map(namer, self.pkgs[suite][component].itervalues())) def parsesourcepackages(self, suite, component, filter=None): sfile=os.sep.join([self.distsdir,suite,component,"/source/Sources.gz"]) k = itemgetter('Package') fdict = {} if filter: for name in filter: fdict[name] = True for ent in sorted(deb822.Sources.iter_paragraphs(GzipFile(sfile)), key=k): if filter and not fdict.has_key(ent['Package']): continue else: yield SourcePackage(ent) def __str__(self): return "Archive rooted at "+self.root class ArchiveDiffer: def diffsuites(self,a,b): return difflib.ndiff(a.suites(), b.suites()) def diffcomponents(self,a,b, suite): return difflib.ndiff(a.components(suite), b.components(suite)) def diffsourcepackages(self,a,b, suite, component): return difflib.ndiff(a.sourcepackages(suite, component, namesonly=True), b.sourcepackages(suite, component, namesonly=True)) # XXX maybe there's a better place/way for this def getidx(letter): name = str(letter) if len(name) < 4 or name[0:3] != "lib": return name[0] else: return name[0:4] class SourcePackage: def __init__(self, info): self.diffgz_name = None self.diffgz_size = None self.diffgz_md5sum = None self.diffgz = None self.type = "Native" self.name = info['Package'] self.format = info['Format'] self.loc = info['Directory'] self.version = info['Version'] self.idx = getidx(self) for f in info['Files']: if fnmatch(f['name'], '*.diff.gz'): self.diffgz_name=f['name'] self.diffgz_size=f['size'] self.diffgz_md5sum=f['md5sum'] self.type = "Debian-diff" def __str__(self): return self.name class MasterIndex: def __init__(self): self.pkgcounts = {} def add(self, name): idx = getidx(name) if not self.pkgcounts.has_key(idx): self.pkgcounts[idx] = 1 else: self.pkgcounts[idx] += 1 def indices(self): for k,v in sorted(self.pkgcounts.iteritems()): yield (k,v) class SourcePackageIndex: def __init__(self): self.pkgs = {} def ins(self, srcpkg, rel): if not self.pkgs.has_key(srcpkg.idx): self.pkgs[srcpkg.idx] = {} if not self.pkgs[srcpkg.idx].has_key(srcpkg.name): self.pkgs[srcpkg.idx][srcpkg.name] = {} if not self.pkgs[srcpkg.idx][srcpkg.name].has_key(rel): self.pkgs[srcpkg.idx][srcpkg.name][rel] = srcpkg def getletter(self, letter): return self.pkgs[getidx(letter)] def indices(self): for k,v in sorted(self.pkgs.iteritems()): yield (k,v) # basic module tests if __name__ == "__main__": import Conf import sys import copy a = Archive(sys.argv[1], suitefilter=["etch"]) b = copy.deepcopy(a) b.addsuite("lenny") b.addcomponent("etch", "something") class x: def __init__(self,name): self.name=name b.addsourcepackage("etch","main",x("foo")) print "suite diff" print "\n".join( ArchiveDiffer().diffsuites(a,b) ) print "component diff" print "\n".join( ArchiveDiffer().diffcomponents(a,b,"etch") ) print "package diff" print "\n".join( ArchiveDiffer().diffsourcepackages(a,b,"etch","main") )