diff options
Diffstat (limited to 'patchtracker')
-rwxr-xr-x | patchtracker/Conf.py | 2 | ||||
-rw-r--r-- | patchtracker/DB.py | 171 | ||||
-rwxr-xr-x | patchtracker/SourceArchive.py | 65 | ||||
-rwxr-xr-x | patchtracker/Writers.py | 23 |
4 files changed, 186 insertions, 75 deletions
diff --git a/patchtracker/Conf.py b/patchtracker/Conf.py index bc095b2..c4ec803 100755 --- a/patchtracker/Conf.py +++ b/patchtracker/Conf.py @@ -5,3 +5,5 @@ template_dir = './templates' static_dir = './static' #root_url = 'http://people.debian.org/~seanius/pts/patches' root_url = '/patches' +database = 'pt.db' +sqlschema = 'db.sql' diff --git a/patchtracker/DB.py b/patchtracker/DB.py index 2f1b208..d74744d 100644 --- a/patchtracker/DB.py +++ b/patchtracker/DB.py @@ -1,68 +1,171 @@ from pysqlite2 import dbapi2 as sqlite -import Conf as Conf +import Conf import os import errno -import time +import patchtracker.SourceArchive as SourceArchive -class PatchTrackerDB: - db = None - now = None - cursor = None +def srcpkg_factory(cursor, row): + d = {} + for idx, col in enumerate(cursor.description): + d[col[0]] = row[idx] + + info = {} + info['Files'] = [] + if d['diffgz_name']: + diffgz = {'name':d['diffgz_name'], 'size':d['diffgz_size'], + 'md5sum':d['diffgz_md5sum'] } + info['Files'].append(diffgz) + + colmap = {'name':'Package','version':'Version','format':'Format', + 'loc':'Directory'} + + for col,field in colmap.iteritems(): + info[field] = d[col] + return SourceArchive.SourcePackage(info) + +class PatchTrackerDB: def __init__(self, dbname=Conf.database): - self.now = int(time.time()) self.db = sqlite.connect(dbname) - self.cursor = self.db.cursor() - self.cursor.execute("SELECT * FROM sqlite_master WHERE name='packages'") - if not self.cursor.fetchone(): + cursor = self.db.cursor() + cursor.execute("SELECT * FROM sqlite_master WHERE name='packages'") + if not cursor.fetchone(): print "repopulating empty database..." + nextcmd = "" for l in file(Conf.sqlschema).readlines(): - self.cursor.execute(l) + if len(l.strip()): + nextcmd += " " + l.strip() + else: + print "exec: %s"%(nextcmd) + cursor.execute(nextcmd) + nextcmd = "" + + def setFactory(self, factory): + self.db.row_factory = factory def findSourcePackage(self, srcpkg): - q = "SELECT * FROM packages WHERE package = ? AND version = ?" - self.cursor.execute(q, (srcpkg.name, srcpkg.version)) - s = self.cursor.fetchone() + q = "SELECT * FROM packages WHERE name=? AND version=?" + cursor = self.db.cursor() + cursor.execute(q, (srcpkg.name, srcpkg.version)) + s = cursor.fetchone() return s def saveSourcePackage(self, srcpkg): + cursor = self.db.cursor() s = self.findSourcePackage(srcpkg) + + queryargs = (srcpkg.name,srcpkg.format,srcpkg.loc, + srcpkg.version,srcpkg.diffgz_name,srcpkg.diffgz_size, + srcpkg.diffgz_md5sum) if not s: - print "creating new record for",srcpkg - q = "INSERT INTO packages (package,format,diffgz,loc,type,version,updated) VALUES (?,?,?,?,?,?,?)" + #print "creating new record for",srcpkg + q = "INSERT INTO packages (id,name,format,loc,version,\ + diffgz_name,diffgz_size,diffgz_md5sum)\ + VALUES ((SELECT MAX(id)+1 FROM packages),?,?,?,?,?,?,?)" else: - print "updating record for",srcpkg - q = "UPDATE packages SET package=?,format=?,diffgz=?,loc=?,type=?,version=?,updated=?" - self.cursor.execute(q, (srcpkg.name,srcpkg.format,srcpkg.diffgz,srcpkg.loc,srcpkg.type,srcpkg.version,self.now)) + #print "updating record for",srcpkg + q = "UPDATE packages SET name=?,format=?,loc=?,version=?,\ + diffgz_name=?,diffgz_size=?,diffgz_md5sum=?\ + WHERE name=? AND version=?" + queryargs += (srcpkg.name, srcpkg.version) + cursor.execute(q, queryargs) - def findRelease(self, release) - raise Exception("not yet implemented") + def findSuite(self, suite): + q = "SELECT * FROM suites WHERE name = ?" + cursor = self.db.cursor() + cursor.execute(q, (suite,)) + return cursor.fetchone() - def saveRelease(self, release) - raise Exception("not yet implemented") + def saveSuite(self, suite): + s = self.findSuite(suite) + if not s: + q = "INSERT INTO suites (id,name) \ + VALUES ((SELECT MAX(id)+1 FROM suites),?)" + cursor = self.db.cursor() + cursor.execute(q, (suite,)) - def findComponent(self, release, component): - raise Exception("not yet implemented") + def findComponent(self, component): + q = "SELECT * FROM components WHERE name = ?" + cursor = self.db.cursor() + cursor.execute(q, (component,)) + return cursor.fetchone() def saveComponent(self, component): - raise Exception("not yet implemented") - - def relateComponentToSourcePackage(self, component, srcpkg): - raise Exception("not yet implemented") + c = self.findComponent(component) + if not c: + q = "INSERT INTO components (id,name) \ + VALUES ((SELECT MAX(id)+1 FROM components),?)" + cursor = self.db.cursor() + cursor.execute(q, (component,)) + + def findLetterToc(self, letter): + oldfactory = self.db.row_factory + dcursor = self.db.cursor() + dq = "SELECT id,name FROM suites" + dcursor.execute(dq) + suites = {} + for id,suite in dcursor.fetchall(): + suites[id] = suite + + self.db.row_factory = srcpkg_factory + cursor = self.db.cursor() + toc = SourceArchive.SourcePackageIndex() + for s,v in suites.iteritems(): + q = "SELECT * FROM packages AS p,package_rel_map AS m \ + WHERE p.name like ? AND p.id = m.package_id and m.suite_id = ?" + cursor.execute(q, (letter+"%", s)) + # use srcpkg_factory to fetch sourcepackages, once per suite + for srcpkg in cursor.fetchall(): + toc.ins(srcpkg, v) + self.db.row_factory = oldfactory + return toc.getletter(letter) + + def findMasterIndex(self): + cursor = self.db.cursor() + toc = SourceArchive.MasterIndex() + q = "SELECT name FROM packages WHERE id > 0" + cursor.execute(q) + for name in cursor.fetchall(): + # XXX find a better way to do this..., probably just store metainfo + # XXX in the db and update it via triggers + toc.add(name[0]) + return toc + + def findSourcePackageRelation(self, srcpkg, suite): + q = "SELECT * FROM packages AS p,suites AS s,package_rel_map AS m \ + WHERE p.name=? AND s.name=? AND m.package_id=p.id \ + AND m.suite_id=s.id" + cursor = self.db.cursor() + cursor.execute(q, (srcpkg.name, suite)) + return cursor.fetchone() + + def relateSourcePackage(self, srcpkg, suite, component): + s = self.findSourcePackageRelation(srcpkg, suite) + if not s: + s = self.findSourcePackage(srcpkg) + q = "INSERT INTO package_rel_map (package_id,suite_id,component_id) \ + VALUES (?, \ + (SELECT id FROM suites WHERE name=?), \ + (SELECT id FROM components WHERE name=?))" + else: + q = "UPDATE package_rel_map SET package_id=? \ + WHERE suite_id=(SELECT id FROM suites WHERE name=?) \ + AND component_id=(SELECT id FROM components WHERE name=?)" + cursor = self.db.cursor() + cursor.execute(q, (s[0], suite, component)) def finalize(self): - # remove cruft in a rather lazy way - self.cursor.execute("DELETE FROM packages WHERE updated < ?", (self.now,)) self.db.commit() + + def __del__(self): + self.finalize() if __name__ == "__main__": print "patch tracker db testing" d = PatchTrackerDB(dbname="foo.db") - from SourceArchive import SourcePackage - sp = SourcePackage({'Package':'foo','Format':'blah','Directory':'/foo','Version':'1.2.3.4','Files':[]}) + sp = SourceArchive.SourcePackage({'Package':'foo','Format':'blah','Directory':'/foo','Version':'1.2.3.4','Files':[]}) d.saveSourcePackage(sp) d.finalize() - diff --git a/patchtracker/SourceArchive.py b/patchtracker/SourceArchive.py index 1f12001..a0aab1b 100755 --- a/patchtracker/SourceArchive.py +++ b/patchtracker/SourceArchive.py @@ -45,49 +45,66 @@ class Archive: def __str__(self): return "Archive rooted at "+self.root -class SourcePackage: - name = None - format = None - diffgz = None - loc = None - type = "Native" - version = None - # todo - vcs = {} +# 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=f + self.diffgz_name=f['name'] + self.diffgz_size=f['size'] + self.diffgz_md5sum=f['md5sum'] self.type = "Debian-diff" - def idx(self): - name = str(self) - if len(name) < 4 or name[0:3] != "lib": - return name[0] - else: - return name[0:4] - 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): - idx = srcpkg.idx() - if not self.pkgs.has_key(idx): - self.pkgs[idx] = {} - if not self.pkgs[idx].has_key(srcpkg.name): - self.pkgs[idx][srcpkg.name] = {} - if not self.pkgs[idx][srcpkg.name].has_key(rel): - self.pkgs[idx][srcpkg.name][rel] = srcpkg + 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()): diff --git a/patchtracker/Writers.py b/patchtracker/Writers.py index 7e2fd1c..c3b59aa 100755 --- a/patchtracker/Writers.py +++ b/patchtracker/Writers.py @@ -23,8 +23,8 @@ class PackageVersTemplate(OurTemplate): self.suite = suite tpl=os.sep.join([Conf.template_dir, "package_vers.tmpl"]) sl = {} - if srcpkg.diffgz: - dfile = os.sep.join([Conf.archive_root,srcpkg.loc,srcpkg.diffgz['name']]) + if srcpkg.diffgz_name: + dfile = os.sep.join([Conf.archive_root,srcpkg.loc,srcpkg.diffgz_name]) sl['diffhandler'] = DiffGzHandler(dfile) else: sl['diffhandler'] = None @@ -34,20 +34,12 @@ class FrontPageTemplate(OurTemplate): allindex = None relindices = [] - def __init__(self, allindex, release_indices=[]): + def __init__(self, allindex): tpl = os.sep.join([Conf.template_dir, "frontpage.tmpl"]) OurTemplate.__init__(self, file=tpl) self.allindex = allindex - self.relindices = release_indices class LetterTocTemplate(OurTemplate): - idx = None - pkgs = None - dists = None - - def releases(self): - return dists - def __init__(self, letter, collection): self.pkgs = collection self.idx = letter @@ -58,6 +50,9 @@ class LetterTocTemplate(OurTemplate): tpl = os.sep.join([Conf.template_dir, "letter_toc.tmpl"]) OurTemplate.__init__(self, file=tpl) + def releases(self): + return dists + class ErrorTemplate(OurTemplate): def __init__(self, msg): tpl = os.sep.join([Conf.template_dir, "cgi_error.tmpl"]) @@ -97,9 +92,3 @@ class FrontPageWriter(PageWriter): t = FrontPageTemplate(allindex, release_indices) dest = os.sep.join([Conf.output_dir, "index.html"]) PageWriter.__init__(self, dest, t) - -class LetterTocWriter(PageWriter): - def __init__(self, letter, collection): - t = LetterTocTemplate(letter, collection) - dest = os.sep.join([Conf.output_dir, "index", t.idx, "index.html"]) - PageWriter.__init__(self, dest, t) |