# -*- coding: utf-8 -*- import cgi import os import sys import patchtracker.Conf as Conf from patchtracker.Templates import ErrorTemplate, PatchTemplate, PackageVersTemplate, LetterTocTemplate, FrontPageTemplate, SearchResultsTemplate 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 import patchtracker.SourceArchive as SourceArchive class ReqHandlerException(Exception): def __init__(self, msg, code="500 Oh noes"): Exception.__init__(self, msg) self.status=code class Cmd: def __init__(self): self.content_type = 'text/html' self.status = "200 OK" class ErrorCmd(Cmd): def __init__(self, msg, code="500 Oh noes"): Cmd.__init__(self) self.status = code self.msg = msg def output(self): return str(ErrorTemplate(self.msg)) class PatchCmd(Cmd): def __init__(self, args): Cmd.__init__(self) self.db = PatchTrackerDB() self.patchtype,mode,pkgname,version = args[0:4] self.parsemode(mode) dh = self.make_diffhandler(pkgname,version) if self.patchtype == "series": self.patchname = os.sep.join(args[4:]) self.content = dh.series().fetch(self.patchname) elif self.patchtype == "debianonly": self.patchname = "debian-dir only changes" self.content = dh.debiandir() elif self.patchtype == "nondebian": self.patchname = "direct (non packaging) changes" self.content = dh.nondebiandir() elif self.patchtype == "misc": self.patchname = os.sep.join(args[4:]) self.content = dh.filterdiff(include=self.patchname) else: raise ReqHandlerException("unhandled patch type '%s'"%(self.patchtype)) self.pkgname = pkgname self.version = version def parsemode(self, mode): if mode == "view" or mode == "dl": self.mode = mode else: raise ReqHandlerException("unhandled display mode '%s'"%(mode)) if mode == "dl": self.content_type = "text/x-diff" def make_diffhandler(self, pkgname, vers): dfile = self.db.findDiffGz(pkgname,vers) if dfile: return DiffGzHandler(dfile) else: raise ReqHandlerException("can not find diff file for %s / %s"%(pkgname,vers)) def output(self): if self.mode == "dl": return str(self.content) else: return str(PatchTemplate(pkg=self.pkgname,vers=self.version, patch=self.content,name=self.patchname, patchtype=self.patchtype)) class PackageCmd(Cmd): def __init__(self, args): Cmd.__init__(self) db = PatchTrackerDB() self.name = args[0] if len(args) > 1: version = args[1] else: version = None self.toc = db.findCollection(package=self.name, version=version) if self.toc.size() == 0: if len(self.name) >= 3: self.toc = db.findCollection(package="%"+self.name+"%", version=version) plist = self.toc.getletter(self.name) if len(self.name) < 3: raise ReqHandlerException("search terms must be 3 or more letters...") elif not plist or len(plist) == 0: raise ReqHandlerException("can't find any package named or containing '%s'"%self.name, code="404 ENOPKG kthxbye") def output(self): p = self.toc.getpackage(self.name) # if there is no match, or if multiple versions were returned if not p or len(set(map(lambda x: x.version, p.values()))) > 1: querydesc = "package name contains" return str(SearchResultsTemplate(self.name, querydesc, self.toc)) else: return str(PackageVersTemplate(p.popitem()[1])) class IndexCmd(Cmd): def __init__(self, args): Cmd.__init__(self) if len(args) < 1 or not len(args[0]): raise ReqHandlerException("please provide a letter on which to index") else: self.db = PatchTrackerDB() self.letter = args[0] self.toc = self.db.findLetterToc(self.letter) def output(self): return str(LetterTocTemplate(self.letter, self.toc)) class MaintCmd(Cmd): def __init__(self, args): Cmd.__init__(self) if len(args) < 1 or not len(args[0]): raise ReqHandlerException("please provide a email address on which to index") else: self.db = PatchTrackerDB() self.email = args[0] self.toc = self.db.findCollection(email=self.email) def output(self): return str(SearchResultsTemplate(self.email, "maintainer email", self.toc)) class JumpCmd(Cmd): def __init__(self, env): Cmd.__init__(self) form = cgi.FieldStorage(fp=env['wsgi.input'],environ=env) self.name = form.getfirst("package") self.uri = "%s/package/%s"%(Conf.root_url, self.name) self.status = "302 Try this other place kthx" def output(self): return "" class FrontPageCmd(Cmd): def __init__(self): Cmd.__init__(self) self.db = PatchTrackerDB() self.index = self.db.findIndices() def output(self): return str(FrontPageTemplate(self.index)) class CmdHandler: def __init__(self, env): self.headers = [] uri=Conf.root_url+env['PATH_INFO'] args = uri[len(Conf.root_url)+1:].split("/") cmdarg = args[0] if cmdarg == "patch": self.cmd = PatchCmd(args[1:]) elif cmdarg == "package": self.cmd = PackageCmd(args[1:]) elif cmdarg == "index": self.cmd = IndexCmd(args[1:]) elif cmdarg == "jump": self.cmd = JumpCmd(env) self.headers.append( ('Location', self.cmd.uri) ) elif cmdarg == "email": self.cmd = MaintCmd(args[1:]) elif not len(cmdarg): self.cmd = FrontPageCmd() else: self.cmd = ErrorCmd("invalid command/location '%s'"%(cmdarg), "404 Not found") self.headers.append( ('Content-type', self.cmd.content_type) ) self.status = self.cmd.status def output(self): return self.cmd.output()