[PATCH] hgweb: make graph data suitable for template usage

Paul Boddie paul at boddie.org.uk
Sun May 20 17:25:32 CDT 2012


# HG changeset patch
# User Paul Boddie <paul at boddie.org.uk>
# Date 1337552405 -7200
# Node ID 6bf09cdbff531a07c2ccce0ee63baca33955608a
# Parent  99f369f5a8dbc192cd520aece8437f3182b1ac50
hgweb: make graph data suitable for template usage

Previously, graph data has been encoded for processing done by
JavaScript code run in the browser, employing simple structures
with implicit member positions. This patch modifies the graph
command to also produce data employing a dictionary-based
structure suitable for use with the templating mechanism, thus
permitting other ways of presenting repository graphs using that
mechanism.

In order to test these changes, the raw theme has been modified
to include templates for graph nodes and edges. In a similar
fashion, themes could employ technologies such as SVG that lend
themselves to templating to produce the graph display. This patch
makes use of a much simpler output representation than SVG in
order to maintain clarity.

diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py	Tue May 15 07:01:35 2012 +0200
+++ b/mercurial/hgweb/webcommands.py	Mon May 21 00:20:05 2012 +0200
@@ -784,28 +784,73 @@
 
     dag = graphmod.dagwalker(web.repo, range(startrev, downrev - 1, -1))
     tree = list(graphmod.colored(dag, web.repo))
-    canvasheight = (len(tree) + 1) * bg_height - 27
-    data = []
-    for (id, type, ctx, vtx, edges) in tree:
-        if type != graphmod.CHANGESET:
-            continue
-        node = str(ctx)
-        age = templatefilters.age(ctx.date())
-        desc = templatefilters.firstline(ctx.description())
-        desc = cgi.escape(templatefilters.nonempty(desc))
-        user = cgi.escape(templatefilters.person(ctx.user()))
-        branch = ctx.branch()
-        try:
-            branchnode = web.repo.branchtip(branch)
-        except error.RepoLookupError:
-            branchnode = None
-        branch = branch, branchnode == ctx.node()
-        data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(),
-                     ctx.bookmarks()))
 
+    def getcolumns(tree):
+        cols = 0
+        for (id, type, ctx, vtx, edges) in tree:
+            if type != graphmod.CHANGESET:
+                continue
+            cols = max(cols, max([edge[0] for edge in edges] or [0]),
+                             max([edge[1] for edge in edges] or [0]))
+        return cols
+ 
+    def graphdata(usetuples, **map):
+        data = []
+ 
+        row = 0
+        for (id, type, ctx, vtx, edges) in tree:
+            if type != graphmod.CHANGESET:
+                continue
+            node = str(ctx)
+            age = templatefilters.age(ctx.date())
+            desc = templatefilters.firstline(ctx.description())
+            desc = cgi.escape(templatefilters.nonempty(desc))
+            user = cgi.escape(templatefilters.person(ctx.user()))
+            branch = ctx.branch()
+            try:
+                branchnode = web.repo.branchtip(branch)
+            except error.RepoLookupError:
+                branchnode = None
+            branch = branch, branchnode == ctx.node()
+
+            if usetuples:
+                data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(),
+                             ctx.bookmarks()))
+            else:
+                edgedata = [dict(col=edge[0], nextcol=edge[1],
+                                 color=(edge[2] - 1) % 6 + 1,
+                                 width=edge[3], bcolor=edge[4]) for edge in edges]
+ 
+                data.append(dict(node=node,
+                                 col=vtx[0],
+                                 color=(vtx[1] - 1) % 6 + 1,
+                                 edges=edgedata,
+                                 row=row,
+                                 nextrow=row+1,
+                                 desc=desc,
+                                 user=user,
+                                 age=age,
+                                 bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()),
+                                 branches=webutil.nodebranchdict(web.repo, ctx),
+                                 inbranch=webutil.nodeinbranch(web.repo, ctx),
+                                 tags=webutil.nodetagsdict(web.repo, ctx.node())))
+ 
+            row += 1
+ 
+        return data
+
+    cols = getcolumns(tree)
+    rows = len(tree)
+    canvasheight = (rows + 1) * bg_height - 27
+  
     return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
                 lessvars=lessvars, morevars=morevars, downrev=downrev,
