#
#
# patch "config.py"
# from [873667db24c6715f19d6a23c9c39b46d42b3b2af]
# to [ec1da48608a688595fedb41cf4600a3d9d0699e7]
#
# patch "monotone.py"
# from [db94b133c60582cc38327251327147bcf5f2f461]
# to [bbcdd36f0094c2e02895fa0aaa28ddf97fe51b3d]
#
# patch "revision.psp"
# from [65c3b846ff13c46662f9ed4f1aafb3017181e354]
# to [3dc4b749e678a9c194796deccb322c3ed0338c2b]
#
============================================================
--- config.py 873667db24c6715f19d6a23c9c39b46d42b3b2af
+++ config.py ec1da48608a688595fedb41cf4600a3d9d0699e7
@@ -1,7 +1,9 @@
import sys
sys.path.append('/home/grahame/monotone/goatpy')
monotone = '/opt/monotone/bin/monotone'
dbfile = '/home/grahame/public_html/viewmtn/viewmtn.db'
+graphdir = '/home/grahame/public_html/viewmtn/graph/'
+graphuri = 'graph/'
============================================================
--- monotone.py db94b133c60582cc38327251327147bcf5f2f461
+++ monotone.py bbcdd36f0094c2e02895fa0aaa28ddf97fe51b3d
@@ -1,7 +1,10 @@
from goatpy import utility
+import urllib
import pipes
+import sets
import re
+import os
#
# a python wrapper for the "monotone" command
@@ -113,6 +116,39 @@
entry[attr].append(value)
if entry: rv.append(entry)
return rv
+ def ancestry_graph(self, graphdir, graphuri, id, limit=0):
+ rv = {
+ 'dot_file' : os.path.join(graphdir, id + ".dot"),
+ 'image_file' : os.path.join(graphdir, id + ".png"),
+ 'imagemap_file' : os.path.join(graphdir, id + ".html"),
+ 'dot_uri' : "%s/%s.dot" % (graphuri, urllib.quote(id)),
+ 'image_uri' : "%s/%s.png" % (graphuri, urllib.quote(id)),
+ 'imagemap_uri' : "%s/%s.html" % (graphuri, urllib.quote(id)),
+ }
+ missing = filter(lambda x: x != True, map(lambda x: os.access(x, os.R_OK), rv.values()))
+ if len(missing) == 0:
+ rv['cached'] = True
+ return rv
+ contents = """
+ graph ancestry {
+ """
+ revisions = sets.Set()
+ for attrs in self.ancestry(id, limit):
+ if not attrs.has_key("Revision") or not attrs.has_key("Ancestor"):
+ continue
+ revision = attrs['Revision'][0]
+ revisions.add(revision)
+ for ancestor in attrs['Ancestor']:
+ if len(ancestor) == 0: continue
+ revisions.add(ancestor)
+ contents += '"%s"--"%s"\n' % (revision, ancestor)
+ for revision in revisions:
+ contents += '"%s" [fontsize=8,shape=square,href="revision.psp?id=%s"]\n' % (revision, urllib.quote(revision))
+ contents += "}\n"
+ open(rv['dot_file'], 'w').write(contents)
+ os.system("/usr/bin/dot -Tcmapx -o %s -Tpng -o %s %s" % (pipes.quote(rv['imagemap_file']), rv['image_file'], rv['dot_file']))
+ rv['cached'] = False
+ return rv
def is_valid_id(s):
return len(s) == 40 and id_re.match(s) != None
============================================================
--- revision.psp 65c3b846ff13c46662f9ed4f1aafb3017181e354
+++ revision.psp 3dc4b749e678a9c194796deccb322c3ed0338c2b
@@ -8,6 +8,7 @@
from template import header,footer
from monotone import Monotone
+reload(config)
reload(common)
reload(template)
reload(monotone)
@@ -31,20 +32,25 @@
info = {'title' : "Revision %s" % (hq(id))}
req.write(header(info))
+ancestry_graph = mt.ancestry_graph(config.graphdir, config.graphuri, id, 20)
+req.write(open(ancestry_graph['imagemap_file']).read())
+
%>
+
+
| Signed by | Name | Value | ||
|---|---|---|---|---|
| <%="%s (%s)" % (hq(cert.get('Key', '')), hq(cert.get('Sig', '')))%> | -<%=hq(cert.get("Name", ''))%> | -<%=hq(cert.get("Value", ''))%> | +<%=hq(cert.get("Name", ''))%> + | <%=hq(cert.get("Value", ''))%> | +