summaryrefslogtreecommitdiff
path: root/patchtracker
diff options
context:
space:
mode:
Diffstat (limited to 'patchtracker')
-rwxr-xr-xpatchtracker/Conf.py2
-rw-r--r--patchtracker/DB.py171
-rwxr-xr-xpatchtracker/SourceArchive.py65
-rwxr-xr-xpatchtracker/Writers.py23
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)