#
#
# add_file "templates/revisionbrowse.html"
# content [45348e21f3fc76b5cfa945ec4be8fbba1af7a267]
#
# patch "viewmtn.py"
# from [88e9dbedf9327ae01d3866eac3769733b9197efc]
# to [5c41506fafddfc5f74233a652edda92f89be421e]
#
============================================================
--- templates/revisionbrowse.html 45348e21f3fc76b5cfa945ec4be8fbba1af7a267
+++ templates/revisionbrowse.html 45348e21f3fc76b5cfa945ec4be8fbba1af7a267
@@ -0,0 +1,50 @@
+#extends revision
+
+#def body
+
+#filter Filter
+
+Path [$path] in revision $link($revision).html()
+#if len($branches) == 1
+of branch
+#end if
+#if len($branches) > 1
+of branches
+#end if
+#if $branches
+$branch_links
+#end if
+
+#filter WebSafe
+
+
+ | Name | Age | Author | Last log entry |
+#for $stanza_type, $this_path, $author, $ago, $content_mark, $shortlog in $entries
+
+
+
+ |
+
+ #filter Filter
+ $link($this_path).html()
+ #filter WebSafe
+ |
+
+ #if $content_mark
+ #filter Filter
+ $link($content_mark).html($ago, True)
+ #filter WebSafe
+ #end if
+ |
+
+ #filter Filter
+ $author
+ #filter WebSafe |
+
+ $shortlog
+ |
+
+#end for
+
+
+#end def
============================================================
--- viewmtn.py 88e9dbedf9327ae01d3866eac3769733b9197efc
+++ viewmtn.py 5c41506fafddfc5f74233a652edda92f89be421e
@@ -52,6 +52,9 @@ def quicklog(changelog):
interesting_line = interesting_line[1:].strip()
return interesting_line
+def nbhq(s):
+ return ' '.join([hq(t) for t in s.split(' ')])
+
def normalise_changelog(changelog):
changelog = map(hq, changelog.split('\n'))
if changelog and changelog[-1] == '':
@@ -64,9 +67,12 @@ class Link:
self.description = description
def uri(self):
return dynamic_join(self.relative_uri)
- def html(self, override_description=None):
+ def html(self, override_description=None, force_nbsp=False):
if override_description:
- d = hq(override_description)
+ if force_nbsp:
+ d = nbhq(override_description)
+ else:
+ d = hq(override_description)
else:
d = self.description
return '%s' % (dynamic_join(self.relative_uri),
@@ -329,7 +335,7 @@ class BranchChanges:
elif cert[5] == 'author':
author = cert[7]
elif cert[5] == 'changelog':
- changelog = normalised_changelog(cert[7])
+ changelog = normalise_changelog(cert[7])
shortlog = quicklog(changelog)
if rev_branch != branch.name:
# yikes, fallen down a well
@@ -451,14 +457,7 @@ class RevisionBrowse(RevisionPage):
revision = mtn.Revision(revision)
branches = RevisionPage.branches_for_rev(self, revision)
revisions = ops.get_revision(revision)
- page_title = "Browsing revision %s [%s]" % (revision.abbrev(), path or '')
- if len(branches) > 0:
- if len(branches) == 1:
- branch_plural = 'branch'
- else:
- branch_plural = 'branches'
- page_title += " of %s %s" % (branch_plural, ', '.join(branches))
-
+
def components(path):
# NB: mtn internally uses '/' for paths, so we shouldn't use os.path.join()
# we should do things manually; otherwise we'll break on other platforms
@@ -477,11 +476,20 @@ class RevisionBrowse(RevisionPage):
rv.append(pc[0])
path = ''
return rv
-
+
+ path = path or ""
path_components = components(path)
normalised_path = '/'.join(path_components)
# TODO: detect whether or not this exists and skip the following if it doesn't.
+ page_title = "Browsing revision %s [%s]" % (revision.abbrev(), normalised_path or '')
+ if len(branches) > 0:
+ if len(branches) == 1:
+ branch_plural = 'branch'
+ else:
+ branch_plural = 'branches'
+ page_title += " of %s %s" % (branch_plural, ', '.join(branches))
+
def cut_manifest_to_subdir():
manifest = map(None, ops.get_manifest_of(revision))
in_the_dir = False
@@ -496,33 +504,42 @@ class RevisionBrowse(RevisionPage):
in_the_dir = True
continue
- # debug(["inthedir", stanza_type, this_path])
this_path_components = components(this_path)
+ # debug(["inthedir", stanza_type, this_path, len(this_path_components), len(path_components)])
if stanza_type == "dir":
- if len(this_path_components) == len(path_components) + 1 and \
+ # are we still in our directory?
+ if len(this_path_components) > len(path_components) and \
this_path_components[:len(path_components)] == path_components:
- yield (stanza_type, this_path)
+ # is this an immediate subdirectory of our directory?
+ if len(this_path_components) == len(path_components) + 1:
+ yield (stanza_type, this_path)
else:
in_the_dir = False
# and we've come out of the dir ne'er to re-enter, so..
break
- elif stanza_type == "file" and len(this_path_components) == len(path_components):
+ elif stanza_type == "file" and len(this_path_components) == len(path_components) + 1:
yield (stanza_type, this_path)
- def get_timecert(rev):
- for cert in ops.certs(rev):
- if cert[4] == 'name' and cert[5] == 'date':
- revdate = common.parse_timecert(cert[7])
+ def info_for_manifest(entry_iter):
+ def timecert(certs):
+ for cert in certs:
+ if cert[4] == 'name' and cert[5] == 'date':
+ revdate = common.parse_timecert(cert[7])
- def info_for_manifest(entry_iter):
- 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.sort(lambda b, a: cmp(get_timecert(a), get_timecert(b)))
- content_mark = content_marks[0]
- # determine the author, and the shortlog
+ # should probably limit memory usage (worst case is this gets huge)
+ # but for now, this is really a needed optimisation, as most of the
+ # time a single cert will be seen *many* times
+ certs = {}
+ certinfo = {}
+
+ def get_cert(cert):
+ if not certs.has_key(cert):
+ certs[cert] = ops.certs(cert)
+ return certs[cert]
+
+ def _get_certinfo(cert):
author, ago, shortlog = None, None, None
- for cert in ops.certs(content_mark):
+ for cert in get_cert(cert):
if cert[4] != 'name':
continue
name, value = cert[5], cert[7]
@@ -533,15 +550,48 @@ class RevisionBrowse(RevisionPage):
ago = common.ago(revdate)
elif name == "changelog":
shortlog = quicklog(normalise_changelog(value))
- to_yield = (stanza_type, this_path, author, ago, shortlog)
- yield map(lambda x: x or "", to_yield)
+ to_return = (author, ago, shortlog)
+ return [t or "" for t in to_return]
+ def get_certinfo(cert):
+ if not certinfo.has_key(cert):
+ certinfo[cert] = _get_certinfo(cert)
+ return certinfo[cert]
+
+ 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)]
+ for mark in content_marks:
+ certs[mark] = get_cert(mark)
+ if len(content_marks):
+ content_marks.sort(lambda b, a: cmp(timecert(certs[a]), timecert(certs[b])))
+ content_mark = mtn.Revision(content_marks[0])
+ author, ago, shortlog = get_certinfo(content_mark)
+ else:
+ author, ago, shortlog, content_mark = "", "", "", None
+ yield (stanza_type, mtn.File(this_path, revision), nbhq(author), ago, content_mark, shortlog)
+
+ def path_links(components):
+ # we always want a link to '/'
+ links = ["/"]
+ running_path = ""
+ for component in components:
+ running_path += component + "/"
+ links.append(running_path)
+
+ def row_class():
+ while True:
+ yield "even"
+ yield "odd"
+
renderer.render('revisionbrowse.html',
branches=branches,
branch_links=', '.join(map(lambda b: link(mtn.Branch(b)).html(), branches)),
path=path,
page_title=page_title,
revision=revision,
+ path_links=path_links(path_components),
+ row_class=row_class(),
entries=info_for_manifest(cut_manifest_to_subdir()))
class RevisionTar: