# # # patch "ancestry.py" # from [6000ee066cd8eb2522563d195869b039e40fd70b] # to [6c95bd62605ad5bb4359dff0e4c8942b6faf9285] # # patch "handlers.py" # from [fa13ff0c027a94aeec104c8b07f63d605ad78db4] # to [e9af5798e92963ad207ab1c3a3646818ae952175] # # patch "links.py" # from [6ac854e0dfc2959803a89f2cb38c4fd7366eb070] # to [193e314b64731eee79799e24847557aa9cc7ee43] # # patch "render.py" # from [c1223ddbb5396f63101b981838cd8296d0cc82ba] # to [2a55c2e22ff97d808ca4fd06d39eb7bea8a101d3] # # patch "templates/base.html" # from [781439204c039e9426f067b004cbb9ba9f0b39ad] # to [8d1f9004c63ca950378f4dc1425deee063b0216d] # # patch "templates/branch.html" # from [7f162c333735ef7f64cd507d524653155972ca9f] # to [ed21182f8c1b680b5b25f3d59a4fc08c12a26a0a] # # patch "templates/branchchangesrss.html" # from [bfbbfead32d6e0aad40646932be79348f2aba0af] # to [b64e6216c319ef2a5a803b4e2483068c59a5f9d8] # # patch "templates/index.html" # from [c8cce216300ecbead5ba0ffad4c4cf26f43885d1] # to [dbcf4480fc966a46608f260adaf0689b0cf3c476] # # patch "templates/revision.html" # from [e9eeb6212f211ce522b1db16156e7129e00993d1] # to [aa7ca2c65f3076fdc9bdf2276aca414f99ca40d8] # # patch "templates/revisioninfo.html" # from [a6ef44ec8a9a16b735b7edea9467072e2c08ce12] # to [69fdcd40892b237c2cf85602a61e7f31ba112675] # # patch "urls.py" # from [16a510f175f983e3853bc0d61029a95e59ae0bbe] # to [74ec1a0af57afeb7d98bcf04248d799b8d9b2738] # # patch "viewmtn.py" # from [6629b45724cc639d2555c41248ccadf35838b83e] # to [ae38f0301e147803284029b0216e4c0c4e5fd6bb] # ============================================================ --- ancestry.py 6000ee066cd8eb2522563d195869b039e40fd70b +++ ancestry.py 6c95bd62605ad5bb4359dff0e4c8942b6faf9285 @@ -9,18 +9,17 @@ import mtn import rfc822, string, sha, os import mtn -from links import link from colorsys import hls_to_rgb import config -def ancestry_dot(ops, revision): +def ancestry_dot(ctxt, revision): def dot_escape(s): # TODO: kind of paranoid, should probably revise permitted = string.digits + string.letters + ' -<>-:,address@hidden&.+_~?/' return ''.join([t for t in s if t in permitted]) revision = mtn.Revision(revision) original_branches = [] - for cert in ops.certs(revision): + for cert in ctxt.ops.certs(revision): if cert[4] == 'name' and cert[5] == 'branch': original_branches.append(cert[7]) @@ -52,10 +51,10 @@ def ancestry_dot(ops, revision): visited = set() def visit_node(revision): - for node in ops.children(revision): + for node in ctxt.ops.children(revision): arcs.add((revision, node)) nodes.add(node) - for node in ops.parents(revision): + for node in ctxt.ops.parents(revision): arcs.add((node, revision)) nodes.add(node) visited.add(revision) @@ -98,7 +97,7 @@ digraph ancestry { for node in nodes: author, date = '', '' branches = [] - for cert in ops.certs(node): + for cert in ctxt.ops.certs(node): if cert[4] == 'name' and cert[5] == 'date': date = cert[7] elif cert[4] == 'name' and cert[5] == 'author': @@ -133,7 +132,7 @@ digraph ancestry { value = nodeopts[option] options.append('%s="%s"' % (option, value)) options.append('label="%s"' % (node_label[node])) - options.append('href="%s"' % link(node).uri()) + options.append('href="%s"' % ctxt.link(node).uri()) line += '[' + ','.join(options) + ']' graph += line + '\n' @@ -149,8 +148,8 @@ digraph ancestry { graph += '}' return graph -def ancestry_graph(ops, revision): - dot_data = ancestry_dot(ops, revision) +def ancestry_graph(ctxt, revision): + dot_data = ancestry_dot(ctxt, revision) # okay, let's output the graph graph_sha = sha.new(dot_data).hexdigest() if not os.access(config.graphopts['directory'], os.R_OK): ============================================================ --- handlers.py fa13ff0c027a94aeec104c8b07f63d605ad78db4 +++ handlers.py e9af5798e92963ad207ab1c3a3646818ae952175 @@ -18,7 +18,6 @@ import mtn, common, syntax, release, bra from fdo import sharedmimeinfo, icontheme # Other bits of ViewMTN import mtn, common, syntax, release, branchdiv -from links import link, dynamic_join, static_join from ancestry import ancestry_graph from render import * hq = cgi.escape @@ -38,8 +37,6 @@ else: else: mimeicon = None -# Renderer, sort out template inheritance, etc, etc. -renderer = Renderer() # Figure out branch divisions divisions = branchdiv.BranchDivisions () @@ -76,11 +73,11 @@ class Index(object): # any stragglers need to be closed for div in in_divs.keys(): yield end_div (div) - renderer.render('index.html', page_title="Branches", branches=division_iter()) + ctxt.render('index.html', page_title="Branches", branches=division_iter()) class About(object): - def GET(self): - renderer.render('about.html', page_title="About") + def GET(self, ctxt): + ctxt.render('about.html', page_title="About") class Tags(object): def GET(self, ctxt, restrict_branch=None): @@ -105,11 +102,11 @@ class Tags(object): revdate = common.parse_timecert(cert[7]) rv = common.ago(revdate) return rv - renderer.render(template_file, page_title="Tags", tags=tags, revision_ago=revision_ago, branch=restrict_branch) + ctxt.render(template_file, page_title="Tags", tags=tags, revision_ago=revision_ago, branch=restrict_branch) class Help(object): - def GET(self): - renderer.render('help.html', page_title="Help") + def GET(self, ctxt): + ctxt.render('help.html', page_title="Help") class Changes(object): class ComparisonRev: @@ -183,7 +180,7 @@ class Changes(object): rv = True return rv - def for_template(self, ops, revs, pathinfo=None, constrain_diff_to=None): + def for_template(self, ctxt, revs, pathinfo=None, constrain_diff_to=None): rv = [] for rev, certs in revs: rev_branch = "" @@ -210,12 +207,12 @@ class Changes(object): diff_to_revision = mtn.Revision(constrain_diff_to) else: diff_to_revision = revision - for stanza in ops.get_revision(rev): + for stanza in ctxt.ops.get_revision(rev): if stanza and stanza[0] == "old_revision": diffs.append(Diff(mtn.Revision(stanza[1]), diff_to_revision, filename)) if diffs: if constrain_diff_to: diffs = [ diffs[0] ] - diffs = '| ' + ', '.join([link(d).html('diff') for d in diffs]) + diffs = '| ' + ', '.join([ctxt.link(d).html('diff') for d in diffs]) else: diffs = '' rv.append((revision, diffs, ago, mtn.Author(author), '
\n'.join(changelog), shortlog, when, mtn.File(filename, rev))) @@ -250,22 +247,25 @@ class Changes(object): 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(ctxt.ops, branch, from_change, to_change) + last_changes = self.branch_get_last_changes(ctxt.ops, branch, from_change, to_change) + if last_changes is None: + return web.notfound() + changed, new_starting_point = last_changes changed = changed[from_change:to_change] if len(changed) != to_change - from_change: next_from, next_to = None, None if from_change <= 0: previous_from, previous_to = None, None - renderer.render(template_name, - page_title="Branch %s" % branch.name, - branch=branch, - from_change=from_change, - to_change=to_change, - previous_from=previous_from, - previous_to=previous_to, - next_from=next_from, - next_to=next_to, - display_revs=self.for_template(ctxt.ops, changed)) + ctxt.render(template_name, + page_title="Branch %s" % branch.name, + branch=branch, + from_change=from_change, + to_change=to_change, + previous_from=previous_from, + previous_to=previous_to, + next_from=next_from, + next_to=next_to, + display_revs=self.for_template(ctxt, 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): @@ -301,17 +301,17 @@ class Changes(object): next_from, next_to = None, None if from_change <= 0: previous_from, previous_to = None, None - renderer.render(template_name, - page_title="Changes to '%s' (from %s)" % (cgi.escape(path), revision.abbrev()), - filename=mtn.File(path, revision), - revision=revision, - from_change=from_change, - to_change=to_change, - previous_from=previous_from, - previous_to=previous_to, - next_from=next_from, - next_to=next_to, - display_revs=self.for_template(ctxt.ops, changed, pathinfo=pathinfo, constrain_diff_to=revision)) + ctxt.render(template_name, + page_title="Changes to '%s' (from %s)" % (cgi.escape(path), revision.abbrev()), + filename=mtn.File(path, revision), + revision=revision, + from_change=from_change, + to_change=to_change, + previous_from=previous_from, + previous_to=previous_to, + next_from=next_from, + next_to=next_to, + display_revs=self.for_template(ctxt, changed, pathinfo=pathinfo, constrain_diff_to=revision)) class HTMLBranchChanges(Changes): def GET(self, ctxt, branch, from_change, to_change): @@ -366,19 +366,19 @@ class RevisionInfo(RevisionPage): return web.notfound() certs = ctxt.ops.certs(revision) revisions = ctxt.ops.get_revision(revision) - output_png, output_imagemap = ancestry_graph(ctxt.ops, revision) + output_png, output_imagemap = ancestry_graph(ctxt, revision) if os.access(output_imagemap, os.R_OK): imagemap = open(output_imagemap).read().replace('\\n', ' by ') - imageuri = dynamic_join('revision/graph/' + revision) + imageuri = ctxt.perdb_join('revision/graph/' + revision) else: imagemap = imageuri = None - renderer.render('revisioninfo.html', - page_title="Revision %s" % revision.abbrev(), - revision=revision, - certs=certs_for_template(certs), - imagemap=imagemap, - imageuri=imageuri, - revisions=revisions_for_template(revision, revisions)) + ctxt.render('revisioninfo.html', + page_title="Revision %s" % revision.abbrev(), + revision=revision, + certs=certs_for_template(ctxt, certs), + imagemap=imagemap, + imageuri=imageuri, + revisions=revisions_for_template(ctxt, revision, revisions)) class RevisionDiff(RevisionPage): def GET(self, ctxt, revision_from, revision_to, filename=None): @@ -394,14 +394,14 @@ class RevisionDiff(RevisionPage): 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()), - revision=revision_from, - revision_from=revision_from, - revision_to=revision_to, - diff=syntax.highlight(diff, 'diff'), - diff_obj=diff_obj, - files=files) + ctxt.render('revisiondiff.html', + page_title="Diff from %s to %s" % (revision_from.abbrev(), revision_to.abbrev()), + revision=revision_from, + revision_from=revision_from, + revision_to=revision_to, + diff=syntax.highlight(diff, 'diff'), + diff_obj=diff_obj, + files=files) class RevisionRawDiff(RevisionPage): def GET(self, ctxt, revision_from, revision_to, filename=None): @@ -447,12 +447,12 @@ class RevisionFile(RevisionPage): template = 'revisionfiletxt.html' else: template = 'revisionfilebin.html' - renderer.render(template, - filename=mtn.File(filename, revision), - page_title="File %s in revision %s" % (filename, revision.abbrev()), - revision=revision, - mimetype=mimetype, - contents=syntax.highlight(contents, language)) + ctxt.render(template, + filename=mtn.File(filename, revision), + page_title="File %s in revision %s" % (filename, revision.abbrev()), + revision=revision, + mimetype=mimetype, + contents=syntax.highlight(contents, language)) class RevisionDownloadFile(RevisionPage): def GET(self, ctxt, revision, filename): @@ -652,22 +652,22 @@ class RevisionBrowse(RevisionPage): yield "even" def mime_icon(mime_type): - return dynamic_join('mimeicon/' + mime_type) + return ctxt.nodb_join('mimeicon/' + mime_type) - renderer.render('revisionbrowse.html', - branches=branches, - branch_links=', '.join([link(mtn.Branch(b)).html() for b in branches]), - path=path, - page_title=page_title, - revision=revision, - path_links=path_links(path_components), - row_class=row_class(), - mime_icon=mime_icon, - entries=info_for_manifest(cut_manifest_to_subdir())) + ctxt.render('revisionbrowse.html', + branches=branches, + branch_links=', '.join([ctxt.link(mtn.Branch(b)).html() for b in branches]), + path=path, + page_title=page_title, + revision=revision, + path_links=path_links(path_components), + row_class=row_class(), + mime_icon=mime_icon, + entries=info_for_manifest(cut_manifest_to_subdir())) class RevisionGraph(object): def GET(self, ctxt, revision): - output_png, output_imagemap = ancestry_graph(ctxt.ops, revision) + output_png, output_imagemap = ancestry_graph(ctxt, revision) if os.access(output_png, os.R_OK): web.header('Content-Type', 'image/png') sys.stdout.write(open(output_png).read()) @@ -732,12 +732,12 @@ class BranchHead(object): if len(heads) == 0: return web.notfound() def proxyurl(revision): - return dynamic_join('revision/' + proxy_to + '/' + revision + urllib.quote(extra_path)) + return ctxt.perdb_join('revision/' + proxy_to + '/' + revision + urllib.quote(extra_path)) if len(heads) == 1 or head_method == 'anyhead': web.redirect(proxyurl(heads[0])) else: # present an option to the user to choose the head - anyhead = 'link' % (dynamic_join('branch/anyhead/' + \ + anyhead = 'link' % (ctxt.perdb_join('branch/anyhead/' + \ proxy_to + '/' + urllib.quote(branch.name, safe = ''))) head_links = [] for revision in heads: @@ -749,14 +749,14 @@ class BranchHead(object): author = mtn.Author(cert[7]) head_links.append('%s %s at %s' % (proxyurl(revision), revision.abbrev(), - link(author).html(), + ctxt.link(author).html(), hq(date))) - renderer.render('branchchoosehead.html', - page_title="Branch %s" % branch.name, - branch=branch, - proxy_to=proxy_to, - anyhead=anyhead, - head_links=head_links) + ctxt.render('branchchoosehead.html', + page_title="Branch %s" % branch.name, + branch=branch, + proxy_to=proxy_to, + anyhead=anyhead, + head_links=head_links) class MimeIcon(object): def GET(self, type, sub_type): ============================================================ --- links.py 6ac854e0dfc2959803a89f2cb38c4fd7366eb070 +++ links.py 193e314b64731eee79799e24847557aa9cc7ee43 @@ -16,9 +16,6 @@ import config import json import config -dynamic_join = lambda path: urlparse.urljoin(config.dynamic_uri_path, path) -static_join = lambda path: urlparse.urljoin(config.static_uri_path, path) - hq = cgi.escape class Link(object): @@ -27,10 +24,19 @@ class Link(object): self.relative_uri = None self.description = description self.json_args = None + self.ctxt = kwargs['ctxt'] + def nbhq(self, s): return ' '.join([hq(t) for t in s.split(' ')]) + def uri(self): - return dynamic_join(self.relative_uri) + if not self.absolute_uri is None: + return self.absolute_uri + elif not self.relative_uri is None: + return self.ctxt.perdb_join(self.relative_uri) + else: + return None + def html(self, override_description=None, force_nbsp=False): if override_description: if force_nbsp: @@ -39,12 +45,9 @@ class Link(object): d = hq(override_description) else: d = self.description - if self.relative_uri: - uri = dynamic_join(self.relative_uri) - elif self.absolute_uri: - uri = self.absolute_uri - else: - return self.description + uri = self.uri() + if uri is None: + return hq(self.description) rv = '%s' % (uri, d) if self.json_args != None: enc_args = binascii.hexlify(json.write(self.json_args)) @@ -150,11 +153,9 @@ def link(obj, link_type=None, **kwargs): link_class = type_to_link_class.get(obj.obj_type) if not link_class: raise LinkException("Unable to link to objects of type: '%s'" % (obj.obj_type)) - # ugh - if link_type: + # bodgy, but can't give named arguments from the templates so we need to + # have the second argument go into link_type + if not link_type is None: kwargs['link_type'] = link_type - return link_class(obj, **kwargs) - - - - + rv = link_class(obj, **kwargs) + return rv ============================================================ --- render.py c1223ddbb5396f63101b981838cd8296d0cc82ba +++ render.py 2a55c2e22ff97d808ca4fd06d39eb7bea8a101d3 @@ -9,7 +9,6 @@ import mtn, release, config, common import cgi, urllib, web import mtn, release, config, common -from links import link, dynamic_join, static_join hq = cgi.escape @@ -55,7 +54,7 @@ def prettify(s): def prettify(s): return ' '.join([hq(x[0].upper() + x[1:]) for x in s.replace("_", "").split(" ")]) -def certs_for_template(cert_gen): +def certs_for_template(ctxt, cert_gen): for cert in cert_gen: if cert[0] == 'key' and len(cert) != 10: raise Exception("Not a correctly formatted certificate: %s" % cert) @@ -66,7 +65,7 @@ def certs_for_template(cert_gen): name = cert[5] value = cert[7] if name == "branch": - value = link(mtn.Branch(value)).html() + value = ctxt.link(mtn.Branch(value)).html() else: value = '
'.join(map(hq, value.split('\n'))) @@ -74,7 +73,7 @@ def certs_for_template(cert_gen): 'name' : prettify(name), 'value' : value } -def revisions_for_template(revision, rev_gen): +def revisions_for_template(ctxt, revision, rev_gen): old_revisions = [] stanzas = [] grouping = None @@ -99,18 +98,18 @@ def revisions_for_template(revision, rev # skip it here if not from_id: continue - diff_links = ','.join([link(Diff(old_revision, revision, fname)).html() for old_revision in old_revisions]) - value = "Patch file %s (%s)" % (link(mtn.File(fname, revision)).html(), diff_links) + diff_links = ','.join([ctxt.link(Diff(old_revision, revision, fname)).html() for old_revision in old_revisions]) + value = "Patch file %s (%s)" % (ctxt.link(mtn.File(fname, revision)).html(), diff_links) elif stanza_type == "old_revision": old_revision = mtn.Revision(stanza[1]) if old_revision.is_empty: value = "This revision is has no ancestor." else: old_revisions.append(old_revision) - value = "Old revision is: %s (%s)" % (link(old_revision).html(), link(Diff(old_revision, revision)).html()) + value = "Old revision is: %s (%s)" % (ctxt.link(old_revision).html(), ctxt.link(Diff(old_revision, revision)).html()) elif stanza_type == "add_file": fname = stanza[1] - value = "Add file: %s" % (link(mtn.File(fname, revision)).html()) + value = "Add file: %s" % (ctxt.link(mtn.File(fname, revision)).html()) elif stanza_type == "add_dir": dname = stanza[1] value = "Add directory: %s" % (hq(dname)) @@ -119,10 +118,10 @@ def revisions_for_template(revision, rev value = "Delete: %s" % (hq(fname)) elif stanza_type == "set": fname, attr, value = stanza[1], stanza[3], stanza[5] - value = "Set attribute '%s' to '%s' upon %s" % (hq(attr), hq(value), link(mtn.File(fname, revision)).html()) + value = "Set attribute '%s' to '%s' upon %s" % (hq(attr), hq(value), ctxt.link(mtn.File(fname, revision)).html()) elif stanza_type == "rename": oldname, newname = stanza[1], stanza[3] - value = "Rename %s to %s" % (hq(oldname), link(mtn.File(newname, revision)).html()) + value = "Rename %s to %s" % (hq(oldname), ctxt.link(mtn.File(newname, revision)).html()) else: value = "(this stanza type is not explicitly rendered; please report this.)\n%s" % hq(str(stanza)) @@ -146,11 +145,8 @@ class Renderer(object): # these variables will be available to any template self.terms = { 'dynamic_uri_path' : config.dynamic_uri_path, - 'dynamic_join' : dynamic_join, 'urllib_quote' : urllib.quote, 'static_uri_path' : config.static_uri_path, - 'static_join' : static_join, - 'link' : link, 'version' : release.version, } @@ -160,8 +156,12 @@ class Renderer(object): web.render(template, None, True, mod_name) self._templates_loaded = True - def render(self, template, **kwargs): + def render(self, ctxt, template, **kwargs): self.load_templates() terms = self.terms.copy() terms.update(kwargs) + terms['link'] = ctxt.link + terms['perdb_join'] = ctxt.perdb_join + terms['nodb_join'] = ctxt.nodb_join + terms['static_join'] = ctxt.static_join web.render(template, terms) ============================================================ --- templates/base.html 781439204c039e9426f067b004cbb9ba9f0b39ad +++ templates/base.html 8d1f9004c63ca950378f4dc1425deee063b0216d @@ -17,10 +17,10 @@