diff options
-rw-r--r-- | TODO | 28 | ||||
-rw-r--r-- | db.sql | 132 | ||||
-rwxr-xr-x | gen-patch-info.py | 24 | ||||
-rwxr-xr-x | pagehandler.py | 45 | ||||
-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 | ||||
-rw-r--r-- | templates/frontpage.tmpl | 12 | ||||
-rw-r--r-- | templates/letter_toc.tmpl | 2 | ||||
-rwxr-xr-x | templates/package_vers.tmpl | 20 |
11 files changed, 402 insertions, 122 deletions
@@ -2,16 +2,10 @@ welcome to the TODO file. == short-range TODO == -fix the patch display/markup +remove hardcoded url parsing - given the disk space requirements, the patches are not automatically - generated any longer. an as-of-yet unwritten cgi script will handle - such requests. - -don't nuke/reinit the whole patch tracking tree - - this also implies that some kind of garbage collection takes place - to remove versions that are no longer being tracked + pagehandler currently assumes installation under a certain subdir, + which isn't at all necessary. better handling of more exotic patch systems @@ -22,8 +16,19 @@ better handling of more exotic patch systems code cleanup from really ugly stuff (look for XXX) +dead code removal/cleanup + + after switching a few design decisions, there's some code that's no longer + used or should be renamed/moved (i.e. writers/templates) + == medium-range TODO == +review db design + + the db schema design is most likely less than optimal, the use of triggers + to emulate foreign keys is novel but likely we can remove a few columns and + use rowids instead, and possibly lower/optimise the remaining queries. + remove all the os.system calls lots of temporary ducttape via os.system that should go away @@ -35,8 +40,9 @@ make prettier pages decide how much should be cgi-based and how much should be written - there's no reason why the other pages couldn't also be generated from - a cgi, if we desired. + there's no reason why the entire system can't be generated via cgi-based + accessing, but the question is whether it should be, or whether certain + componenets should remain static. == long-range TODO == @@ -1,4 +1,128 @@ -create table packages ( id int, package varchar(256), format varchar(32), diffgz varchar(1024), loc varchar(1024), type varchar(32), version varchar(256), updated int ); -create table releases ( id int, name varchar(32), md5sum varchar(32), updated int ); -create table components ( id int, name varchar(32), updated int ); -create table pkg_rel ( rel_id int, comp_id int, pkg_id int ); +CREATE TABLE packages ( + id int UNIQUE NOT NULL, + name text NOT NULL, + version text NOT NULL, + format text NOT NULL, + loc text NOT NULL, + diffgz_name text DEFAULT NULL, + diffgz_size int DEFAULT NULL, + diffgz_md5sum varchar(32) DEFAULT NULL +); + +CREATE TABLE suites ( + id int UNIQUE NOT NULL, + name text UNIQUE NOT NULL PRIMARY KEY +); + +CREATE TABLE components ( + id int UNIQUE NOT NULL, + name text PRIMARY KEY +); + +CREATE TABLE package_rel_map ( + package_id int NOT NULL + CONSTRAINT fk_package_id REFERENCES packages(id), + suite_id int NOT NULL + CONSTRAINT fk_suite_id REFERENCES suites(id) ON DELETE CASCADE, + component_id int NOT NULL + CONSTRAINT fk_component_id REFERENCES components(id) +); + +-- sqlite doesn't actually implement FK constraints, therefore we +-- help out a little and do it ourselves via triggers + +-- before insert on the package relation mapping, catch invalid references + +CREATE TRIGGER fki_package_rel_map_suite_id_suites_id + BEFORE INSERT ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'INSERT on "package_rel_map" violates FK constraint on "suites.id"') + WHERE (SELECT id FROM suites WHERE id = NEW.suite_id) IS NULL; + END; + +CREATE TRIGGER fki_package_rel_map_package_id_packages_id + BEFORE INSERT ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'INSERT on "package_rel_map" violates FK constraint on "packages.id"') + WHERE (SELECT id FROM packages WHERE id = NEW.package_id) IS NULL; + END; + +CREATE TRIGGER fki_package_rel_map_component_id_components_id + BEFORE INSERT ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'INSERT on "package_rel_map" violates FK constraint on "components.id"') + WHERE (SELECT id FROM components WHERE id =NEW.component_id) IS NULL; + END; + +-- the same but for updates + +CREATE TRIGGER fku_package_rel_map_suite_id_suites_id + BEFORE UPDATE ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'update on "package_rel_map" violates FK constraint on "suites.id"') + WHERE (SELECT id FROM suites WHERE id = NEW.suite_id) IS NULL; + END; + +CREATE TRIGGER fku_package_rel_map_package_id_packages_id + BEFORE UPDATE ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'update on "package_rel_map" violates FK constraint on "packages.id"') + WHERE (SELECT id FROM packages WHERE id = NEW.package_id) IS NULL; + END; + +CREATE TRIGGER fku_package_rel_map_component_id_components_id + BEFORE UPDATE ON [package_rel_map] + FOR EACH ROW BEGIN + SELECT RAISE(ROLLBACK, 'update on "package_rel_map" violates FK constraint on "components.id"') + WHERE (SELECT id FROM components WHERE id=NEW.component_id) IS NULL; + END; + +-- when a package/component/suite id is deleted, clean up any references +-- that would otherwise be orphaned + +CREATE TRIGGER fkdc_package_rel_map_suite_id_suites_id + BEFORE DELETE ON suites + FOR EACH ROW BEGIN + DELETE FROM package_rel_map WHERE package_rel_map.suite_id = OLD.id; + END; + +CREATE TRIGGER fkdc_package_rel_map_component_id_components_id + BEFORE DELETE ON components + FOR EACH ROW BEGIN + DELETE FROM package_rel_map WHERE package_rel_map.component_id = OLD.id; + END; + +CREATE TRIGGER fkdc_package_rel_map_package_id_packages_id + BEFORE DELETE ON packages + FOR EACH ROW BEGIN + DELETE FROM package_rel_map WHERE package_rel_map.package_id = OLD.id; + END; + +-- when a package relation mapping is deleted or updated, delete the package +-- record for the old relation if no other references to that package exist + +CREATE TRIGGER fkdc_packages_id_package_rel_map_package_id + BEFORE DELETE ON package_rel_map + FOR EACH ROW BEGIN + DELETE FROM packages WHERE packages.id = OLD.package_id + AND (SELECT package_id FROM package_rel_map + WHERE package_id = OLD.package_id AND rowid != OLD.rowid) + IS NULL; + END; + +CREATE TRIGGER fku_package_rel_map_prune_packages_package_id + BEFORE UPDATE ON [package_rel_map] + FOR EACH ROW BEGIN + DELETE FROM packages WHERE packages.id = OLD.package_id + AND (OLD.package_id != NEW.package_id) + AND (SELECT package_id FROM package_rel_map + WHERE package_id = OLD.package_id AND rowid != OLD.rowid) + IS NULL; + END; + +INSERT INTO packages VALUES (0,'','','','',NULL,NULL,NULL); + +INSERT INTO suites VALUES (0,''); + +INSERT INTO components VALUES (0,''); + diff --git a/gen-patch-info.py b/gen-patch-info.py index 618179a..afe6b3e 100755 --- a/gen-patch-info.py +++ b/gen-patch-info.py @@ -3,12 +3,14 @@ import os import sys import getopt +import errno import patchtracker.Conf as Conf -from patchtracker.Writers import LetterTocWriter, FrontPageWriter, PackageVersWriter -from patchtracker.SourceArchive import Archive, SourcePackage, SourcePackageIndex +from patchtracker.SourceArchive import Archive, SourcePackage +from patchtracker.DB import PatchTrackerDB if __name__ == '__main__': + db = PatchTrackerDB() os.system("cheetah compile templates/skeleton") opts,args = getopt.getopt(sys.argv[1:], "s:p:") suites = None @@ -22,20 +24,24 @@ if __name__ == '__main__': a = Archive(Conf.archive_root) # just for now until development stablizes #os.system("rm -rf "+Conf.output_dir) - #os.mkdir(Conf.output_dir) + try: + os.mkdir(Conf.output_dir) + except OSError, e: + if e.errno != errno.EEXIST: + raise e print a - master_index = SourcePackageIndex() for s in a.suites(filter=suites): print "suite: ",s + db.saveSuite(s) for c in a.components(s): print "\tcomponent:",c + db.saveComponent(c) for p in a.sourcepackages(s, c, filter=packages): print "\t\tpackage:",p - PackageVersWriter(p, s) - master_index.ins(p,s) + db.saveSourcePackage(p) + db.relateSourcePackage(p,suite=s,component=c) os.system("cp -a "+Conf.static_dir+"/* "+Conf.output_dir) - FrontPageWriter(master_index) - for letter,stuff in master_index.indices(): - LetterTocWriter(letter,stuff) + + db.finalize() diff --git a/pagehandler.py b/pagehandler.py index 858534b..9fc6d9c 100755 --- a/pagehandler.py +++ b/pagehandler.py @@ -5,17 +5,21 @@ import cgi import os import sys import patchtracker.Conf as Conf -from patchtracker.Writers import ErrorTemplate, PatchTemplate +from patchtracker.Writers import ErrorTemplate, PatchTemplate, PackageVersTemplate, LetterTocTemplate, FrontPageTemplate from patchtracker.DiffGzHandler import DiffGzHandler +import patchtracker.DB as DB +from patchtracker.DB import PatchTrackerDB import pygments from pygments.lexers import DiffLexer from pygments.formatters import HtmlFormatter class CmdHandler: def __init__(self, req_uri): + self.db = PatchTrackerDB() args = req_uri.split("/") + self.cmd = args[2] # XXX this assumes http://site/foo/patch/adsfadf - if args[2] == "patch": + if self.cmd == "patch": patchtype,mode,pkgname,version = args[3:7] self.parsemode(mode) dh = self.make_diffhandler(pkgname,version) @@ -32,8 +36,21 @@ class CmdHandler: self.error("unhandled patch type '%s'"%(patchtype)) self.pkgname = pkgname self.version = version + elif self.cmd == "package": + self.db.setFactory(DB.srcpkg_factory) + self.name = args[3] + self.version = args[4] + self.srcpkg = self.db.findSourcePackage(self) + elif self.cmd == "index": + if len(args) < 4 or not len(args[3]): + self.error("please provide a letter on which to index") + else: + self.letter = args[3] + self.toc = self.db.findLetterToc(self.letter) else: - self.error("unhandled command: '%s'"%(args[2])) + # XXX better way to set up "frontpage" + self.index = self.db.findMasterIndex() + self.cmd = "frontpage" # XXX this assumes to much hard coded, but until there's a faster # XXX (i.e. database) way to query sourcepackage/diffs it will @@ -67,13 +84,25 @@ class CmdHandler: sys.exit(1) def output(self): - if self.mode == "dl": - print "Content-Type: text/x-diff\n\n" - print self.content - else: + if self.cmd == "patch": + if self.mode == "dl": + print "Content-Type: text/x-diff\n\n" + print self.content + else: + print "Content-Type: text/html\n\n" + print PatchTemplate(pkg=self.pkgname,vers=self.version,patch=self.content,name=self.patchname) + elif self.cmd == "package": + print "Content-Type: text/html\n\n" + print PackageVersTemplate(self.srcpkg,"XXX FIXME") + elif self.cmd == "index": + print "Content-Type: text/html\n\n" + print LetterTocTemplate(self.letter, self.toc) + elif self.cmd == "frontpage": print "Content-Type: text/html\n\n" - print PatchTemplate(pkg=self.pkgname,vers=self.version,patch=self.content,name=self.patchname) + print FrontPageTemplate(self.index) if __name__ == "__main__": uri = os.getenv("REQUEST_URI") + if not uri: + uri = sys.argv[1] CmdHandler(uri).output() 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) diff --git a/templates/frontpage.tmpl b/templates/frontpage.tmpl index e283f98..5cb7fcc 100644 --- a/templates/frontpage.tmpl +++ b/templates/frontpage.tmpl @@ -6,9 +6,13 @@ Debian Project patch tracking system #def body <h1>Debian Project patch tracking system</h1> <h2>Browse patches by package name</h2> -#for $k in $allindex.pkgs.iterkeys() - #if $allindex.pkgs[$k] - <a href="index/$k">$k</a> - #end if + <table class="patchlisting"> + <tr><th>index</th><th># packages</th></tr> +#for $k,$v in $allindex.indices + <tr> + <td><a href="index/$k">$k</a></td> + <td>$v</td> + </tr> #end for + </table> #end def diff --git a/templates/letter_toc.tmpl b/templates/letter_toc.tmpl index 308e535..a5623f4 100644 --- a/templates/letter_toc.tmpl +++ b/templates/letter_toc.tmpl @@ -13,7 +13,7 @@ Debian Project patch tracking system <th>$d</th> #end for </tr> -#for $p in $pkgs +#for $p in $sorted($pkgs.iterkeys) <tr> <td> <a href="http://packages.debian.org/$p">$p</a> diff --git a/templates/package_vers.tmpl b/templates/package_vers.tmpl index 4ecd692..e1f6350 100755 --- a/templates/package_vers.tmpl +++ b/templates/package_vers.tmpl @@ -20,30 +20,30 @@ debian specific patch information for $src.name / $suite <th>Source Package Format</th> <td>$src.format</td> </tr> -#if $src.diffgz +#if $src.diffgz_name <tr> <th>Diff.gz</th> - <td>$src.loc / $src.diffgz['name']</td> + <td>$src.loc / $src.diffgz_name</td> </tr> #end if </table> -#if $src.diffgz +#if $src.diffgz_name <h2> "Debian diff" Information </h2> <table class="patchlisting"> <tr> <th>Diff file</th> <td colspan="2"> - <a href="$conf.archive_root_url/$src.loc/$src.diffgz['name']"> - $src.diffgz['name'] + <a href="$conf.archive_root_url/$src.loc/$src.diffgz_name"> + $src.diffgz_name </a> </td> </tr> <tr> - <th>Size</th><td colspan="2">$src.diffgz['size']</td> + <th>Size</th><td colspan="2">$src.diffgz_size</td> </tr> <tr> - <th>MD5sum</th><td colspan="2">$src.diffgz['md5sum']</td> + <th>MD5sum</th><td colspan="2">$src.diffgz_md5sum</td> </tr> <tr> <th>./debian only changes</th> @@ -54,7 +54,7 @@ debian specific patch information for $src.name / $suite <a href="$u/patch/debianonly/dl/$src.name/$src.version">download</a> </td> </tr> -#if $src.diffgz and $diffhandler.nondebiandir.lines +#if $src.diffgz_name and $diffhandler.nondebiandir.lines <tr> <th>non packaging (i.e. not ./debian) changes</th> <td> @@ -68,7 +68,7 @@ debian specific patch information for $src.name / $suite </table> #end if -#if $src.diffgz and $diffhandler.nondebiandir.lines +#if $src.diffgz_name and $diffhandler.nondebiandir.lines <h2> Misc. Non-packaging "direct" style patches </h2> <table class="patchlisting"> <tr> @@ -81,7 +81,7 @@ debian specific patch information for $src.name / $suite </table> #end if -#if $src.diffgz +#if $src.diffgz_name #set $series = $diffhandler.series #if $series <h2> "series" style patches </h2> |