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