1 # HG changeset patch 2 # User Paul Boddie <paul@boddie.org.uk> 3 # Date 1337552405 -7200 4 # Node ID 6bf09cdbff531a07c2ccce0ee63baca33955608a 5 # Parent 99f369f5a8dbc192cd520aece8437f3182b1ac50 6 hgweb: make graph data suitable for template usage 7 8 Previously, graph data has been encoded for processing done by 9 JavaScript code run in the browser, employing simple structures 10 with implicit member positions. This patch modifies the graph 11 command to also produce data employing a dictionary-based 12 structure suitable for use with the templating mechanism, thus 13 permitting other ways of presenting repository graphs using that 14 mechanism. 15 16 In order to test these changes, the raw theme has been modified 17 to include templates for graph nodes and edges. In a similar 18 fashion, themes could employ technologies such as SVG that lend 19 themselves to templating to produce the graph display. This patch 20 makes use of a much simpler output representation than SVG in 21 order to maintain clarity. 22 23 diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/hgweb/webcommands.py 24 --- a/mercurial/hgweb/webcommands.py Tue May 15 07:01:35 2012 +0200 25 +++ b/mercurial/hgweb/webcommands.py Mon May 21 00:20:05 2012 +0200 26 @@ -784,28 +784,73 @@ 27 28 dag = graphmod.dagwalker(web.repo, range(startrev, downrev - 1, -1)) 29 tree = list(graphmod.colored(dag, web.repo)) 30 - canvasheight = (len(tree) + 1) * bg_height - 27 31 - data = [] 32 - for (id, type, ctx, vtx, edges) in tree: 33 - if type != graphmod.CHANGESET: 34 - continue 35 - node = str(ctx) 36 - age = templatefilters.age(ctx.date()) 37 - desc = templatefilters.firstline(ctx.description()) 38 - desc = cgi.escape(templatefilters.nonempty(desc)) 39 - user = cgi.escape(templatefilters.person(ctx.user())) 40 - branch = ctx.branch() 41 - try: 42 - branchnode = web.repo.branchtip(branch) 43 - except error.RepoLookupError: 44 - branchnode = None 45 - branch = branch, branchnode == ctx.node() 46 - data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(), 47 - ctx.bookmarks())) 48 49 + def getcolumns(tree): 50 + cols = 0 51 + for (id, type, ctx, vtx, edges) in tree: 52 + if type != graphmod.CHANGESET: 53 + continue 54 + cols = max(cols, max([edge[0] for edge in edges] or [0]), 55 + max([edge[1] for edge in edges] or [0])) 56 + return cols 57 + 58 + def graphdata(usetuples, **map): 59 + data = [] 60 + 61 + row = 0 62 + for (id, type, ctx, vtx, edges) in tree: 63 + if type != graphmod.CHANGESET: 64 + continue 65 + node = str(ctx) 66 + age = templatefilters.age(ctx.date()) 67 + desc = templatefilters.firstline(ctx.description()) 68 + desc = cgi.escape(templatefilters.nonempty(desc)) 69 + user = cgi.escape(templatefilters.person(ctx.user())) 70 + branch = ctx.branch() 71 + try: 72 + branchnode = web.repo.branchtip(branch) 73 + except error.RepoLookupError: 74 + branchnode = None 75 + branch = branch, branchnode == ctx.node() 76 + 77 + if usetuples: 78 + data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(), 79 + ctx.bookmarks())) 80 + else: 81 + edgedata = [dict(col=edge[0], nextcol=edge[1], 82 + color=(edge[2] - 1) % 6 + 1, 83 + width=edge[3], bcolor=edge[4]) for edge in edges] 84 + 85 + data.append(dict(node=node, 86 + col=vtx[0], 87 + color=(vtx[1] - 1) % 6 + 1, 88 + edges=edgedata, 89 + row=row, 90 + nextrow=row+1, 91 + desc=desc, 92 + user=user, 93 + age=age, 94 + bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()), 95 + branches=webutil.nodebranchdict(web.repo, ctx), 96 + inbranch=webutil.nodeinbranch(web.repo, ctx), 97 + tags=webutil.nodetagsdict(web.repo, ctx.node()))) 98 + 99 + row += 1 100 + 101 + return data 102 + 103 + cols = getcolumns(tree) 104 + rows = len(tree) 105 + canvasheight = (rows + 1) * bg_height - 27 106 + 107 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev, 108 lessvars=lessvars, morevars=morevars, downrev=downrev, 109 - canvasheight=canvasheight, jsdata=data, bg_height=bg_height, 110 + cols=cols, rows=rows, 111 + canvaswidth=(cols+1)*bg_height, 112 + truecanvasheight=rows*bg_height, 113 + canvasheight=canvasheight, bg_height=bg_height, 114 + jsdata=lambda **x: graphdata(True, **x), 115 + nodes=lambda **x: graphdata(False, **x), 116 node=revnode_hex, changenav=changenav) 117 118 def _getdoc(e): 119 diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graph.tmpl 120 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 121 +++ b/mercurial/templates/raw/graph.tmpl Mon May 21 00:20:05 2012 +0200 122 @@ -0,0 +1,6 @@ 123 +{header} 124 +# HG graph 125 +# Node ID {node} 126 +# Rows shown {rows} 127 + 128 +{nodes%graphnode} 129 diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graphedge.tmpl 130 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 131 +++ b/mercurial/templates/raw/graphedge.tmpl Mon May 21 00:20:05 2012 +0200 132 @@ -0,0 +1,1 @@ 133 +edge: ({col}, {row}) -> ({nextcol}, {nextrow}) (color {color}) 134 diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/graphnode.tmpl 135 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 136 +++ b/mercurial/templates/raw/graphnode.tmpl Mon May 21 00:20:05 2012 +0200 137 @@ -0,0 +1,7 @@ 138 +changeset: {node} 139 +user: {user} 140 +date: {age} 141 +summary: {desc} 142 +{branches%branchname}{tags%tagname}{bookmarks%bookmarkname} 143 +node: ({col}, {row}) (color {color}) 144 +{edges%graphedge} 145 diff -r 99f369f5a8db -r 6bf09cdbff53 mercurial/templates/raw/map 146 --- a/mercurial/templates/raw/map Tue May 15 07:01:35 2012 +0200 147 +++ b/mercurial/templates/raw/map Mon May 21 00:20:05 2012 +0200 148 @@ -28,3 +28,9 @@ 149 bookmarkentry = '{bookmark} {node}\n' 150 branches = '{entries%branchentry}' 151 branchentry = '{branch} {node} {status}\n' 152 +graph = graph.tmpl 153 +graphnode = graphnode.tmpl 154 +graphedge = graphedge.tmpl 155 +bookmarkname = 'bookmark: {name}\n' 156 +branchname = 'branch: {name}\n' 157 +tagname = 'tag: {name}\n' 158 diff -r 99f369f5a8db -r 6bf09cdbff53 tests/test-hgweb-commands.t 159 --- a/tests/test-hgweb-commands.t Tue May 15 07:01:35 2012 +0200 160 +++ b/tests/test-hgweb-commands.t Mon May 21 00:20:05 2012 +0200 161 @@ -1047,6 +1047,55 @@ 162 </body> 163 </html> 164 165 +raw graph 166 + 167 + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=raw' 168 + 200 Script output follows 169 + 170 + 171 + # HG graph 172 + # Node ID ba87b23d29ca67a305625d81a20ac279c1e3f444 173 + # Rows shown 4 174 + 175 + changeset: ba87b23d29ca 176 + user: test 177 + date: 1970-01-01 178 + summary: branch 179 + branch: unstable 180 + tag: tip 181 + bookmark: something 182 + 183 + node: (0, 0) (color 1) 184 + edge: (0, 0) -> (0, 1) (color 1) 185 + 186 + changeset: 1d22e65f027e 187 + user: test 188 + date: 1970-01-01 189 + summary: branch 190 + branch: stable 191 + 192 + node: (0, 1) (color 1) 193 + edge: (0, 1) -> (0, 2) (color 1) 194 + 195 + changeset: a4f92ed23982 196 + user: test 197 + date: 1970-01-01 198 + summary: Added tag 1.0 for changeset 2ef0ac749a14 199 + branch: default 200 + 201 + node: (0, 2) (color 1) 202 + edge: (0, 2) -> (0, 3) (color 1) 203 + 204 + changeset: 2ef0ac749a14 205 + user: test 206 + date: 1970-01-01 207 + summary: base 208 + tag: 1.0 209 + bookmark: anotherthing 210 + 211 + node: (0, 3) (color 1) 212 + 213 + 214 215 capabilities 216