The unified diff between revisions [92eb8752..] and [14e5fc76..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'handlers.py'

#
#
# patch "handlers.py"
#  from [59c9ba315b35d9ffe2667872266876b511188802]
#    to [fa13ff0c027a94aeec104c8b07f63d605ad78db4]
#
============================================================
--- handlers.py	59c9ba315b35d9ffe2667872266876b511188802
+++ handlers.py	fa13ff0c027a94aeec104c8b07f63d605ad78db4
@@ -17,9 +17,8 @@ from fdo import sharedmimeinfo, iconthem
 # FreeDesktop.org share mime info and icon theme specification
 from fdo import sharedmimeinfo, icontheme
 # Other bits of ViewMTN
-import mtn, common, syntax, release
+import mtn, common, syntax, release, branchdiv
 from links import link, dynamic_join, static_join
-from branchdiv import BranchDivisions
 from ancestry import ancestry_graph
 from render import *
 hq = cgi.escape
@@ -38,30 +37,15 @@ else:
         raise e
 else:
     mimeicon = None
+
 # Renderer, sort out template inheritance, etc, etc.
 renderer = Renderer()
 # Figure out branch divisions
-divisions = BranchDivisions ()
+divisions = branchdiv.BranchDivisions ()

-class ComparisonRev:
-    def __init__(self, ops, revision):
-        self.revision = revision
-        self.certs = list(ops.certs(self.revision))
-        self.date = None
-        for cert in self.certs:
-            if cert[4] == 'name' and cert[5] == 'date':
-                self.date = common.parse_timecert(cert[7])
-    def __repr__(self):
-        return "ComparisonRev <%s>" % (repr(self.revision))
-    def __cmp__(self, other):
-        # irritating edge-case, heapq compares us to empty string if
-        # there's only one thing in the list
-        if not other: return 1
-        return cmp(other.date, self.date)
-
 class Index(object):
-    def GET(self, ops):
-        branches = list(ops.branches ())
+    def GET(self, ctxt):
+        branches = list(ctxt.ops.branches ())
         divisions.calculate_divisions (branches)
         def division_iter():
             bitter = iter(branches)
@@ -99,9 +83,9 @@ class Tags(object):
         renderer.render('about.html', page_title="About")

 class Tags(object):
-    def GET(self, ops, restrict_branch=None):
+    def GET(self, ctxt, restrict_branch=None):
         # otherwise we couldn't use automate again..
-        tags = list(ops.tags())
+        tags = list(ctxt.ops.tags())
         if restrict_branch != None:
             restrict_branch = mtn.Branch(restrict_branch)
             def tag_in(tag):
@@ -116,7 +100,7 @@ class Tags(object):
         tags.sort(lambda t1, t2: cmp(t1.name, t2.name))
         def revision_ago(rev):
             rv = ""
-            for cert in ops.certs(rev):
+            for cert in ctxt.ops.certs(rev):
                 if cert[4] == 'name' and cert[5] == 'date':
                     revdate = common.parse_timecert(cert[7])
                     rv = common.ago(revdate)
@@ -128,6 +112,24 @@ class Changes(object):
         renderer.render('help.html', page_title="Help")

 class Changes(object):
+    class ComparisonRev:
+        def __init__(self, ops, revision):
+            self.revision = revision
+            self.certs = list(ops.certs(self.revision))
+            self.date = None
+            for cert in self.certs:
+                if cert[4] == 'name' and cert[5] == 'date':
+                    self.date = common.parse_timecert(cert[7])
+        def __repr__(self):
+            return "ComparisonRev <%s>" % (repr(self.revision))
+        def __cmp__(self, other):
+            # irritating edge-case, heapq compares us to empty string if
+            # there's only one thing in the list
+            if not other:
+                return 1
+            return cmp(other.date, self.date)
+
+
     def __get_last_changes(self, ops, start_from, parent_func, selection_func, n):
         """returns at least n revisions that are parents of the revisions in start_from,
         ordered by time (descending). selection_func is called for each revision, and
@@ -146,7 +148,7 @@ class Changes(object):
         result = []
         revq = []
         for rev in start_from:
-            heapq.heappush(revq, ComparisonRev(ops, rev))
+            heapq.heappush(revq, Changes.ComparisonRev(ops, rev))
         while len(result) < n:
         #           print >>sys.stderr, "start_revq state:", map(lambda x: (x.revision, x.date), revq)
             # update based on the last result we output
@@ -155,7 +157,7 @@ class Changes(object):
                 for parent_rev in parents:
                     if parent_rev == None:
                         continue
-                    heapq.heappush(revq, ComparisonRev(ops, parent_rev))
+                    heapq.heappush(revq, Changes.ComparisonRev(ops, parent_rev))

             # try and find something we haven't already output in the heap
             last_result = None
@@ -245,10 +247,10 @@ class Changes(object):
                                                               to_change)
         return changed, new_starting_point

-    def Branch_GET(self, ops, branch, from_change, to_change, template_name):
+    def Branch_GET(self, ctxt, branch, from_change, to_change, template_name):
         branch = mtn.Branch(branch)
         from_change, to_change, next_from, next_to, previous_from, previous_to = self.determine_bounds(from_change, to_change)
-        changed, new_starting_point = self.branch_get_last_changes(ops, branch, from_change, to_change)
+        changed, new_starting_point = self.branch_get_last_changes(ctxt.ops, branch, from_change, to_change)
         changed = changed[from_change:to_change]
         if len(changed) != to_change - from_change:
             next_from, next_to = None, None
@@ -263,7 +265,7 @@ class Changes(object):
                         previous_to=previous_to,
                         next_from=next_from,
                         next_to=next_to,
-                        display_revs=self.for_template(ops, changed))
+                        display_revs=self.for_template(ctxt.ops, changed))

     def file_get_last_changes(self, ops, from_change, to_change, revision, path):
         def content_changed_fn(start_revision, start_path, in_revision, pathinfo):
@@ -291,9 +293,9 @@ class Changes(object):
                                                               to_change)
         return changed, new_starting_point, pathinfo

-    def File_GET(self, ops, from_change, to_change, revision, path, template_name):
+    def File_GET(self, ctxt, from_change, to_change, revision, path, template_name):
         from_change, to_change, next_from, next_to, previous_from, previous_to = self.determine_bounds(from_change, to_change)
-        changed, new_starting_point, pathinfo = self.file_get_last_changes(ops, from_change, to_change, revision, path)
+        changed, new_starting_point, pathinfo = self.file_get_last_changes(ctxt.ops, from_change, to_change, revision, path)
         changed = changed[from_change:to_change]
         if len(changed) != to_change - from_change:
             next_from, next_to = None, None
@@ -309,15 +311,15 @@ class Changes(object):
                         previous_to=previous_to,
                         next_from=next_from,
                         next_to=next_to,
-                        display_revs=self.for_template(ops, changed, pathinfo=pathinfo, constrain_diff_to=revision))
+                        display_revs=self.for_template(ctxt.ops, changed, pathinfo=pathinfo, constrain_diff_to=revision))

 class HTMLBranchChanges(Changes):
-    def GET(self, ops, branch, from_change, to_change):
-        Changes.Branch_GET(self, ops, branch, from_change, to_change, "branchchanges.html")
+    def GET(self, ctxt, branch, from_change, to_change):
+        Changes.Branch_GET(self, ctxt, branch, from_change, to_change, "branchchanges.html")

 class RSSBranchChanges(Changes):
-    def GET(self, ops, branch, from_change, to_change):
-        Changes.Branch_GET(self, ops, branch, from_change, to_change, "branchchangesrss.html")
+    def GET(self, ctxt, branch, from_change, to_change):
+        Changes.Branch_GET(self, ctxt, branch, from_change, to_change, "branchchangesrss.html")

 class RevisionPage(object):
     def get_fileid(self, ops, revision, filename):
@@ -344,27 +346,27 @@ class RevisionFileChanges(Changes, Revis
         return rv

 class RevisionFileChanges(Changes, RevisionPage):
-    def GET(self, ops, from_change, to_change, revision, path):
+    def GET(self, ctxt, from_change, to_change, revision, path):
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
-        Changes.File_GET(self, ops, from_change, to_change, revision, path, "revisionfilechanges.html")
+        Changes.File_GET(self, ctxt, from_change, to_change, revision, path, "revisionfilechanges.html")

 class RevisionFileChangesRSS(Changes, RevisionPage):
-    def GET(self, ops, from_change, to_change, revision, path):
+    def GET(self, ctxt, from_change, to_change, revision, path):
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
-        Changes.File_GET(self, ops, from_change, to_change, revision, path, "revisionfilechangesrss.html")
+        Changes.File_GET(self, ctxt, from_change, to_change, revision, path, "revisionfilechangesrss.html")

 class RevisionInfo(RevisionPage):
-    def GET(self, ops, revision):
+    def GET(self, ctxt, revision):
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
-        certs = ops.certs(revision)
-        revisions = ops.get_revision(revision)
-        output_png, output_imagemap = ancestry_graph(ops, revision)
+        certs = ctxt.ops.certs(revision)
+        revisions = ctxt.ops.get_revision(revision)
+        output_png, output_imagemap = ancestry_graph(ctxt.ops, revision)
         if os.access(output_imagemap, os.R_OK):
             imagemap = open(output_imagemap).read().replace('\\n', ' by ')
             imageuri = dynamic_join('revision/graph/' + revision)
@@ -379,18 +381,18 @@ class RevisionDiff(RevisionPage):
                         revisions=revisions_for_template(revision, revisions))

 class RevisionDiff(RevisionPage):
-    def GET(self, ops, revision_from, revision_to, filename=None):
+    def GET(self, ctxt, revision_from, revision_to, filename=None):
         revision_from = mtn.Revision(revision_from)
         revision_to = mtn.Revision(revision_to)
-        if not self.exists(ops, revision_from):
+        if not self.exists(ctxt.ops, revision_from):
             return web.notfound()
-        if not self.exists(ops, revision_to):
+        if not self.exists(ctxt.ops, revision_to):
             return web.notfound()
         if filename != None:
             files = [filename]
         else:
             files = []
-        diff = ops.diff(revision_from, revision_to, files)
+        diff = ctxt.ops.diff(revision_from, revision_to, files)
         diff_obj = Diff(revision_from, revision_to, files)
         renderer.render('revisiondiff.html',
                         page_title="Diff from %s to %s" % (revision_from.abbrev(), revision_to.abbrev()),
@@ -402,33 +404,33 @@ class RevisionRawDiff(RevisionPage):
                         files=files)

 class RevisionRawDiff(RevisionPage):
-    def GET(self, ops, revision_from, revision_to, filename=None):
+    def GET(self, ctxt, revision_from, revision_to, filename=None):
         revision_from = mtn.Revision(revision_from)
         revision_to = mtn.Revision(revision_to)
-        if not self.exists(ops, revision_from):
+        if not self.exists(ctxt.ops, revision_from):
             return web.notfound()
-        if not self.exists(ops, revision_to):
+        if not self.exists(ctxt.ops, revision_to):
             return web.notfound()
         if filename != None:
             files = [filename]
         else:
             files = []
-        diff = ops.diff(revision_from, revision_to, files)
+        diff = ctxt.ops.diff(revision_from, revision_to, files)
         web.header('Content-Type', 'text/x-diff')
         for line in diff:
             sys.stdout.write (line)
         sys.stdout.flush()

 class RevisionFile(RevisionPage):
-    def GET(self, ops, revision, filename):
+    def GET(self, ctxt, revision, filename):
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
         language = filename.rsplit('.', 1)[-1]
-        fileid = RevisionPage.get_fileid(self, ops, revision, filename)
+        fileid = RevisionPage.get_fileid(self, ctxt.ops, revision, filename)
         if not fileid:
             return web.notfound()
-        contents = ops.get_file(fileid)
+        contents = ctxt.ops.get_file(fileid)
         mimetype = mimehelp.lookup(filename, '')
         mime_to_template = {
             'image/jpeg'           : 'revisionfileimg.html',
@@ -453,15 +455,15 @@ class RevisionDownloadFile(RevisionPage)
                         contents=syntax.highlight(contents, language))

 class RevisionDownloadFile(RevisionPage):
-    def GET(self, ops, revision, filename):
+    def GET(self, ctxt, revision, filename):
         web.header('Content-Disposition', 'attachment; filename=%s' % filename)
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
-        fileid = RevisionPage.get_fileid(self, ops, revision, filename)
+        fileid = RevisionPage.get_fileid(self, ctxt.ops, revision, filename)
         if not fileid:
             return web.notfound()
-        for idx, data in enumerate(ops.get_file(fileid)):
+        for idx, data in enumerate(ctxt.ops.get_file(fileid)):
             if idx == 0:
                 mimetype = mimehelp.lookup(filename, data)
                 web.header('Content-Type', mimetype)
@@ -469,16 +471,16 @@ class RevisionTar(RevisionPage):
         sys.stdout.flush()

 class RevisionTar(RevisionPage):
-    def GET(self, ops, revision):
+    def GET(self, ctxt, revision):
         # we'll output in the USTAR tar format; documentation taken from:
         # http://en.wikipedia.org/wiki/Tar_%28file_format%29
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
         filename = "%s.tar" % revision
         web.header('Content-Disposition', 'attachment; filename=%s' % filename)
         web.header('Content-Type', 'application/x-tar')
-        manifest = [stanza for stanza in ops.get_manifest_of(revision)]
+        manifest = [stanza for stanza in ctxt.ops.get_manifest_of(revision)]
         # for now; we might want to come up with something more interesting;
         # maybe the branch name (but there might be multiple branches?)
         basedirname = revision
@@ -492,7 +494,7 @@ class RevisionTar(RevisionPage):
             filename, fileid = stanza[1], stanza[3]
             filecontents = cStringIO.StringIO()
             filesize = 0
-            for data in ops.get_file(fileid):
+            for data in ctxt.ops.get_file(fileid):
                 filesize += len(data)
                 filecontents.write(data)
             ti = tarfile.TarInfo()
@@ -500,11 +502,11 @@ class RevisionTar(RevisionPage):
             ti.mode, ti.type = 00600, tarfile.REGTYPE
             ti.uid = ti.gid = 0
             # determine the most recent of the content marks
-            content_marks = [t[1] for t in ops.get_content_changed(revision, filename)]
+            content_marks = [t[1] for t in ctxt.ops.get_content_changed(revision, filename)]
             if len(content_marks) > 0:
                 # just pick one to make this faster
                 content_mark = content_marks[0]
-                since_epoch = timecert(ops.certs(content_mark)) - datetime.datetime.fromtimestamp(0)
+                since_epoch = timecert(ctxt.ops.certs(content_mark)) - datetime.datetime.fromtimestamp(0)
                 ti.mtime = since_epoch.days * 24 * 60 * 60 + since_epoch.seconds
             else:
                 ti.mtime = 0
@@ -513,12 +515,12 @@ class RevisionBrowse(RevisionPage):
             tarobj.addfile(ti, filecontents)

 class RevisionBrowse(RevisionPage):
-    def GET(self, ops, revision, path):
+    def GET(self, ctxt, revision, path):
         revision = mtn.Revision(revision)
-        if not self.exists(ops, revision):
+        if not self.exists(ctxt.ops, revision):
             return web.notfound()
-        branches = RevisionPage.branches_for_rev(self, ops, revision)
-        revisions = ops.get_revision(revision)
+        branches = RevisionPage.branches_for_rev(self, ctxt.ops, revision)
+        revisions = ctxt.ops.get_revision(revision)

         def components(path):
             # NB: mtn internally uses '/' for paths, so we shouldn't use os.path.join()
@@ -553,7 +555,7 @@ class RevisionBrowse(RevisionPage):
             page_title += " of %s %s" % (branch_plural, ', '.join(branches))

         def cut_manifest_to_subdir():
-            manifest = list(ops.get_manifest_of(revision))
+            manifest = list(ctxt.ops.get_manifest_of(revision))
             in_the_dir = False
             for stanza in manifest:
                 stanza_type = stanza[0]
@@ -593,7 +595,7 @@ class RevisionBrowse(RevisionPage):
                 if not certs.has_key(revision):
                     # subtle bug slipped in here; ops.cert() is a generator
                     # so we can't just store it in a cache!
-                    certs[revision] = list(ops.certs(revision))
+                    certs[revision] = list(ctxt.ops.certs(revision))
                 return certs[revision]

             def _get_certinfo(revision):
@@ -619,7 +621,7 @@ class RevisionBrowse(RevisionPage):

             for stanza_type, this_path in entry_iter:
                 # determine the most recent of the content marks
-                content_marks = [t[1] for t in ops.get_content_changed(revision, this_path)]
+                content_marks = [t[1] for t in ctxt.ops.get_content_changed(revision, this_path)]
                 for mark in content_marks:
                     get_cert(mark)
                 if len(content_marks):
@@ -664,8 +666,8 @@ class RevisionGraph(object):
                         entries=info_for_manifest(cut_manifest_to_subdir()))

 class RevisionGraph(object):
-    def GET(self, ops, revision):
-        output_png, output_imagemap = ancestry_graph(ops, revision)
+    def GET(self, ctxt, revision):
+        output_png, output_imagemap = ancestry_graph(ctxt.ops, revision)
         if os.access(output_png, os.R_OK):
             web.header('Content-Type', 'image/png')
             sys.stdout.write(open(output_png).read())
@@ -683,13 +685,13 @@ class Json(object):
                 revdate = common.parse_timecert(cert[7])
                 rv['ago'] = common.ago(revdate)

-    def BranchLink(self, ops, for_branch):
+    def BranchLink(self, ctxt, for_branch):
         rv = {
             'type' : 'branch',
             'branch' : for_branch,
         }
         branch = mtn.Branch(for_branch)
-        changes, new_starting_point = Changes().branch_get_last_changes(ops, branch, 0, 1)
+        changes, new_starting_point = Changes().branch_get_last_changes(ctxt.ops, branch, 0, 1)
         if len(changes) < 1:
             return web.notfound()
         if not changes:
@@ -699,34 +701,34 @@ class Json(object):
             self.fill_from_certs(rv, certs)
         return rv

-    def RevisionLink(self, ops, revision_id):
+    def RevisionLink(self, ctxt, revision_id):
         rv = {
             'type' : 'revision',
             'revision_id' : revision_id,
         }
         rev = mtn.Revision(revision_id)
-        certs = ops.certs(rev)
+        certs = ctxt.ops.certs(rev)
         self.fill_from_certs(rv, certs)
         return rv

-    def GET(self, ops, method, encoded_args):
+    def GET(self, ctxt, method, encoded_args):
         writer = json.JsonWriter()
         if not encoded_args.startswith('js_'):
             return web.notfound()
         args = json.read(binascii.unhexlify((encoded_args[3:])))
         if hasattr(self, method):
-            rv = getattr(self, method)(ops, *args)
+            rv = getattr(self, method)(ctxt, *args)
         else:
             return web.notfound()
         print writer.write(rv)

 class BranchHead(object):
-    def GET(self, ops, head_method, proxy_to, branch, extra_path):
+    def GET(self, ctxt, head_method, proxy_to, branch, extra_path):
         branch = mtn.Branch(branch)
         valid = ('browse', 'file', 'downloadfile', 'info', 'tar', 'graph')
         if not proxy_to in valid:
             return web.notfound()
-        heads = [head for head in ops.heads(branch.name)]
+        heads = [head for head in ctxt.ops.heads(branch.name)]
         if len(heads) == 0:
             return web.notfound()
         def proxyurl(revision):
@@ -740,7 +742,7 @@ class BranchHead(object):
             head_links = []
             for revision in heads:
                 author, date = '', ''
-                for cert in ops.certs(revision):
+                for cert in ctxt.ops.certs(revision):
                     if cert[4] == 'name' and cert[5] == 'date':
                         date = cert[7]
                     elif cert[4] == 'name' and cert[5] == 'author':