comparison hgext/graphlog.py @ 7325:f9985108d4e4

graphlog: split the actual DAG grapher out into a separate method This allows extensions like pbranch to use asciigraph() to graph dependencies for patch branches, but could be used for basically any DAG.
author Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
date Fri, 07 Nov 2008 10:37:20 +0100
parents 3a2cbf68e2f1
children ba7ab8c4a577
comparison
equal deleted inserted replaced
7324:3a2cbf68e2f1 7325:f9985108d4e4
196 revs = revrange(repo, rev_opt) 196 revs = revrange(repo, rev_opt)
197 return (max(revs), min(revs)) 197 return (max(revs), min(revs))
198 else: 198 else:
199 return (len(repo) - 1, 0) 199 return (len(repo) - 1, 0)
200 200
201 def graphlog(ui, repo, path=None, **opts): 201 def ascii(ui, grapher):
202 """show revision history alongside an ASCII revision graph 202 """prints an ASCII graph of the DAG returned by the grapher
203 203
204 Print a revision history alongside a revision graph drawn with 204 grapher is a generator that emits tuples with the following elements:
205 ASCII characters. 205
206 206 - Character to use as node's symbol.
207 Nodes printed as an @ character are parents of the working 207 - List of lines to display as the node's text.
208 directory. 208 - Column of the current node in the set of ongoing edges.
209 - Edges; a list of (col, next_col) indicating the edges between
210 the current node and its parents.
211 - Number of columns (ongoing edges) in the current revision.
212 - The difference between the number of columns (ongoing edges)
213 in the next revision and the number of columns (ongoing edges)
214 in the current revision. That is: -1 means one column removed;
215 0 means no columns added or removed; 1 means one column added.
209 """ 216 """
210
211 limit = get_limit(opts["limit"])
212 (start_rev, stop_rev) = get_revs(repo, opts["rev"])
213 stop_rev = max(stop_rev, start_rev - limit + 1)
214 if start_rev == nullrev:
215 return
216 cs_printer = show_changeset(ui, repo, opts)
217 if path:
218 path = canonpath(repo.root, os.getcwd(), path)
219 if path:
220 grapher = filelog_grapher(repo, path, start_rev, stop_rev)
221 else:
222 grapher = revision_grapher(repo, start_rev, stop_rev)
223 repo_parents = repo.dirstate.parents()
224 prev_n_columns_diff = 0 217 prev_n_columns_diff = 0
225 prev_node_index = 0 218 prev_node_index = 0
226 219 for (node_ch, node_lines, node_index, edges, n_columns, n_columns_diff) in grapher:
227 for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher:
228 # node_lines is the list of all text lines to draw alongside the graph 220 # node_lines is the list of all text lines to draw alongside the graph
229 ui.pushbuffer()
230 cs_printer.show(rev, node)
231 node_lines = ui.popbuffer().split("\n")[:-1]
232 221
233 if n_columns_diff == -1: 222 if n_columns_diff == -1:
234 # Transform 223 # Transform
235 # 224 #
236 # | | | | | | 225 # | | | | | |
259 # o | | o | | 248 # o | | o | |
260 fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line 249 fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line
261 250
262 # nodeline is the line containing the node character (typically o) 251 # nodeline is the line containing the node character (typically o)
263 nodeline = ["|", " "] * node_index 252 nodeline = ["|", " "] * node_index
264 if node in repo_parents:
265 node_ch = "@"
266 else:
267 node_ch = "o"
268 nodeline.extend([node_ch, " "]) 253 nodeline.extend([node_ch, " "])
269 254
270 nodeline.extend( 255 nodeline.extend(
271 get_nodeline_edges_tail( 256 get_nodeline_edges_tail(
272 node_index, prev_node_index, n_columns, n_columns_diff, 257 node_index, prev_node_index, n_columns, n_columns_diff,
312 297
313 # ... and start over 298 # ... and start over
314 prev_node_index = node_index 299 prev_node_index = node_index
315 prev_n_columns_diff = n_columns_diff 300 prev_n_columns_diff = n_columns_diff
316 301
302 def graphlog(ui, repo, path=None, **opts):
303 """show revision history alongside an ASCII revision graph
304
305 Print a revision history alongside a revision graph drawn with
306 ASCII characters.
307
308 Nodes printed as an @ character are parents of the working
309 directory.
310 """
311
312 limit = get_limit(opts["limit"])
313 (start_rev, stop_rev) = get_revs(repo, opts["rev"])
314 stop_rev = max(stop_rev, start_rev - limit + 1)
315 if start_rev == nullrev:
316 return
317 if path:
318 path = canonpath(repo.root, os.getcwd(), path)
319 if path:
320 revgrapher = filelog_grapher(repo, path, start_rev, stop_rev)
321 else:
322 revgrapher = revision_grapher(repo, start_rev, stop_rev)
323
324 repo_parents = repo.dirstate.parents()
325 cs_printer = show_changeset(ui, repo, opts)
326 def grapher():
327 for (rev, node, node_index, edges, n_columns, n_columns_diff) in revgrapher:
328 # log_strings is the list of all log strings to draw alongside
329 # the graph.
330 ui.pushbuffer()
331 cs_printer.show(rev, node)
332 log_strings = ui.popbuffer().split("\n")[:-1]
333 if node in repo_parents:
334 node_ch = "@"
335 else:
336 node_ch = "o"
337 yield (node_ch, log_strings, node_index, edges, n_columns, n_columns_diff)
338
339 ascii(ui, grapher())
340
317 cmdtable = { 341 cmdtable = {
318 "glog": 342 "glog":
319 (graphlog, 343 (graphlog,
320 [('l', 'limit', '', _('limit number of changes displayed')), 344 [('l', 'limit', '', _('limit number of changes displayed')),
321 ('p', 'patch', False, _('show patch')), 345 ('p', 'patch', False, _('show patch')),