-                canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
+                cols=cols, rows=rows,
+                canvaswidth=(cols+1)*bg_height,
+                truecanvasheight=rows*bg_height,
+                canvasheight=canvasheight, bg_height=bg_height,
+                jsdata=lambda **x: graphdata(True, **x),
+                nodes=lambda **x: graphdata(False, **x),
                 node=revnode_hex, changenav=changenav)
 
 def _getdoc(e):
diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graph.tmpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/templates/raw/graph.tmpl	Mon May 21 00:20:05 2012 +0200
@@ -0,0 +1,6 @@
+{header}
+# HG graph
+# Node ID {node}
+# Rows shown {rows}
+
+{nodes%graphnode}
diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graphedge.tmpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/templates/raw/graphedge.tmpl	Mon May 21 00:20:05 2012 +0200
@@ -0,0 +1,1 @@
+edge:        ({col}, {row}) -> ({nextcol}, {nextrow}) (color {color})
diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graphnode.tmpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/templates/raw/graphnode.tmpl	Mon May 21 00:20:05 2012 +0200
@@ -0,0 +1,7 @@
+changeset:   {node}
+user:        {user}
+date:        {age}
+summary:     {desc}
+{branches%branchname}{tags%tagname}{bookmarks%bookmarkname}
+node:        ({col}, {row}) (color {color})
+{edges%graphedge}
diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/map
--- a/mercurial/templates/raw/map	Tue May 15 07:01:35 2012 +0200
+++ b/mercurial/templates/raw/map	Mon May 21 00:20:05 2012 +0200
@@ -28,3 +28,9 @@
 bookmarkentry = '{bookmark}	{node}\n'
 branches = '{entries%branchentry}'
 branchentry = '{branch}	{node}	{status}\n'
+graph = graph.tmpl
+graphnode = graphnode.tmpl
+graphedge = graphedge.tmpl
+bookmarkname = 'bookmark:    {name}\n'
+branchname = 'branch:      {name}\n'
+tagname = 'tag:         {name}\n'
diff -r 99f369f5a8db -r 6bf09cdbff53 tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t	Tue May 15 07:01:35 2012 +0200
+++ b/tests/test-hgweb-commands.t	Mon May 21 00:20:05 2012 +0200
@@ -1047,6 +1047,55 @@
   </body>
   </html>
   
+raw graph
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=raw'
+  200 Script output follows
+  
+  
+  # HG graph
+  # Node ID ba87b23d29ca67a305625d81a20ac279c1e3f444
+  # Rows shown 4
+  
+  changeset:   ba87b23d29ca
+  user:        test
+  date:        1970-01-01
+  summary:     branch
+  branch:      unstable
+  tag:         tip
+  bookmark:    something
+  
+  node:        (0, 0) (color 1)
+  edge:        (0, 0) -> (0, 1) (color 1)
+  
+  changeset:   1d22e65f027e
+  user:        test
+  date:        1970-01-01
+  summary:     branch
+  branch:      stable
+  
+  node:        (0, 1) (color 1)
+  edge:        (0, 1) -> (0, 2) (color 1)
+  
+  changeset:   a4f92ed23982
+  user:        test
+  date:        1970-01-01
+  summary:     Added tag 1.0 for changeset 2ef0ac749a14
+  branch:      default
+  
+  node:        (0, 2) (color 1)
+  edge:        (0, 2) -> (0, 3) (color 1)
+  
+  changeset:   2ef0ac749a14
+  user:        test
+  date:        1970-01-01
+  summary:     base
+  tag:         1.0
+  bookmark:    anotherthing
+  
+  node:        (0, 3) (color 1)
+  
+  
 
 capabilities
 


More information about the Mercurial-devel mailing list