##// END OF EJS Templates
graphlog: move common code into function again, change function types
Dirkjan Ochtman -
r9369:20140c24 default
parent child Browse files
Show More
@@ -1,380 +1,376 b''
1 # ASCII graph log extension for Mercurial
1 # ASCII graph log extension for Mercurial
2 #
2 #
3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net>
3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 '''command to view revision graphs from a shell
8 '''command to view revision graphs from a shell
9
9
10 This extension adds a --graph option to the incoming, outgoing and log
10 This extension adds a --graph option to the incoming, outgoing and log
11 commands. When this options is given, an ASCII representation of the
11 commands. When this options is given, an ASCII representation of the
12 revision graph is also shown.
12 revision graph is also shown.
13 '''
13 '''
14
14
15 import os, sys
15 import os, sys
16 from mercurial.cmdutil import revrange, show_changeset
16 from mercurial.cmdutil import revrange, show_changeset
17 from mercurial.commands import templateopts
17 from mercurial.commands import templateopts
18 from mercurial.i18n import _
18 from mercurial.i18n import _
19 from mercurial.node import nullrev
19 from mercurial.node import nullrev
20 from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
20 from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
21 from mercurial import hg, url, util, graphmod
21 from mercurial import hg, url, util, graphmod
22
22
23 ASCIIDATA = 'ASC'
23 ASCIIDATA = 'ASC'
24
24
25 def asciiformat(revdag, displayer, parents):
25 def asciiedges(seen, rev, parents):
26 """formats a changelog DAG walk for ASCII output"""
27 for (id, type, ctx, parentids) in revdag:
28 if type != graphmod.CHANGESET:
29 continue
30 displayer.show(ctx)
31 lines = displayer.hunk.pop(ctx.rev()).split('\n')[:-1]
32 char = ctx.node() in parents and '@' or 'o'
33 yield (id, ASCIIDATA, (char, lines), parentids)
34
35 def asciiedges(nodes):
36 """adds edge info to changelog DAG walk suitable for ascii()"""
26 """adds edge info to changelog DAG walk suitable for ascii()"""
37 seen = []
27 if rev not in seen:
38 for node, type, data, parents in nodes:
28 seen.append(rev)
39 if node not in seen:
29 nodeidx = seen.index(rev)
40 seen.append(node)
41 nodeidx = seen.index(node)
42
30
43 knownparents = []
31 knownparents = []
44 newparents = []
32 newparents = []
45 for parent in parents:
33 for parent in parents:
46 if parent in seen:
34 if parent in seen:
47 knownparents.append(parent)
35 knownparents.append(parent)
48 else:
36 else:
49 newparents.append(parent)
37 newparents.append(parent)
50
38
51 ncols = len(seen)
39 ncols = len(seen)
52 nextseen = seen[:]
40 seen[nodeidx:nodeidx + 1] = newparents
53 nextseen[nodeidx:nodeidx + 1] = newparents
41 edges = [(nodeidx, seen.index(p)) for p in knownparents]
54 edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
55
42
56 if len(newparents) > 0:
43 if len(newparents) > 0:
57 edges.append((nodeidx, nodeidx))
44 edges.append((nodeidx, nodeidx))
58 if len(newparents) > 1:
45 if len(newparents) > 1:
59 edges.append((nodeidx, nodeidx + 1))
46 edges.append((nodeidx, nodeidx + 1))
60 nmorecols = len(nextseen) - ncols
47
61 seen = nextseen
48 nmorecols = len(seen) - ncols
62 yield (nodeidx, type, data, edges, ncols, nmorecols)
49 return nodeidx, edges, ncols, nmorecols
63
50
64 def fix_long_right_edges(edges):
51 def fix_long_right_edges(edges):
65 for (i, (start, end)) in enumerate(edges):
52 for (i, (start, end)) in enumerate(edges):
66 if end > start:
53 if end > start:
67 edges[i] = (start, end + 1)
54 edges[i] = (start, end + 1)
68
55
69 def get_nodeline_edges_tail(
56 def get_nodeline_edges_tail(
70 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
57 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
71 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
58 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
72 # Still going in the same non-vertical direction.
59 # Still going in the same non-vertical direction.
73 if n_columns_diff == -1:
60 if n_columns_diff == -1:
74 start = max(node_index + 1, p_node_index)
61 start = max(node_index + 1, p_node_index)
75 tail = ["|", " "] * (start - node_index - 1)
62 tail = ["|", " "] * (start - node_index - 1)
76 tail.extend(["/", " "] * (n_columns - start))
63 tail.extend(["/", " "] * (n_columns - start))
77 return tail
64 return tail
78 else:
65 else:
79 return ["\\", " "] * (n_columns - node_index - 1)
66 return ["\\", " "] * (n_columns - node_index - 1)
80 else:
67 else:
81 return ["|", " "] * (n_columns - node_index - 1)
68 return ["|", " "] * (n_columns - node_index - 1)
82
69
83 def draw_edges(edges, nodeline, interline):
70 def draw_edges(edges, nodeline, interline):
84 for (start, end) in edges:
71 for (start, end) in edges:
85 if start == end + 1:
72 if start == end + 1:
86 interline[2 * end + 1] = "/"
73 interline[2 * end + 1] = "/"
87 elif start == end - 1:
74 elif start == end - 1:
88 interline[2 * start + 1] = "\\"
75 interline[2 * start + 1] = "\\"
89 elif start == end:
76 elif start == end:
90 interline[2 * start] = "|"
77 interline[2 * start] = "|"
91 else:
78 else:
92 nodeline[2 * end] = "+"
79 nodeline[2 * end] = "+"
93 if start > end:
80 if start > end:
94 (start, end) = (end, start)
81 (start, end) = (end, start)
95 for i in range(2 * start + 1, 2 * end):
82 for i in range(2 * start + 1, 2 * end):
96 if nodeline[i] != "+":
83 if nodeline[i] != "+":
97 nodeline[i] = "-"
84 nodeline[i] = "-"
98
85
99 def get_padding_line(ni, n_columns, edges):
86 def get_padding_line(ni, n_columns, edges):
100 line = []
87 line = []
101 line.extend(["|", " "] * ni)
88 line.extend(["|", " "] * ni)
102 if (ni, ni - 1) in edges or (ni, ni) in edges:
89 if (ni, ni - 1) in edges or (ni, ni) in edges:
103 # (ni, ni - 1) (ni, ni)
90 # (ni, ni - 1) (ni, ni)
104 # | | | | | | | |
91 # | | | | | | | |
105 # +---o | | o---+
92 # +---o | | o---+
106 # | | c | | c | |
93 # | | c | | c | |
107 # | |/ / | |/ /
94 # | |/ / | |/ /
108 # | | | | | |
95 # | | | | | |
109 c = "|"
96 c = "|"
110 else:
97 else:
111 c = " "
98 c = " "
112 line.extend([c, " "])
99 line.extend([c, " "])
113 line.extend(["|", " "] * (n_columns - ni - 1))
100 line.extend(["|", " "] * (n_columns - ni - 1))
114 return line
101 return line
115
102
116 def ascii(ui, dag):
103 def ascii(ui, dag):
117 """prints an ASCII graph of the DAG
104 """prints an ASCII graph of the DAG
118
105
119 dag is a generator that emits tuples with the following elements:
106 dag is a generator that emits tuples with the following elements:
120
107
121 - Column of the current node in the set of ongoing edges.
108 - Column of the current node in the set of ongoing edges.
122 - Type indicator of node data == ASCIIDATA.
109 - Type indicator of node data == ASCIIDATA.
123 - Payload: (char, lines):
110 - Payload: (char, lines):
124 - Character to use as node's symbol.
111 - Character to use as node's symbol.
125 - List of lines to display as the node's text.
112 - List of lines to display as the node's text.
126 - Edges; a list of (col, next_col) indicating the edges between
113 - Edges; a list of (col, next_col) indicating the edges between
127 the current node and its parents.
114 the current node and its parents.
128 - Number of columns (ongoing edges) in the current revision.
115 - Number of columns (ongoing edges) in the current revision.
129 - The difference between the number of columns (ongoing edges)
116 - The difference between the number of columns (ongoing edges)
130 in the next revision and the number of columns (ongoing edges)
117 in the next revision and the number of columns (ongoing edges)
131 in the current revision. That is: -1 means one column removed;
118 in the current revision. That is: -1 means one column removed;
132 0 means no columns added or removed; 1 means one column added.
119 0 means no columns added or removed; 1 means one column added.
133 """
120 """
134 prev_n_columns_diff = 0
121 prev_n_columns_diff = 0
135 prev_node_index = 0
122 prev_node_index = 0
136 for (node_index, type, (node_ch, node_lines), edges, n_columns, n_columns_diff) in dag:
123 for (node_index, type, (node_ch, node_lines), edges, n_columns, n_columns_diff) in dag:
137
124
138 assert -2 < n_columns_diff < 2
125 assert -2 < n_columns_diff < 2
139 if n_columns_diff == -1:
126 if n_columns_diff == -1:
140 # Transform
127 # Transform
141 #
128 #
142 # | | | | | |
129 # | | | | | |
143 # o | | into o---+
130 # o | | into o---+
144 # |X / |/ /
131 # |X / |/ /
145 # | | | |
132 # | | | |
146 fix_long_right_edges(edges)
133 fix_long_right_edges(edges)
147
134
148 # add_padding_line says whether to rewrite
135 # add_padding_line says whether to rewrite
149 #
136 #
150 # | | | | | | | |
137 # | | | | | | | |
151 # | o---+ into | o---+
138 # | o---+ into | o---+
152 # | / / | | | # <--- padding line
139 # | / / | | | # <--- padding line
153 # o | | | / /
140 # o | | | / /
154 # o | |
141 # o | |
155 add_padding_line = (len(node_lines) > 2 and
142 add_padding_line = (len(node_lines) > 2 and
156 n_columns_diff == -1 and
143 n_columns_diff == -1 and
157 [x for (x, y) in edges if x + 1 < y])
144 [x for (x, y) in edges if x + 1 < y])
158
145
159 # fix_nodeline_tail says whether to rewrite
146 # fix_nodeline_tail says whether to rewrite
160 #
147 #
161 # | | o | | | | o | |
148 # | | o | | | | o | |
162 # | | |/ / | | |/ /
149 # | | |/ / | | |/ /
163 # | o | | into | o / / # <--- fixed nodeline tail
150 # | o | | into | o / / # <--- fixed nodeline tail
164 # | |/ / | |/ /
151 # | |/ / | |/ /
165 # o | | o | |
152 # o | | o | |
166 fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line
153 fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line
167
154
168 # nodeline is the line containing the node character (typically o)
155 # nodeline is the line containing the node character (typically o)
169 nodeline = ["|", " "] * node_index
156 nodeline = ["|", " "] * node_index
170 nodeline.extend([node_ch, " "])
157 nodeline.extend([node_ch, " "])
171
158
172 nodeline.extend(
159 nodeline.extend(
173 get_nodeline_edges_tail(
160 get_nodeline_edges_tail(
174 node_index, prev_node_index, n_columns, n_columns_diff,
161 node_index, prev_node_index, n_columns, n_columns_diff,
175 prev_n_columns_diff, fix_nodeline_tail))
162 prev_n_columns_diff, fix_nodeline_tail))
176
163
177 # shift_interline is the line containing the non-vertical
164 # shift_interline is the line containing the non-vertical
178 # edges between this entry and the next
165 # edges between this entry and the next
179 shift_interline = ["|", " "] * node_index
166 shift_interline = ["|", " "] * node_index
180 if n_columns_diff == -1:
167 if n_columns_diff == -1:
181 n_spaces = 1
168 n_spaces = 1
182 edge_ch = "/"
169 edge_ch = "/"
183 elif n_columns_diff == 0:
170 elif n_columns_diff == 0:
184 n_spaces = 2
171 n_spaces = 2
185 edge_ch = "|"
172 edge_ch = "|"
186 else:
173 else:
187 n_spaces = 3
174 n_spaces = 3
188 edge_ch = "\\"
175 edge_ch = "\\"
189 shift_interline.extend(n_spaces * [" "])
176 shift_interline.extend(n_spaces * [" "])
190 shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
177 shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
191
178
192 # draw edges from the current node to its parents
179 # draw edges from the current node to its parents
193 draw_edges(edges, nodeline, shift_interline)
180 draw_edges(edges, nodeline, shift_interline)
194
181
195 # lines is the list of all graph lines to print
182 # lines is the list of all graph lines to print
196 lines = [nodeline]
183 lines = [nodeline]
197 if add_padding_line:
184 if add_padding_line:
198 lines.append(get_padding_line(node_index, n_columns, edges))
185 lines.append(get_padding_line(node_index, n_columns, edges))
199 lines.append(shift_interline)
186 lines.append(shift_interline)
200
187
201 # make sure that there are as many graph lines as there are
188 # make sure that there are as many graph lines as there are
202 # log strings
189 # log strings
203 while len(node_lines) < len(lines):
190 while len(node_lines) < len(lines):
204 node_lines.append("")
191 node_lines.append("")
205 if len(lines) < len(node_lines):
192 if len(lines) < len(node_lines):
206 extra_interline = ["|", " "] * (n_columns + n_columns_diff)
193 extra_interline = ["|", " "] * (n_columns + n_columns_diff)
207 while len(lines) < len(node_lines):
194 while len(lines) < len(node_lines):
208 lines.append(extra_interline)
195 lines.append(extra_interline)
209
196
210 # print lines
197 # print lines
211 indentation_level = max(n_columns, n_columns + n_columns_diff)
198 indentation_level = max(n_columns, n_columns + n_columns_diff)
212 for (line, logstr) in zip(lines, node_lines):
199 for (line, logstr) in zip(lines, node_lines):
213 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
200 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
214 ui.write(ln.rstrip() + '\n')
201 ui.write(ln.rstrip() + '\n')
215
202
216 # ... and start over
203 # ... and start over
217 prev_node_index = node_index
204 prev_node_index = node_index
218 prev_n_columns_diff = n_columns_diff
205 prev_n_columns_diff = n_columns_diff
219
206
220 def get_revs(repo, rev_opt):
207 def get_revs(repo, rev_opt):
221 if rev_opt:
208 if rev_opt:
222 revs = revrange(repo, rev_opt)
209 revs = revrange(repo, rev_opt)
223 return (max(revs), min(revs))
210 return (max(revs), min(revs))
224 else:
211 else:
225 return (len(repo) - 1, 0)
212 return (len(repo) - 1, 0)
226
213
227 def check_unsupported_flags(opts):
214 def check_unsupported_flags(opts):
228 for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
215 for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
229 "only_merges", "user", "only_branch", "prune", "newest_first",
216 "only_merges", "user", "only_branch", "prune", "newest_first",
230 "no_merges", "include", "exclude"]:
217 "no_merges", "include", "exclude"]:
231 if op in opts and opts[op]:
218 if op in opts and opts[op]:
232 raise util.Abort(_("--graph option is incompatible with --%s") % op)
219 raise util.Abort(_("--graph option is incompatible with --%s") % op)
233
220
221 def generate(dag, displayer, showparents, edgefn):
222 seen = []
223 for rev, type, ctx, parents in dag:
224 char = ctx.node() in showparents and '@' or 'o'
225 displayer.show(ctx)
226 lines = displayer.hunk.pop(rev).split('\n')[:-1]
227 cols = edgefn(seen, rev, parents)
228 yield cols[0], type, (char, lines), cols[1], cols[2], cols[3]
229
234 def graphlog(ui, repo, path=None, **opts):
230 def graphlog(ui, repo, path=None, **opts):
235 """show revision history alongside an ASCII revision graph
231 """show revision history alongside an ASCII revision graph
236
232
237 Print a revision history alongside a revision graph drawn with
233 Print a revision history alongside a revision graph drawn with
238 ASCII characters.
234 ASCII characters.
239
235
240 Nodes printed as an @ character are parents of the working
236 Nodes printed as an @ character are parents of the working
241 directory.
237 directory.
242 """
238 """
243
239
244 check_unsupported_flags(opts)
240 check_unsupported_flags(opts)
245 limit = cmdutil.loglimit(opts)
241 limit = cmdutil.loglimit(opts)
246 start, stop = get_revs(repo, opts["rev"])
242 start, stop = get_revs(repo, opts["rev"])
247 stop = max(stop, start - limit + 1)
243 stop = max(stop, start - limit + 1)
248 if start == nullrev:
244 if start == nullrev:
249 return
245 return
250
246
251 if path:
247 if path:
252 path = util.canonpath(repo.root, os.getcwd(), path)
248 path = util.canonpath(repo.root, os.getcwd(), path)
253 if path: # could be reset in canonpath
249 if path: # could be reset in canonpath
254 revdag = graphmod.filerevs(repo, path, start, stop)
250 revdag = graphmod.filerevs(repo, path, start, stop)
255 else:
251 else:
256 revdag = graphmod.revisions(repo, start, stop)
252 revdag = graphmod.revisions(repo, start, stop)
257
253
258 displayer = show_changeset(ui, repo, opts, buffered=True)
254 displayer = show_changeset(ui, repo, opts, buffered=True)
259 showparents = [ctx.node() for ctx in repo[None].parents()]
255 showparents = [ctx.node() for ctx in repo[None].parents()]
260 fmtdag = asciiformat(revdag, displayer, showparents)
256 gen = generate(revdag, displayer, showparents, asciiedges)
261 ascii(ui, asciiedges(fmtdag))
257 ascii(ui, gen)
262
258
263 def graphrevs(repo, nodes, opts):
259 def graphrevs(repo, nodes, opts):
264 limit = cmdutil.loglimit(opts)
260 limit = cmdutil.loglimit(opts)
265 nodes.reverse()
261 nodes.reverse()
266 if limit < sys.maxint:
262 if limit < sys.maxint:
267 nodes = nodes[:limit]
263 nodes = nodes[:limit]
268 return graphmod.nodes(repo, nodes)
264 return graphmod.nodes(repo, nodes)
269
265
270 def goutgoing(ui, repo, dest=None, **opts):
266 def goutgoing(ui, repo, dest=None, **opts):
271 """show the outgoing changesets alongside an ASCII revision graph
267 """show the outgoing changesets alongside an ASCII revision graph
272
268
273 Print the outgoing changesets alongside a revision graph drawn with
269 Print the outgoing changesets alongside a revision graph drawn with
274 ASCII characters.
270 ASCII characters.
275
271
276 Nodes printed as an @ character are parents of the working
272 Nodes printed as an @ character are parents of the working
277 directory.
273 directory.
278 """
274 """
279
275
280 check_unsupported_flags(opts)
276 check_unsupported_flags(opts)
281 dest, revs, checkout = hg.parseurl(
277 dest, revs, checkout = hg.parseurl(
282 ui.expandpath(dest or 'default-push', dest or 'default'),
278 ui.expandpath(dest or 'default-push', dest or 'default'),
283 opts.get('rev'))
279 opts.get('rev'))
284 if revs:
280 if revs:
285 revs = [repo.lookup(rev) for rev in revs]
281 revs = [repo.lookup(rev) for rev in revs]
286 other = hg.repository(cmdutil.remoteui(ui, opts), dest)
282 other = hg.repository(cmdutil.remoteui(ui, opts), dest)
287 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
283 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
288 o = repo.findoutgoing(other, force=opts.get('force'))
284 o = repo.findoutgoing(other, force=opts.get('force'))
289 if not o:
285 if not o:
290 ui.status(_("no changes found\n"))
286 ui.status(_("no changes found\n"))
291 return
287 return
292
288
293 o = repo.changelog.nodesbetween(o, revs)[0]
289 o = repo.changelog.nodesbetween(o, revs)[0]
294 revdag = graphrevs(repo, o, opts)
290 revdag = graphrevs(repo, o, opts)
295 displayer = show_changeset(ui, repo, opts, buffered=True)
291 displayer = show_changeset(ui, repo, opts, buffered=True)
296 showparents = [ctx.node() for ctx in repo[None].parents()]
292 showparents = [ctx.node() for ctx in repo[None].parents()]
297 fmtdag = asciiformat(revdag, displayer, showparents)
293 gen = generate(revdag, displayer, showparents, asciiedges)
298 ascii(ui, asciiedges(fmtdag))
294 ascii(ui, gen)
299
295
300 def gincoming(ui, repo, source="default", **opts):
296 def gincoming(ui, repo, source="default", **opts):
301 """show the incoming changesets alongside an ASCII revision graph
297 """show the incoming changesets alongside an ASCII revision graph
302
298
303 Print the incoming changesets alongside a revision graph drawn with
299 Print the incoming changesets alongside a revision graph drawn with
304 ASCII characters.
300 ASCII characters.
305
301
306 Nodes printed as an @ character are parents of the working
302 Nodes printed as an @ character are parents of the working
307 directory.
303 directory.
308 """
304 """
309
305
310 check_unsupported_flags(opts)
306 check_unsupported_flags(opts)
311 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
307 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
312 other = hg.repository(cmdutil.remoteui(repo, opts), source)
308 other = hg.repository(cmdutil.remoteui(repo, opts), source)
313 ui.status(_('comparing with %s\n') % url.hidepassword(source))
309 ui.status(_('comparing with %s\n') % url.hidepassword(source))
314 if revs:
310 if revs:
315 revs = [other.lookup(rev) for rev in revs]
311 revs = [other.lookup(rev) for rev in revs]
316 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
312 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
317 if not incoming:
313 if not incoming:
318 try:
314 try:
319 os.unlink(opts["bundle"])
315 os.unlink(opts["bundle"])
320 except:
316 except:
321 pass
317 pass
322 ui.status(_("no changes found\n"))
318 ui.status(_("no changes found\n"))
323 return
319 return
324
320
325 cleanup = None
321 cleanup = None
326 try:
322 try:
327
323
328 fname = opts["bundle"]
324 fname = opts["bundle"]
329 if fname or not other.local():
325 if fname or not other.local():
330 # create a bundle (uncompressed if other repo is not local)
326 # create a bundle (uncompressed if other repo is not local)
331 if revs is None:
327 if revs is None:
332 cg = other.changegroup(incoming, "incoming")
328 cg = other.changegroup(incoming, "incoming")
333 else:
329 else:
334 cg = other.changegroupsubset(incoming, revs, 'incoming')
330 cg = other.changegroupsubset(incoming, revs, 'incoming')
335 bundletype = other.local() and "HG10BZ" or "HG10UN"
331 bundletype = other.local() and "HG10BZ" or "HG10UN"
336 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
332 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
337 # keep written bundle?
333 # keep written bundle?
338 if opts["bundle"]:
334 if opts["bundle"]:
339 cleanup = None
335 cleanup = None
340 if not other.local():
336 if not other.local():
341 # use the created uncompressed bundlerepo
337 # use the created uncompressed bundlerepo
342 other = bundlerepo.bundlerepository(ui, repo.root, fname)
338 other = bundlerepo.bundlerepository(ui, repo.root, fname)
343
339
344 chlist = other.changelog.nodesbetween(incoming, revs)[0]
340 chlist = other.changelog.nodesbetween(incoming, revs)[0]
345 revdag = graphrevs(other, chlist, opts)
341 revdag = graphrevs(other, chlist, opts)
346 displayer = show_changeset(ui, other, opts, buffered=True)
342 displayer = show_changeset(ui, other, opts, buffered=True)
347 showparents = [ctx.node() for ctx in repo[None].parents()]
343 showparents = [ctx.node() for ctx in repo[None].parents()]
348 fmtdag = asciiformat(revdag, displayer, showparents)
344 gen = generate(revdag, displayer, showparents, asciiedges)
349 ascii(ui, asciiedges(fmtdag))
345 ascii(ui, gen)
350
346
351 finally:
347 finally:
352 if hasattr(other, 'close'):
348 if hasattr(other, 'close'):
353 other.close()
349 other.close()
354 if cleanup:
350 if cleanup:
355 os.unlink(cleanup)
351 os.unlink(cleanup)
356
352
357 def uisetup(ui):
353 def uisetup(ui):
358 '''Initialize the extension.'''
354 '''Initialize the extension.'''
359 _wrapcmd(ui, 'log', commands.table, graphlog)
355 _wrapcmd(ui, 'log', commands.table, graphlog)
360 _wrapcmd(ui, 'incoming', commands.table, gincoming)
356 _wrapcmd(ui, 'incoming', commands.table, gincoming)
361 _wrapcmd(ui, 'outgoing', commands.table, goutgoing)
357 _wrapcmd(ui, 'outgoing', commands.table, goutgoing)
362
358
363 def _wrapcmd(ui, cmd, table, wrapfn):
359 def _wrapcmd(ui, cmd, table, wrapfn):
364 '''wrap the command'''
360 '''wrap the command'''
365 def graph(orig, *args, **kwargs):
361 def graph(orig, *args, **kwargs):
366 if kwargs['graph']:
362 if kwargs['graph']:
367 return wrapfn(*args, **kwargs)
363 return wrapfn(*args, **kwargs)
368 return orig(*args, **kwargs)
364 return orig(*args, **kwargs)
369 entry = extensions.wrapcommand(table, cmd, graph)
365 entry = extensions.wrapcommand(table, cmd, graph)
370 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
366 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
371
367
372 cmdtable = {
368 cmdtable = {
373 "glog":
369 "glog":
374 (graphlog,
370 (graphlog,
375 [('l', 'limit', '', _('limit number of changes displayed')),
371 [('l', 'limit', '', _('limit number of changes displayed')),
376 ('p', 'patch', False, _('show patch')),
372 ('p', 'patch', False, _('show patch')),
377 ('r', 'rev', [], _('show the specified revision or range')),
373 ('r', 'rev', [], _('show the specified revision or range')),
378 ] + templateopts,
374 ] + templateopts,
379 _('hg glog [OPTION]... [FILE]')),
375 _('hg glog [OPTION]... [FILE]')),
380 }
376 }
General Comments 0
You need to be logged in to leave comments. Login now