#
#
# patch "common.py"
# from [1bbdf3b52720be34cf84c878bc04cd35ac0a6b28]
# to [dee058e73c68b381c4c9c4343fc7d74e3b26479e]
#
# patch "mtn.py"
# from [bfdcd3f284ef8508f44fc96f3ae2c54aa5809b61]
# to [93ca32757dbb55233d8215aedfc6c155432f3d02]
#
# patch "templates/branchchanges.html"
# from [40fd79c1afb1a371288d26707f8592115dc09e36]
# to [bab70162c2dd25a6eb276b7dc09933527b4131fd]
#
# patch "viewmtn.py"
# from [1001ee02e7b1f4554682a8cc0544e161deff6fde]
# to [a2ea5c28701ff9a4d9f2ff0e9023640dc667fc8a]
#
============================================================
--- common.py 1bbdf3b52720be34cf84c878bc04cd35ac0a6b28
+++ common.py dee058e73c68b381c4c9c4343fc7d74e3b26479e
@@ -25,13 +25,6 @@ def terminate_popen3(process):
except:
debug("%s failed_to_stop %s" % (os.getpid(), process.pid))
-def quicklog(value):
- hq = html_escape()
- rv = hq(value.strip().split('\n')[0])
- if rv.startswith('*'):
- rv = rv[1:].strip()
- return rv
-
def ago(event):
def plural(v, singular, plural):
if v == 1:
============================================================
--- mtn.py bfdcd3f284ef8508f44fc96f3ae2c54aa5809b61
+++ mtn.py 93ca32757dbb55233d8215aedfc6c155432f3d02
@@ -312,6 +312,25 @@ class Operations:
for line in self.automate.run('graph', []):
yield line
+ def parents(self, revision):
+ if revision != "":
+ for line in (t.strip() for t in self.automate.run('parents', [revision])):
+ if not line:
+ continue
+ yield apply(Revision, (line,))
+
+ def toposort(self, revisions):
+ for line in (t.strip() for t in self.automate.run('toposort', revisions)):
+ if not line:
+ continue
+ yield apply(Revision, (line,))
+
+ def heads(self, branch):
+ for line in (t.strip() for t in self.automate.run('heads', [branch])):
+ if not line:
+ continue
+ yield apply(Revision, (line,))
+
def get_revision(self, revision):
for stanza in basic_io_from_stream(self.automate.run('get_revision', [revision])):
yield stanza
============================================================
--- templates/branchchanges.html 40fd79c1afb1a371288d26707f8592115dc09e36
+++ templates/branchchanges.html bab70162c2dd25a6eb276b7dc09933527b4131fd
@@ -1,7 +1,41 @@
#extends branch
#def body
-Woo, changes.
+
+Displaying topologically sorted log of changes (estimated as being changes 1 - 10)
+
+
+
+#for $revision, $diffs, $ago, $author, $changelog, $shortlog, $when in $display_revs
+
+ Author: |
+ $author |
+
+
+ Changelog: |
+
+#filter Filter
+$changelog
+#filter WebSafe
+ |
+
+
+ Date: |
+ $when |
+
+#end for
+
+
+
#end def
============================================================
--- viewmtn.py 1001ee02e7b1f4554682a8cc0544e161deff6fde
+++ viewmtn.py a2ea5c28701ff9a4d9f2ff0e9023640dc667fc8a
@@ -40,17 +40,26 @@ class Link:
static_join = lambda path: urlparse.urljoin(config.static_uri_path, path)
class Link:
- def __init__(self, description=None):
+ def __init__(self, description=None, link_type=None):
self.relative_uri = None
self.description = description
- def html(self):
+ def html(self, override_description=None):
+ if override_description:
+ d = hq(override_description)
+ else:
+ d = self.description
return '%s' % (dynamic_join(self.relative_uri),
- self.description)
+ d)
class RevisionLink(Link):
def __init__(self, revision, **kwargs):
+ link_type = kwargs.get("link_type")
+ if link_type == "browse":
+ subpage = "browse"
+ else:
+ subpage = "info"
Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'revision/info/%s' % (revision)
+ self.relative_uri = 'revision/%s/%s' % (subpage, revision)
self.description = revision.abbrev()
class TagLink(Link):
@@ -170,11 +179,11 @@ type_to_link_class = {
'tag' : TagLink,
}
-def link(obj):
+def link(obj, link_type=None):
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))
- return link_class(obj)
+ return link_class(obj, link_type=link_type)
class Renderer:
def __init__(self):
@@ -234,16 +243,83 @@ class BranchChanges:
renderer.render('help.html', page_title="Help")
class BranchChanges:
- def GET(self, branch):
+ def get_last_changes(self, branch, start_at, count):
+ if len(start_at) == 0:
+ revs = map(None, ops.heads(branch.name))
+ else:
+ revs = start_at
+ if len(revs) == 0:
+ raise Exception("get_last_changes() unable to find somewhere to start!")
+ to_parent = revs+[] # copy
+ while len(revs) < count:
+ new_to_parent = []
+ for rev in to_parent:
+ new_to_parent += ops.parents(rev)
+ if len(new_to_parent) == 0:
+ # out of revisions...
+ break
+ to_parent = new_to_parent
+ revs += new_to_parent
+# toposort seems pretty darn slow; let's avoid this one..
+# revs = map(None, ops.toposort(revs))[:count]
+ certs_for_revs = []
+ for rev in revs:
+ certs_for_revs.append((rev, map(None, ops.certs(rev))))
+ def cd(certs):
+ for cert in certs:
+ if cert[4] == 'name' and cert[5] == 'date':
+ return common.parse_timecert(cert[7])
+ return None
+ certs_for_revs.sort(lambda b, a: cmp(cd(a[1]), cd(b[1])))
+ return certs_for_revs[:count], new_to_parent
+
+ def GET(self, branch, start_at=[], old_start_at=[]):
+ def quicklog(changelog):
+ rv = changelog[0].strip()
+ if rv.startswith('*'):
+ rv = rv[1:].strip()
+ return rv
+ def for_template(revs):
+ rv = []
+ for rev, certs in revs:
+ rev_branch = ""
+ revision, diffs, ago, author, changelog, shortlog, when = mtn.Revision(rev), [], "", "", "", "", ""
+ for cert in certs:
+ if cert[4] != 'name':
+ continue
+ if cert[5] == "branch":
+ rev_branch = cert[7]
+ elif cert[5] == 'date':
+ when = cert[7]
+ revdate = common.parse_timecert(when)
+ ago = common.ago(revdate)
+ elif cert[5] == 'author':
+ author = cert[7]
+ elif cert[5] == 'changelog':
+ changelog = map(hq, cert[7].split('\n'))
+ if changelog and changelog[-1] == '':
+ changelog = changelog[:-1]
+ shortlog = quicklog(changelog)
+ if rev_branch != branch.name:
+ # yikes, fallen down a well
+ continue
+ for stanza in ops.get_revision(rev):
+ if stanza and stanza[0] == "old_revision":
+ old_revision = stanza[1]
+ diffs.append(Diff(mtn.Revision(old_revision), revision))
+ if diffs:
+ diffs = '| ' + ', '.join(map(lambda d: link(d).html('diff'), diffs))
+ else:
+ diffs = ''
+ rv.append((revision, diffs, ago, author, '\n'.join(changelog), shortlog, when))
+ return rv
branch = mtn.Branch(branch)
+ changed, new_starting_point = self.get_last_changes(branch, start_at, 10)
renderer.render('branchchanges.html',
- page_title="Branch %s" % branch,
- branch=branch)
+ page_title="Branch %s" % branch.name,
+ branch=branch,
+ display_revs=for_template(changed))
-class RevisionBrowse:
- def GET(self, revision):
- print "not implemented..."
-
class RevisionInfo:
def GET(self, revision):
revision = mtn.Revision(revision)
@@ -326,7 +402,7 @@ urls = (
'/revision/info/('+mtn.revision_re+')', 'RevisionInfo',
'/revision/tar/('+mtn.revision_re+')', 'RevisionTar',
- '/branch/changes/(.*)', 'BranchChanges',
+ '/branch/changes/(.*)()()', 'BranchChanges',
'/branch/head/(.*)', 'BranchHead',
'/branch/tar/(.*)', 'BranchTar',
'/static/(.*)', 'Static'