##// END OF EJS Templates
graphlog: fix --follow-first --rev combinations...
Patrick Mezard -
r16409:2cbd7dd0 default
parent child Browse files
Show More
@@ -1,551 +1,553 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 or any later version.
6 # GNU General Public License version 2 or any later version.
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 from mercurial.cmdutil import show_changeset
15 from mercurial.cmdutil import show_changeset
16 from mercurial.commands import templateopts
16 from mercurial.commands import templateopts
17 from mercurial.i18n import _
17 from mercurial.i18n import _
18 from mercurial.node import nullrev
18 from mercurial.node import nullrev
19 from mercurial import cmdutil, commands, extensions, scmutil
19 from mercurial import cmdutil, commands, extensions, scmutil
20 from mercurial import hg, util, graphmod, templatekw
20 from mercurial import hg, util, graphmod, templatekw
21 from mercurial import revset as revsetmod
21 from mercurial import revset as revsetmod
22
22
23 cmdtable = {}
23 cmdtable = {}
24 command = cmdutil.command(cmdtable)
24 command = cmdutil.command(cmdtable)
25
25
26 ASCIIDATA = 'ASC'
26 ASCIIDATA = 'ASC'
27
27
28 def asciiedges(type, char, lines, seen, rev, parents):
28 def asciiedges(type, char, lines, seen, rev, parents):
29 """adds edge info to changelog DAG walk suitable for ascii()"""
29 """adds edge info to changelog DAG walk suitable for ascii()"""
30 if rev not in seen:
30 if rev not in seen:
31 seen.append(rev)
31 seen.append(rev)
32 nodeidx = seen.index(rev)
32 nodeidx = seen.index(rev)
33
33
34 knownparents = []
34 knownparents = []
35 newparents = []
35 newparents = []
36 for parent in parents:
36 for parent in parents:
37 if parent in seen:
37 if parent in seen:
38 knownparents.append(parent)
38 knownparents.append(parent)
39 else:
39 else:
40 newparents.append(parent)
40 newparents.append(parent)
41
41
42 ncols = len(seen)
42 ncols = len(seen)
43 nextseen = seen[:]
43 nextseen = seen[:]
44 nextseen[nodeidx:nodeidx + 1] = newparents
44 nextseen[nodeidx:nodeidx + 1] = newparents
45 edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
45 edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
46
46
47 while len(newparents) > 2:
47 while len(newparents) > 2:
48 # ascii() only knows how to add or remove a single column between two
48 # ascii() only knows how to add or remove a single column between two
49 # calls. Nodes with more than two parents break this constraint so we
49 # calls. Nodes with more than two parents break this constraint so we
50 # introduce intermediate expansion lines to grow the active node list
50 # introduce intermediate expansion lines to grow the active node list
51 # slowly.
51 # slowly.
52 edges.append((nodeidx, nodeidx))
52 edges.append((nodeidx, nodeidx))
53 edges.append((nodeidx, nodeidx + 1))
53 edges.append((nodeidx, nodeidx + 1))
54 nmorecols = 1
54 nmorecols = 1
55 yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
55 yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
56 char = '\\'
56 char = '\\'
57 lines = []
57 lines = []
58 nodeidx += 1
58 nodeidx += 1
59 ncols += 1
59 ncols += 1
60 edges = []
60 edges = []
61 del newparents[0]
61 del newparents[0]
62
62
63 if len(newparents) > 0:
63 if len(newparents) > 0:
64 edges.append((nodeidx, nodeidx))
64 edges.append((nodeidx, nodeidx))
65 if len(newparents) > 1:
65 if len(newparents) > 1:
66 edges.append((nodeidx, nodeidx + 1))
66 edges.append((nodeidx, nodeidx + 1))
67 nmorecols = len(nextseen) - ncols
67 nmorecols = len(nextseen) - ncols
68 seen[:] = nextseen
68 seen[:] = nextseen
69 yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
69 yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
70
70
71 def fix_long_right_edges(edges):
71 def fix_long_right_edges(edges):
72 for (i, (start, end)) in enumerate(edges):
72 for (i, (start, end)) in enumerate(edges):
73 if end > start:
73 if end > start:
74 edges[i] = (start, end + 1)
74 edges[i] = (start, end + 1)
75
75
76 def get_nodeline_edges_tail(
76 def get_nodeline_edges_tail(
77 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
77 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
78 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
78 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
79 # Still going in the same non-vertical direction.
79 # Still going in the same non-vertical direction.
80 if n_columns_diff == -1:
80 if n_columns_diff == -1:
81 start = max(node_index + 1, p_node_index)
81 start = max(node_index + 1, p_node_index)
82 tail = ["|", " "] * (start - node_index - 1)
82 tail = ["|", " "] * (start - node_index - 1)
83 tail.extend(["/", " "] * (n_columns - start))
83 tail.extend(["/", " "] * (n_columns - start))
84 return tail
84 return tail
85 else:
85 else:
86 return ["\\", " "] * (n_columns - node_index - 1)
86 return ["\\", " "] * (n_columns - node_index - 1)
87 else:
87 else:
88 return ["|", " "] * (n_columns - node_index - 1)
88 return ["|", " "] * (n_columns - node_index - 1)
89
89
90 def draw_edges(edges, nodeline, interline):
90 def draw_edges(edges, nodeline, interline):
91 for (start, end) in edges:
91 for (start, end) in edges:
92 if start == end + 1:
92 if start == end + 1:
93 interline[2 * end + 1] = "/"
93 interline[2 * end + 1] = "/"
94 elif start == end - 1:
94 elif start == end - 1:
95 interline[2 * start + 1] = "\\"
95 interline[2 * start + 1] = "\\"
96 elif start == end:
96 elif start == end:
97 interline[2 * start] = "|"
97 interline[2 * start] = "|"
98 else:
98 else:
99 if 2 * end >= len(nodeline):
99 if 2 * end >= len(nodeline):
100 continue
100 continue
101 nodeline[2 * end] = "+"
101 nodeline[2 * end] = "+"
102 if start > end:
102 if start > end:
103 (start, end) = (end, start)
103 (start, end) = (end, start)
104 for i in range(2 * start + 1, 2 * end):
104 for i in range(2 * start + 1, 2 * end):
105 if nodeline[i] != "+":
105 if nodeline[i] != "+":
106 nodeline[i] = "-"
106 nodeline[i] = "-"
107
107
108 def get_padding_line(ni, n_columns, edges):
108 def get_padding_line(ni, n_columns, edges):
109 line = []
109 line = []
110 line.extend(["|", " "] * ni)
110 line.extend(["|", " "] * ni)
111 if (ni, ni - 1) in edges or (ni, ni) in edges:
111 if (ni, ni - 1) in edges or (ni, ni) in edges:
112 # (ni, ni - 1) (ni, ni)
112 # (ni, ni - 1) (ni, ni)
113 # | | | | | | | |
113 # | | | | | | | |
114 # +---o | | o---+
114 # +---o | | o---+
115 # | | c | | c | |
115 # | | c | | c | |
116 # | |/ / | |/ /
116 # | |/ / | |/ /
117 # | | | | | |
117 # | | | | | |
118 c = "|"
118 c = "|"
119 else:
119 else:
120 c = " "
120 c = " "
121 line.extend([c, " "])
121 line.extend([c, " "])
122 line.extend(["|", " "] * (n_columns - ni - 1))
122 line.extend(["|", " "] * (n_columns - ni - 1))
123 return line
123 return line
124
124
125 def asciistate():
125 def asciistate():
126 """returns the initial value for the "state" argument to ascii()"""
126 """returns the initial value for the "state" argument to ascii()"""
127 return [0, 0]
127 return [0, 0]
128
128
129 def ascii(ui, state, type, char, text, coldata):
129 def ascii(ui, state, type, char, text, coldata):
130 """prints an ASCII graph of the DAG
130 """prints an ASCII graph of the DAG
131
131
132 takes the following arguments (one call per node in the graph):
132 takes the following arguments (one call per node in the graph):
133
133
134 - ui to write to
134 - ui to write to
135 - Somewhere to keep the needed state in (init to asciistate())
135 - Somewhere to keep the needed state in (init to asciistate())
136 - Column of the current node in the set of ongoing edges.
136 - Column of the current node in the set of ongoing edges.
137 - Type indicator of node data == ASCIIDATA.
137 - Type indicator of node data == ASCIIDATA.
138 - Payload: (char, lines):
138 - Payload: (char, lines):
139 - Character to use as node's symbol.
139 - Character to use as node's symbol.
140 - List of lines to display as the node's text.
140 - List of lines to display as the node's text.
141 - Edges; a list of (col, next_col) indicating the edges between
141 - Edges; a list of (col, next_col) indicating the edges between
142 the current node and its parents.
142 the current node and its parents.
143 - Number of columns (ongoing edges) in the current revision.
143 - Number of columns (ongoing edges) in the current revision.
144 - The difference between the number of columns (ongoing edges)
144 - The difference between the number of columns (ongoing edges)
145 in the next revision and the number of columns (ongoing edges)
145 in the next revision and the number of columns (ongoing edges)
146 in the current revision. That is: -1 means one column removed;
146 in the current revision. That is: -1 means one column removed;
147 0 means no columns added or removed; 1 means one column added.
147 0 means no columns added or removed; 1 means one column added.
148 """
148 """
149
149
150 idx, edges, ncols, coldiff = coldata
150 idx, edges, ncols, coldiff = coldata
151 assert -2 < coldiff < 2
151 assert -2 < coldiff < 2
152 if coldiff == -1:
152 if coldiff == -1:
153 # Transform
153 # Transform
154 #
154 #
155 # | | | | | |
155 # | | | | | |
156 # o | | into o---+
156 # o | | into o---+
157 # |X / |/ /
157 # |X / |/ /
158 # | | | |
158 # | | | |
159 fix_long_right_edges(edges)
159 fix_long_right_edges(edges)
160
160
161 # add_padding_line says whether to rewrite
161 # add_padding_line says whether to rewrite
162 #
162 #
163 # | | | | | | | |
163 # | | | | | | | |
164 # | o---+ into | o---+
164 # | o---+ into | o---+
165 # | / / | | | # <--- padding line
165 # | / / | | | # <--- padding line
166 # o | | | / /
166 # o | | | / /
167 # o | |
167 # o | |
168 add_padding_line = (len(text) > 2 and coldiff == -1 and
168 add_padding_line = (len(text) > 2 and coldiff == -1 and
169 [x for (x, y) in edges if x + 1 < y])
169 [x for (x, y) in edges if x + 1 < y])
170
170
171 # fix_nodeline_tail says whether to rewrite
171 # fix_nodeline_tail says whether to rewrite
172 #
172 #
173 # | | o | | | | o | |
173 # | | o | | | | o | |
174 # | | |/ / | | |/ /
174 # | | |/ / | | |/ /
175 # | o | | into | o / / # <--- fixed nodeline tail
175 # | o | | into | o / / # <--- fixed nodeline tail
176 # | |/ / | |/ /
176 # | |/ / | |/ /
177 # o | | o | |
177 # o | | o | |
178 fix_nodeline_tail = len(text) <= 2 and not add_padding_line
178 fix_nodeline_tail = len(text) <= 2 and not add_padding_line
179
179
180 # nodeline is the line containing the node character (typically o)
180 # nodeline is the line containing the node character (typically o)
181 nodeline = ["|", " "] * idx
181 nodeline = ["|", " "] * idx
182 nodeline.extend([char, " "])
182 nodeline.extend([char, " "])
183
183
184 nodeline.extend(
184 nodeline.extend(
185 get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
185 get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
186 state[0], fix_nodeline_tail))
186 state[0], fix_nodeline_tail))
187
187
188 # shift_interline is the line containing the non-vertical
188 # shift_interline is the line containing the non-vertical
189 # edges between this entry and the next
189 # edges between this entry and the next
190 shift_interline = ["|", " "] * idx
190 shift_interline = ["|", " "] * idx
191 if coldiff == -1:
191 if coldiff == -1:
192 n_spaces = 1
192 n_spaces = 1
193 edge_ch = "/"
193 edge_ch = "/"
194 elif coldiff == 0:
194 elif coldiff == 0:
195 n_spaces = 2
195 n_spaces = 2
196 edge_ch = "|"
196 edge_ch = "|"
197 else:
197 else:
198 n_spaces = 3
198 n_spaces = 3
199 edge_ch = "\\"
199 edge_ch = "\\"
200 shift_interline.extend(n_spaces * [" "])
200 shift_interline.extend(n_spaces * [" "])
201 shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
201 shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
202
202
203 # draw edges from the current node to its parents
203 # draw edges from the current node to its parents
204 draw_edges(edges, nodeline, shift_interline)
204 draw_edges(edges, nodeline, shift_interline)
205
205
206 # lines is the list of all graph lines to print
206 # lines is the list of all graph lines to print
207 lines = [nodeline]
207 lines = [nodeline]
208 if add_padding_line:
208 if add_padding_line:
209 lines.append(get_padding_line(idx, ncols, edges))
209 lines.append(get_padding_line(idx, ncols, edges))
210 lines.append(shift_interline)
210 lines.append(shift_interline)
211
211
212 # make sure that there are as many graph lines as there are
212 # make sure that there are as many graph lines as there are
213 # log strings
213 # log strings
214 while len(text) < len(lines):
214 while len(text) < len(lines):
215 text.append("")
215 text.append("")
216 if len(lines) < len(text):
216 if len(lines) < len(text):
217 extra_interline = ["|", " "] * (ncols + coldiff)
217 extra_interline = ["|", " "] * (ncols + coldiff)
218 while len(lines) < len(text):
218 while len(lines) < len(text):
219 lines.append(extra_interline)
219 lines.append(extra_interline)
220
220
221 # print lines
221 # print lines
222 indentation_level = max(ncols, ncols + coldiff)
222 indentation_level = max(ncols, ncols + coldiff)
223 for (line, logstr) in zip(lines, text):
223 for (line, logstr) in zip(lines, text):
224 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
224 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
225 ui.write(ln.rstrip() + '\n')
225 ui.write(ln.rstrip() + '\n')
226
226
227 # ... and start over
227 # ... and start over
228 state[0] = coldiff
228 state[0] = coldiff
229 state[1] = idx
229 state[1] = idx
230
230
231 def get_revs(repo, rev_opt):
231 def get_revs(repo, rev_opt):
232 if rev_opt:
232 if rev_opt:
233 revs = scmutil.revrange(repo, rev_opt)
233 revs = scmutil.revrange(repo, rev_opt)
234 if len(revs) == 0:
234 if len(revs) == 0:
235 return (nullrev, nullrev)
235 return (nullrev, nullrev)
236 return (max(revs), min(revs))
236 return (max(revs), min(revs))
237 else:
237 else:
238 return (len(repo) - 1, 0)
238 return (len(repo) - 1, 0)
239
239
240 def check_unsupported_flags(pats, opts):
240 def check_unsupported_flags(pats, opts):
241 for op in ["newest_first"]:
241 for op in ["newest_first"]:
242 if op in opts and opts[op]:
242 if op in opts and opts[op]:
243 raise util.Abort(_("-G/--graph option is incompatible with --%s")
243 raise util.Abort(_("-G/--graph option is incompatible with --%s")
244 % op.replace("_", "-"))
244 % op.replace("_", "-"))
245
245
246 def makefilematcher(repo, pats, followfirst):
246 def makefilematcher(repo, pats, followfirst):
247 # When displaying a revision with --patch --follow FILE, we have
247 # When displaying a revision with --patch --follow FILE, we have
248 # to know which file of the revision must be diffed. With
248 # to know which file of the revision must be diffed. With
249 # --follow, we want the names of the ancestors of FILE in the
249 # --follow, we want the names of the ancestors of FILE in the
250 # revision, stored in "fcache". "fcache" is populated by
250 # revision, stored in "fcache". "fcache" is populated by
251 # reproducing the graph traversal already done by --follow revset
251 # reproducing the graph traversal already done by --follow revset
252 # and relating linkrevs to file names (which is not "correct" but
252 # and relating linkrevs to file names (which is not "correct" but
253 # good enough).
253 # good enough).
254 fcache = {}
254 fcache = {}
255 fcacheready = [False]
255 fcacheready = [False]
256 pctx = repo['.']
256 pctx = repo['.']
257 wctx = repo[None]
257 wctx = repo[None]
258
258
259 def populate():
259 def populate():
260 for fn in pats:
260 for fn in pats:
261 for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
261 for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
262 for c in i:
262 for c in i:
263 fcache.setdefault(c.linkrev(), set()).add(c.path())
263 fcache.setdefault(c.linkrev(), set()).add(c.path())
264
264
265 def filematcher(rev):
265 def filematcher(rev):
266 if not fcacheready[0]:
266 if not fcacheready[0]:
267 # Lazy initialization
267 # Lazy initialization
268 fcacheready[0] = True
268 fcacheready[0] = True
269 populate()
269 populate()
270 return scmutil.match(wctx, fcache.get(rev, []), default='path')
270 return scmutil.match(wctx, fcache.get(rev, []), default='path')
271
271
272 return filematcher
272 return filematcher
273
273
274 def _makelogrevset(repo, pats, opts, revs):
274 def _makelogrevset(repo, pats, opts, revs):
275 """Return (expr, filematcher) where expr is a revset string built
275 """Return (expr, filematcher) where expr is a revset string built
276 from log options and file patterns or None. If --stat or --patch
276 from log options and file patterns or None. If --stat or --patch
277 are not passed filematcher is None. Otherwise it is a callable
277 are not passed filematcher is None. Otherwise it is a callable
278 taking a revision number and returning a match objects filtering
278 taking a revision number and returning a match objects filtering
279 the files to be detailed when displaying the revision.
279 the files to be detailed when displaying the revision.
280 """
280 """
281 opt2revset = {
281 opt2revset = {
282 'follow_first': ('_followfirst()', None),
283 'no_merges': ('not merge()', None),
282 'no_merges': ('not merge()', None),
284 'only_merges': ('merge()', None),
283 'only_merges': ('merge()', None),
285 '_ancestors': ('ancestors(%(val)s)', None),
284 '_ancestors': ('ancestors(%(val)s)', None),
285 '_fancestors': ('_firstancestors(%(val)s)', None),
286 '_descendants': ('descendants(%(val)s)', None),
286 '_descendants': ('descendants(%(val)s)', None),
287 '_fdescendants': ('_firstdescendants(%(val)s)', None),
287 '_matchfiles': ('_matchfiles(%(val)s)', None),
288 '_matchfiles': ('_matchfiles(%(val)s)', None),
288 'date': ('date(%(val)r)', None),
289 'date': ('date(%(val)r)', None),
289 'branch': ('branch(%(val)r)', ' or '),
290 'branch': ('branch(%(val)r)', ' or '),
290 '_patslog': ('filelog(%(val)r)', ' or '),
291 '_patslog': ('filelog(%(val)r)', ' or '),
291 '_patsfollow': ('follow(%(val)r)', ' or '),
292 '_patsfollow': ('follow(%(val)r)', ' or '),
292 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
293 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
293 'keyword': ('keyword(%(val)r)', ' or '),
294 'keyword': ('keyword(%(val)r)', ' or '),
294 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
295 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
295 'user': ('user(%(val)r)', ' or '),
296 'user': ('user(%(val)r)', ' or '),
296 }
297 }
297
298
298 opts = dict(opts)
299 opts = dict(opts)
299 # follow or not follow?
300 # follow or not follow?
300 follow = opts.get('follow') or opts.get('follow_first')
301 follow = opts.get('follow') or opts.get('follow_first')
301 followfirst = opts.get('follow_first')
302 followfirst = opts.get('follow_first')
302 if 'follow_first' in opts:
303 del opts['follow_first']
304 # --follow with FILE behaviour depends on revs...
303 # --follow with FILE behaviour depends on revs...
305 startrev = revs[0]
304 startrev = revs[0]
306 followdescendants = len(revs) > 1 and revs[0] < revs[1]
305 followdescendants = len(revs) > 1 and revs[0] < revs[1]
307
306
308 # branch and only_branch are really aliases and must be handled at
307 # branch and only_branch are really aliases and must be handled at
309 # the same time
308 # the same time
310 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
309 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
311 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
310 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
312 # pats/include/exclude are passed to match.match() directly in
311 # pats/include/exclude are passed to match.match() directly in
313 # _matchfile() revset but walkchangerevs() builds its matcher with
312 # _matchfile() revset but walkchangerevs() builds its matcher with
314 # scmutil.match(). The difference is input pats are globbed on
313 # scmutil.match(). The difference is input pats are globbed on
315 # platforms without shell expansion (windows).
314 # platforms without shell expansion (windows).
316 pctx = repo[None]
315 pctx = repo[None]
317 match, pats = scmutil.matchandpats(pctx, pats, opts)
316 match, pats = scmutil.matchandpats(pctx, pats, opts)
318 slowpath = match.anypats() or (match.files() and opts.get('removed'))
317 slowpath = match.anypats() or (match.files() and opts.get('removed'))
319 if not slowpath:
318 if not slowpath:
320 for f in match.files():
319 for f in match.files():
321 if follow and f not in pctx:
320 if follow and f not in pctx:
322 raise util.Abort(_('cannot follow file not in parent '
321 raise util.Abort(_('cannot follow file not in parent '
323 'revision: "%s"') % f)
322 'revision: "%s"') % f)
324 filelog = repo.file(f)
323 filelog = repo.file(f)
325 if not len(filelog):
324 if not len(filelog):
326 # A zero count may be a directory or deleted file, so
325 # A zero count may be a directory or deleted file, so
327 # try to find matching entries on the slow path.
326 # try to find matching entries on the slow path.
328 if follow:
327 if follow:
329 raise util.Abort(
328 raise util.Abort(
330 _('cannot follow nonexistent file: "%s"') % f)
329 _('cannot follow nonexistent file: "%s"') % f)
331 slowpath = True
330 slowpath = True
332 if slowpath:
331 if slowpath:
333 # See cmdutil.walkchangerevs() slow path.
332 # See cmdutil.walkchangerevs() slow path.
334 #
333 #
335 if follow:
334 if follow:
336 raise util.Abort(_('can only follow copies/renames for explicit '
335 raise util.Abort(_('can only follow copies/renames for explicit '
337 'filenames'))
336 'filenames'))
338 # pats/include/exclude cannot be represented as separate
337 # pats/include/exclude cannot be represented as separate
339 # revset expressions as their filtering logic applies at file
338 # revset expressions as their filtering logic applies at file
340 # level. For instance "-I a -X a" matches a revision touching
339 # level. For instance "-I a -X a" matches a revision touching
341 # "a" and "b" while "file(a) and not file(b)" does
340 # "a" and "b" while "file(a) and not file(b)" does
342 # not. Besides, filesets are evaluated against the working
341 # not. Besides, filesets are evaluated against the working
343 # directory.
342 # directory.
344 matchargs = ['r:']
343 matchargs = ['r:']
345 for p in pats:
344 for p in pats:
346 matchargs.append('p:' + p)
345 matchargs.append('p:' + p)
347 for p in opts.get('include', []):
346 for p in opts.get('include', []):
348 matchargs.append('i:' + p)
347 matchargs.append('i:' + p)
349 for p in opts.get('exclude', []):
348 for p in opts.get('exclude', []):
350 matchargs.append('x:' + p)
349 matchargs.append('x:' + p)
351 matchargs = ','.join(('%r' % p) for p in matchargs)
350 matchargs = ','.join(('%r' % p) for p in matchargs)
352 opts['_matchfiles'] = matchargs
351 opts['_matchfiles'] = matchargs
353 else:
352 else:
354 if follow:
353 if follow:
355 if followfirst:
354 if followfirst:
356 if pats:
355 if pats:
357 opts['_patsfollowfirst'] = list(pats)
356 opts['_patsfollowfirst'] = list(pats)
358 else:
357 else:
359 opts['follow_first'] = True
358 if followdescendants:
359 opts['_fdescendants'] = str(startrev)
360 else:
361 opts['_fancestors'] = str(startrev)
360 else:
362 else:
361 if pats:
363 if pats:
362 opts['_patsfollow'] = list(pats)
364 opts['_patsfollow'] = list(pats)
363 else:
365 else:
364 if followdescendants:
366 if followdescendants:
365 opts['_descendants'] = str(startrev)
367 opts['_descendants'] = str(startrev)
366 else:
368 else:
367 opts['_ancestors'] = str(startrev)
369 opts['_ancestors'] = str(startrev)
368 else:
370 else:
369 opts['_patslog'] = list(pats)
371 opts['_patslog'] = list(pats)
370
372
371 filematcher = None
373 filematcher = None
372 if opts.get('patch') or opts.get('stat'):
374 if opts.get('patch') or opts.get('stat'):
373 if follow:
375 if follow:
374 filematcher = makefilematcher(repo, pats, followfirst)
376 filematcher = makefilematcher(repo, pats, followfirst)
375 else:
377 else:
376 filematcher = lambda rev: match
378 filematcher = lambda rev: match
377
379
378 revset = []
380 revset = []
379 for op, val in opts.iteritems():
381 for op, val in opts.iteritems():
380 if not val:
382 if not val:
381 continue
383 continue
382 if op not in opt2revset:
384 if op not in opt2revset:
383 continue
385 continue
384 revop, andor = opt2revset[op]
386 revop, andor = opt2revset[op]
385 if '%(val)' not in revop:
387 if '%(val)' not in revop:
386 revset.append(revop)
388 revset.append(revop)
387 else:
389 else:
388 if not isinstance(val, list):
390 if not isinstance(val, list):
389 expr = revop % {'val': val}
391 expr = revop % {'val': val}
390 else:
392 else:
391 expr = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
393 expr = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
392 revset.append(expr)
394 revset.append(expr)
393
395
394 if revset:
396 if revset:
395 revset = '(' + ' and '.join(revset) + ')'
397 revset = '(' + ' and '.join(revset) + ')'
396 else:
398 else:
397 revset = None
399 revset = None
398 return revset, filematcher
400 return revset, filematcher
399
401
400 def getlogrevs(repo, pats, opts):
402 def getlogrevs(repo, pats, opts):
401 """Return (revs, expr, filematcher) where revs is a list of
403 """Return (revs, expr, filematcher) where revs is a list of
402 revision numbers, expr is a revset string built from log options
404 revision numbers, expr is a revset string built from log options
403 and file patterns or None, and used to filter 'revs'. If --stat or
405 and file patterns or None, and used to filter 'revs'. If --stat or
404 --patch are not passed filematcher is None. Otherwise it is a
406 --patch are not passed filematcher is None. Otherwise it is a
405 callable taking a revision number and returning a match objects
407 callable taking a revision number and returning a match objects
406 filtering the files to be detailed when displaying the revision.
408 filtering the files to be detailed when displaying the revision.
407 """
409 """
408 if not len(repo):
410 if not len(repo):
409 return [], None, None
411 return [], None, None
410 # Default --rev value depends on --follow but --follow behaviour
412 # Default --rev value depends on --follow but --follow behaviour
411 # depends on revisions resolved from --rev...
413 # depends on revisions resolved from --rev...
412 follow = opts.get('follow') or opts.get('follow_first')
414 follow = opts.get('follow') or opts.get('follow_first')
413 if opts.get('rev'):
415 if opts.get('rev'):
414 revs = scmutil.revrange(repo, opts['rev'])
416 revs = scmutil.revrange(repo, opts['rev'])
415 else:
417 else:
416 if follow and len(repo) > 0:
418 if follow and len(repo) > 0:
417 revs = scmutil.revrange(repo, ['.:0'])
419 revs = scmutil.revrange(repo, ['.:0'])
418 else:
420 else:
419 revs = range(len(repo) - 1, -1, -1)
421 revs = range(len(repo) - 1, -1, -1)
420 if not revs:
422 if not revs:
421 return [], None, None
423 return [], None, None
422 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
424 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
423 if expr:
425 if expr:
424 # Evaluate revisions in changelog order for performance
426 # Evaluate revisions in changelog order for performance
425 # reasons but preserve the original sequence order in the
427 # reasons but preserve the original sequence order in the
426 # filtered result.
428 # filtered result.
427 matched = set(revsetmod.match(repo.ui, expr)(repo, sorted(revs)))
429 matched = set(revsetmod.match(repo.ui, expr)(repo, sorted(revs)))
428 revs = [r for r in revs if r in matched]
430 revs = [r for r in revs if r in matched]
429 return revs, expr, filematcher
431 return revs, expr, filematcher
430
432
431 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
433 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
432 filematcher=None):
434 filematcher=None):
433 seen, state = [], asciistate()
435 seen, state = [], asciistate()
434 for rev, type, ctx, parents in dag:
436 for rev, type, ctx, parents in dag:
435 char = ctx.node() in showparents and '@' or 'o'
437 char = ctx.node() in showparents and '@' or 'o'
436 copies = None
438 copies = None
437 if getrenamed and ctx.rev():
439 if getrenamed and ctx.rev():
438 copies = []
440 copies = []
439 for fn in ctx.files():
441 for fn in ctx.files():
440 rename = getrenamed(fn, ctx.rev())
442 rename = getrenamed(fn, ctx.rev())
441 if rename:
443 if rename:
442 copies.append((fn, rename[0]))
444 copies.append((fn, rename[0]))
443 revmatchfn = None
445 revmatchfn = None
444 if filematcher is not None:
446 if filematcher is not None:
445 revmatchfn = filematcher(ctx.rev())
447 revmatchfn = filematcher(ctx.rev())
446 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
448 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
447 lines = displayer.hunk.pop(rev).split('\n')[:-1]
449 lines = displayer.hunk.pop(rev).split('\n')[:-1]
448 displayer.flush(rev)
450 displayer.flush(rev)
449 edges = edgefn(type, char, lines, seen, rev, parents)
451 edges = edgefn(type, char, lines, seen, rev, parents)
450 for type, char, lines, coldata in edges:
452 for type, char, lines, coldata in edges:
451 ascii(ui, state, type, char, lines, coldata)
453 ascii(ui, state, type, char, lines, coldata)
452 displayer.close()
454 displayer.close()
453
455
454 @command('glog',
456 @command('glog',
455 [('l', 'limit', '',
457 [('l', 'limit', '',
456 _('limit number of changes displayed'), _('NUM')),
458 _('limit number of changes displayed'), _('NUM')),
457 ('p', 'patch', False, _('show patch')),
459 ('p', 'patch', False, _('show patch')),
458 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
460 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
459 ] + templateopts,
461 ] + templateopts,
460 _('hg glog [OPTION]... [FILE]'))
462 _('hg glog [OPTION]... [FILE]'))
461 def graphlog(ui, repo, *pats, **opts):
463 def graphlog(ui, repo, *pats, **opts):
462 """show revision history alongside an ASCII revision graph
464 """show revision history alongside an ASCII revision graph
463
465
464 Print a revision history alongside a revision graph drawn with
466 Print a revision history alongside a revision graph drawn with
465 ASCII characters.
467 ASCII characters.
466
468
467 Nodes printed as an @ character are parents of the working
469 Nodes printed as an @ character are parents of the working
468 directory.
470 directory.
469 """
471 """
470
472
471 check_unsupported_flags(pats, opts)
473 check_unsupported_flags(pats, opts)
472
474
473 revs, expr, filematcher = getlogrevs(repo, pats, opts)
475 revs, expr, filematcher = getlogrevs(repo, pats, opts)
474 revs = sorted(revs, reverse=1)
476 revs = sorted(revs, reverse=1)
475 limit = cmdutil.loglimit(opts)
477 limit = cmdutil.loglimit(opts)
476 if limit is not None:
478 if limit is not None:
477 revs = revs[:limit]
479 revs = revs[:limit]
478 revdag = graphmod.dagwalker(repo, revs)
480 revdag = graphmod.dagwalker(repo, revs)
479
481
480 getrenamed = None
482 getrenamed = None
481 if opts.get('copies'):
483 if opts.get('copies'):
482 endrev = None
484 endrev = None
483 if opts.get('rev'):
485 if opts.get('rev'):
484 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
486 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
485 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
487 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
486 displayer = show_changeset(ui, repo, opts, buffered=True)
488 displayer = show_changeset(ui, repo, opts, buffered=True)
487 showparents = [ctx.node() for ctx in repo[None].parents()]
489 showparents = [ctx.node() for ctx in repo[None].parents()]
488 generate(ui, revdag, displayer, showparents, asciiedges, getrenamed,
490 generate(ui, revdag, displayer, showparents, asciiedges, getrenamed,
489 filematcher)
491 filematcher)
490
492
491 def graphrevs(repo, nodes, opts):
493 def graphrevs(repo, nodes, opts):
492 limit = cmdutil.loglimit(opts)
494 limit = cmdutil.loglimit(opts)
493 nodes.reverse()
495 nodes.reverse()
494 if limit is not None:
496 if limit is not None:
495 nodes = nodes[:limit]
497 nodes = nodes[:limit]
496 return graphmod.nodes(repo, nodes)
498 return graphmod.nodes(repo, nodes)
497
499
498 def goutgoing(ui, repo, dest=None, **opts):
500 def goutgoing(ui, repo, dest=None, **opts):
499 """show the outgoing changesets alongside an ASCII revision graph
501 """show the outgoing changesets alongside an ASCII revision graph
500
502
501 Print the outgoing changesets alongside a revision graph drawn with
503 Print the outgoing changesets alongside a revision graph drawn with
502 ASCII characters.
504 ASCII characters.
503
505
504 Nodes printed as an @ character are parents of the working
506 Nodes printed as an @ character are parents of the working
505 directory.
507 directory.
506 """
508 """
507
509
508 check_unsupported_flags([], opts)
510 check_unsupported_flags([], opts)
509 o = hg._outgoing(ui, repo, dest, opts)
511 o = hg._outgoing(ui, repo, dest, opts)
510 if o is None:
512 if o is None:
511 return
513 return
512
514
513 revdag = graphrevs(repo, o, opts)
515 revdag = graphrevs(repo, o, opts)
514 displayer = show_changeset(ui, repo, opts, buffered=True)
516 displayer = show_changeset(ui, repo, opts, buffered=True)
515 showparents = [ctx.node() for ctx in repo[None].parents()]
517 showparents = [ctx.node() for ctx in repo[None].parents()]
516 generate(ui, revdag, displayer, showparents, asciiedges)
518 generate(ui, revdag, displayer, showparents, asciiedges)
517
519
518 def gincoming(ui, repo, source="default", **opts):
520 def gincoming(ui, repo, source="default", **opts):
519 """show the incoming changesets alongside an ASCII revision graph
521 """show the incoming changesets alongside an ASCII revision graph
520
522
521 Print the incoming changesets alongside a revision graph drawn with
523 Print the incoming changesets alongside a revision graph drawn with
522 ASCII characters.
524 ASCII characters.
523
525
524 Nodes printed as an @ character are parents of the working
526 Nodes printed as an @ character are parents of the working
525 directory.
527 directory.
526 """
528 """
527 def subreporecurse():
529 def subreporecurse():
528 return 1
530 return 1
529
531
530 check_unsupported_flags([], opts)
532 check_unsupported_flags([], opts)
531 def display(other, chlist, displayer):
533 def display(other, chlist, displayer):
532 revdag = graphrevs(other, chlist, opts)
534 revdag = graphrevs(other, chlist, opts)
533 showparents = [ctx.node() for ctx in repo[None].parents()]
535 showparents = [ctx.node() for ctx in repo[None].parents()]
534 generate(ui, revdag, displayer, showparents, asciiedges)
536 generate(ui, revdag, displayer, showparents, asciiedges)
535
537
536 hg._incoming(display, subreporecurse, ui, repo, source, opts, buffered=True)
538 hg._incoming(display, subreporecurse, ui, repo, source, opts, buffered=True)
537
539
538 def uisetup(ui):
540 def uisetup(ui):
539 '''Initialize the extension.'''
541 '''Initialize the extension.'''
540 _wrapcmd('log', commands.table, graphlog)
542 _wrapcmd('log', commands.table, graphlog)
541 _wrapcmd('incoming', commands.table, gincoming)
543 _wrapcmd('incoming', commands.table, gincoming)
542 _wrapcmd('outgoing', commands.table, goutgoing)
544 _wrapcmd('outgoing', commands.table, goutgoing)
543
545
544 def _wrapcmd(cmd, table, wrapfn):
546 def _wrapcmd(cmd, table, wrapfn):
545 '''wrap the command'''
547 '''wrap the command'''
546 def graph(orig, *args, **kwargs):
548 def graph(orig, *args, **kwargs):
547 if kwargs['graph']:
549 if kwargs['graph']:
548 return wrapfn(*args, **kwargs)
550 return wrapfn(*args, **kwargs)
549 return orig(*args, **kwargs)
551 return orig(*args, **kwargs)
550 entry = extensions.wrapcommand(table, cmd, graph)
552 entry = extensions.wrapcommand(table, cmd, graph)
551 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
553 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
@@ -1,1417 +1,1459 b''
1 # revset.py - revision set queries for mercurial
1 # revset.py - revision set queries for mercurial
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
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 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import re
8 import re
9 import parser, util, error, discovery, hbisect, phases
9 import parser, util, error, discovery, hbisect, phases
10 import node as nodemod
10 import node as nodemod
11 import bookmarks as bookmarksmod
11 import bookmarks as bookmarksmod
12 import match as matchmod
12 import match as matchmod
13 from i18n import _
13 from i18n import _
14 import encoding
14 import encoding
15
15
16 def _revancestors(repo, revs, followfirst):
17 """Like revlog.ancestors(), but supports followfirst."""
18 cut = followfirst and 1 or None
19 cl = repo.changelog
20 visit = list(revs)
21 seen = set([nodemod.nullrev])
22 while visit:
23 for parent in cl.parentrevs(visit.pop(0))[:cut]:
24 if parent not in seen:
25 visit.append(parent)
26 seen.add(parent)
27 yield parent
28
29 def _revdescendants(repo, revs, followfirst):
30 """Like revlog.descendants() but supports followfirst."""
31 cut = followfirst and 1 or None
32 cl = repo.changelog
33 first = min(revs)
34 if first == nodemod.nullrev:
35 # Are there nodes with a null first parent and a non-null
36 # second one? Maybe. Do we care? Probably not.
37 for i in cl:
38 yield i
39 return
40
41 seen = set(revs)
42 for i in xrange(first + 1, len(cl)):
43 for x in cl.parentrevs(i)[:cut]:
44 if x != nodemod.nullrev and x in seen:
45 seen.add(i)
46 yield i
47 break
48
16 elements = {
49 elements = {
17 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
50 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
18 "~": (18, None, ("ancestor", 18)),
51 "~": (18, None, ("ancestor", 18)),
19 "^": (18, None, ("parent", 18), ("parentpost", 18)),
52 "^": (18, None, ("parent", 18), ("parentpost", 18)),
20 "-": (5, ("negate", 19), ("minus", 5)),
53 "-": (5, ("negate", 19), ("minus", 5)),
21 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
54 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
22 ("dagrangepost", 17)),
55 ("dagrangepost", 17)),
23 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
56 "..": (17, ("dagrangepre", 17), ("dagrange", 17),
24 ("dagrangepost", 17)),
57 ("dagrangepost", 17)),
25 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
58 ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
26 "not": (10, ("not", 10)),
59 "not": (10, ("not", 10)),
27 "!": (10, ("not", 10)),
60 "!": (10, ("not", 10)),
28 "and": (5, None, ("and", 5)),
61 "and": (5, None, ("and", 5)),
29 "&": (5, None, ("and", 5)),
62 "&": (5, None, ("and", 5)),
30 "or": (4, None, ("or", 4)),
63 "or": (4, None, ("or", 4)),
31 "|": (4, None, ("or", 4)),
64 "|": (4, None, ("or", 4)),
32 "+": (4, None, ("or", 4)),
65 "+": (4, None, ("or", 4)),
33 ",": (2, None, ("list", 2)),
66 ",": (2, None, ("list", 2)),
34 ")": (0, None, None),
67 ")": (0, None, None),
35 "symbol": (0, ("symbol",), None),
68 "symbol": (0, ("symbol",), None),
36 "string": (0, ("string",), None),
69 "string": (0, ("string",), None),
37 "end": (0, None, None),
70 "end": (0, None, None),
38 }
71 }
39
72
40 keywords = set(['and', 'or', 'not'])
73 keywords = set(['and', 'or', 'not'])
41
74
42 def tokenize(program):
75 def tokenize(program):
43 pos, l = 0, len(program)
76 pos, l = 0, len(program)
44 while pos < l:
77 while pos < l:
45 c = program[pos]
78 c = program[pos]
46 if c.isspace(): # skip inter-token whitespace
79 if c.isspace(): # skip inter-token whitespace
47 pass
80 pass
48 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
81 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
49 yield ('::', None, pos)
82 yield ('::', None, pos)
50 pos += 1 # skip ahead
83 pos += 1 # skip ahead
51 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
84 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
52 yield ('..', None, pos)
85 yield ('..', None, pos)
53 pos += 1 # skip ahead
86 pos += 1 # skip ahead
54 elif c in "():,-|&+!~^": # handle simple operators
87 elif c in "():,-|&+!~^": # handle simple operators
55 yield (c, None, pos)
88 yield (c, None, pos)
56 elif (c in '"\'' or c == 'r' and
89 elif (c in '"\'' or c == 'r' and
57 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
90 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
58 if c == 'r':
91 if c == 'r':
59 pos += 1
92 pos += 1
60 c = program[pos]
93 c = program[pos]
61 decode = lambda x: x
94 decode = lambda x: x
62 else:
95 else:
63 decode = lambda x: x.decode('string-escape')
96 decode = lambda x: x.decode('string-escape')
64 pos += 1
97 pos += 1
65 s = pos
98 s = pos
66 while pos < l: # find closing quote
99 while pos < l: # find closing quote
67 d = program[pos]
100 d = program[pos]
68 if d == '\\': # skip over escaped characters
101 if d == '\\': # skip over escaped characters
69 pos += 2
102 pos += 2
70 continue
103 continue
71 if d == c:
104 if d == c:
72 yield ('string', decode(program[s:pos]), s)
105 yield ('string', decode(program[s:pos]), s)
73 break
106 break
74 pos += 1
107 pos += 1
75 else:
108 else:
76 raise error.ParseError(_("unterminated string"), s)
109 raise error.ParseError(_("unterminated string"), s)
77 elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
110 elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
78 s = pos
111 s = pos
79 pos += 1
112 pos += 1
80 while pos < l: # find end of symbol
113 while pos < l: # find end of symbol
81 d = program[pos]
114 d = program[pos]
82 if not (d.isalnum() or d in "._/" or ord(d) > 127):
115 if not (d.isalnum() or d in "._/" or ord(d) > 127):
83 break
116 break
84 if d == '.' and program[pos - 1] == '.': # special case for ..
117 if d == '.' and program[pos - 1] == '.': # special case for ..
85 pos -= 1
118 pos -= 1
86 break
119 break
87 pos += 1
120 pos += 1
88 sym = program[s:pos]
121 sym = program[s:pos]
89 if sym in keywords: # operator keywords
122 if sym in keywords: # operator keywords
90 yield (sym, None, s)
123 yield (sym, None, s)
91 else:
124 else:
92 yield ('symbol', sym, s)
125 yield ('symbol', sym, s)
93 pos -= 1
126 pos -= 1
94 else:
127 else:
95 raise error.ParseError(_("syntax error"), pos)
128 raise error.ParseError(_("syntax error"), pos)
96 pos += 1
129 pos += 1
97 yield ('end', None, pos)
130 yield ('end', None, pos)
98
131
99 # helpers
132 # helpers
100
133
101 def getstring(x, err):
134 def getstring(x, err):
102 if x and (x[0] == 'string' or x[0] == 'symbol'):
135 if x and (x[0] == 'string' or x[0] == 'symbol'):
103 return x[1]
136 return x[1]
104 raise error.ParseError(err)
137 raise error.ParseError(err)
105
138
106 def getlist(x):
139 def getlist(x):
107 if not x:
140 if not x:
108 return []
141 return []
109 if x[0] == 'list':
142 if x[0] == 'list':
110 return getlist(x[1]) + [x[2]]
143 return getlist(x[1]) + [x[2]]
111 return [x]
144 return [x]
112
145
113 def getargs(x, min, max, err):
146 def getargs(x, min, max, err):
114 l = getlist(x)
147 l = getlist(x)
115 if len(l) < min or (max >= 0 and len(l) > max):
148 if len(l) < min or (max >= 0 and len(l) > max):
116 raise error.ParseError(err)
149 raise error.ParseError(err)
117 return l
150 return l
118
151
119 def getset(repo, subset, x):
152 def getset(repo, subset, x):
120 if not x:
153 if not x:
121 raise error.ParseError(_("missing argument"))
154 raise error.ParseError(_("missing argument"))
122 return methods[x[0]](repo, subset, *x[1:])
155 return methods[x[0]](repo, subset, *x[1:])
123
156
124 # operator methods
157 # operator methods
125
158
126 def stringset(repo, subset, x):
159 def stringset(repo, subset, x):
127 x = repo[x].rev()
160 x = repo[x].rev()
128 if x == -1 and len(subset) == len(repo):
161 if x == -1 and len(subset) == len(repo):
129 return [-1]
162 return [-1]
130 if len(subset) == len(repo) or x in subset:
163 if len(subset) == len(repo) or x in subset:
131 return [x]
164 return [x]
132 return []
165 return []
133
166
134 def symbolset(repo, subset, x):
167 def symbolset(repo, subset, x):
135 if x in symbols:
168 if x in symbols:
136 raise error.ParseError(_("can't use %s here") % x)
169 raise error.ParseError(_("can't use %s here") % x)
137 return stringset(repo, subset, x)
170 return stringset(repo, subset, x)
138
171
139 def rangeset(repo, subset, x, y):
172 def rangeset(repo, subset, x, y):
140 m = getset(repo, subset, x)
173 m = getset(repo, subset, x)
141 if not m:
174 if not m:
142 m = getset(repo, range(len(repo)), x)
175 m = getset(repo, range(len(repo)), x)
143
176
144 n = getset(repo, subset, y)
177 n = getset(repo, subset, y)
145 if not n:
178 if not n:
146 n = getset(repo, range(len(repo)), y)
179 n = getset(repo, range(len(repo)), y)
147
180
148 if not m or not n:
181 if not m or not n:
149 return []
182 return []
150 m, n = m[0], n[-1]
183 m, n = m[0], n[-1]
151
184
152 if m < n:
185 if m < n:
153 r = range(m, n + 1)
186 r = range(m, n + 1)
154 else:
187 else:
155 r = range(m, n - 1, -1)
188 r = range(m, n - 1, -1)
156 s = set(subset)
189 s = set(subset)
157 return [x for x in r if x in s]
190 return [x for x in r if x in s]
158
191
159 def andset(repo, subset, x, y):
192 def andset(repo, subset, x, y):
160 return getset(repo, getset(repo, subset, x), y)
193 return getset(repo, getset(repo, subset, x), y)
161
194
162 def orset(repo, subset, x, y):
195 def orset(repo, subset, x, y):
163 xl = getset(repo, subset, x)
196 xl = getset(repo, subset, x)
164 s = set(xl)
197 s = set(xl)
165 yl = getset(repo, [r for r in subset if r not in s], y)
198 yl = getset(repo, [r for r in subset if r not in s], y)
166 return xl + yl
199 return xl + yl
167
200
168 def notset(repo, subset, x):
201 def notset(repo, subset, x):
169 s = set(getset(repo, subset, x))
202 s = set(getset(repo, subset, x))
170 return [r for r in subset if r not in s]
203 return [r for r in subset if r not in s]
171
204
172 def listset(repo, subset, a, b):
205 def listset(repo, subset, a, b):
173 raise error.ParseError(_("can't use a list in this context"))
206 raise error.ParseError(_("can't use a list in this context"))
174
207
175 def func(repo, subset, a, b):
208 def func(repo, subset, a, b):
176 if a[0] == 'symbol' and a[1] in symbols:
209 if a[0] == 'symbol' and a[1] in symbols:
177 return symbols[a[1]](repo, subset, b)
210 return symbols[a[1]](repo, subset, b)
178 raise error.ParseError(_("not a function: %s") % a[1])
211 raise error.ParseError(_("not a function: %s") % a[1])
179
212
180 # functions
213 # functions
181
214
182 def adds(repo, subset, x):
215 def adds(repo, subset, x):
183 """``adds(pattern)``
216 """``adds(pattern)``
184 Changesets that add a file matching pattern.
217 Changesets that add a file matching pattern.
185 """
218 """
186 # i18n: "adds" is a keyword
219 # i18n: "adds" is a keyword
187 pat = getstring(x, _("adds requires a pattern"))
220 pat = getstring(x, _("adds requires a pattern"))
188 return checkstatus(repo, subset, pat, 1)
221 return checkstatus(repo, subset, pat, 1)
189
222
190 def ancestor(repo, subset, x):
223 def ancestor(repo, subset, x):
191 """``ancestor(single, single)``
224 """``ancestor(single, single)``
192 Greatest common ancestor of the two changesets.
225 Greatest common ancestor of the two changesets.
193 """
226 """
194 # i18n: "ancestor" is a keyword
227 # i18n: "ancestor" is a keyword
195 l = getargs(x, 2, 2, _("ancestor requires two arguments"))
228 l = getargs(x, 2, 2, _("ancestor requires two arguments"))
196 r = range(len(repo))
229 r = range(len(repo))
197 a = getset(repo, r, l[0])
230 a = getset(repo, r, l[0])
198 b = getset(repo, r, l[1])
231 b = getset(repo, r, l[1])
199 if len(a) != 1 or len(b) != 1:
232 if len(a) != 1 or len(b) != 1:
200 # i18n: "ancestor" is a keyword
233 # i18n: "ancestor" is a keyword
201 raise error.ParseError(_("ancestor arguments must be single revisions"))
234 raise error.ParseError(_("ancestor arguments must be single revisions"))
202 an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
235 an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
203
236
204 return [r for r in an if r in subset]
237 return [r for r in an if r in subset]
205
238
239 def _ancestors(repo, subset, x, followfirst=False):
240 args = getset(repo, range(len(repo)), x)
241 if not args:
242 return []
243 s = set(_revancestors(repo, args, followfirst)) | set(args)
244 return [r for r in subset if r in s]
245
206 def ancestors(repo, subset, x):
246 def ancestors(repo, subset, x):
207 """``ancestors(set)``
247 """``ancestors(set)``
208 Changesets that are ancestors of a changeset in set.
248 Changesets that are ancestors of a changeset in set.
209 """
249 """
210 args = getset(repo, range(len(repo)), x)
250 return _ancestors(repo, subset, x)
211 if not args:
251
212 return []
252 def _firstancestors(repo, subset, x):
213 s = set(repo.changelog.ancestors(*args)) | set(args)
253 # ``_firstancestors(set)``
214 return [r for r in subset if r in s]
254 # Like ``ancestors(set)`` but follows only the first parents.
255 return _ancestors(repo, subset, x, followfirst=True)
215
256
216 def ancestorspec(repo, subset, x, n):
257 def ancestorspec(repo, subset, x, n):
217 """``set~n``
258 """``set~n``
218 Changesets that are the Nth ancestor (first parents only) of a changeset in set.
259 Changesets that are the Nth ancestor (first parents only) of a changeset in set.
219 """
260 """
220 try:
261 try:
221 n = int(n[1])
262 n = int(n[1])
222 except (TypeError, ValueError):
263 except (TypeError, ValueError):
223 raise error.ParseError(_("~ expects a number"))
264 raise error.ParseError(_("~ expects a number"))
224 ps = set()
265 ps = set()
225 cl = repo.changelog
266 cl = repo.changelog
226 for r in getset(repo, subset, x):
267 for r in getset(repo, subset, x):
227 for i in range(n):
268 for i in range(n):
228 r = cl.parentrevs(r)[0]
269 r = cl.parentrevs(r)[0]
229 ps.add(r)
270 ps.add(r)
230 return [r for r in subset if r in ps]
271 return [r for r in subset if r in ps]
231
272
232 def author(repo, subset, x):
273 def author(repo, subset, x):
233 """``author(string)``
274 """``author(string)``
234 Alias for ``user(string)``.
275 Alias for ``user(string)``.
235 """
276 """
236 # i18n: "author" is a keyword
277 # i18n: "author" is a keyword
237 n = encoding.lower(getstring(x, _("author requires a string")))
278 n = encoding.lower(getstring(x, _("author requires a string")))
238 return [r for r in subset if n in encoding.lower(repo[r].user())]
279 return [r for r in subset if n in encoding.lower(repo[r].user())]
239
280
240 def bisect(repo, subset, x):
281 def bisect(repo, subset, x):
241 """``bisect(string)``
282 """``bisect(string)``
242 Changesets marked in the specified bisect status:
283 Changesets marked in the specified bisect status:
243
284
244 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
285 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
245 - ``goods``, ``bads`` : csets topologicaly good/bad
286 - ``goods``, ``bads`` : csets topologicaly good/bad
246 - ``range`` : csets taking part in the bisection
287 - ``range`` : csets taking part in the bisection
247 - ``pruned`` : csets that are goods, bads or skipped
288 - ``pruned`` : csets that are goods, bads or skipped
248 - ``untested`` : csets whose fate is yet unknown
289 - ``untested`` : csets whose fate is yet unknown
249 - ``ignored`` : csets ignored due to DAG topology
290 - ``ignored`` : csets ignored due to DAG topology
250 """
291 """
251 status = getstring(x, _("bisect requires a string")).lower()
292 status = getstring(x, _("bisect requires a string")).lower()
252 return [r for r in subset if r in hbisect.get(repo, status)]
293 return [r for r in subset if r in hbisect.get(repo, status)]
253
294
254 # Backward-compatibility
295 # Backward-compatibility
255 # - no help entry so that we do not advertise it any more
296 # - no help entry so that we do not advertise it any more
256 def bisected(repo, subset, x):
297 def bisected(repo, subset, x):
257 return bisect(repo, subset, x)
298 return bisect(repo, subset, x)
258
299
259 def bookmark(repo, subset, x):
300 def bookmark(repo, subset, x):
260 """``bookmark([name])``
301 """``bookmark([name])``
261 The named bookmark or all bookmarks.
302 The named bookmark or all bookmarks.
262 """
303 """
263 # i18n: "bookmark" is a keyword
304 # i18n: "bookmark" is a keyword
264 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
305 args = getargs(x, 0, 1, _('bookmark takes one or no arguments'))
265 if args:
306 if args:
266 bm = getstring(args[0],
307 bm = getstring(args[0],
267 # i18n: "bookmark" is a keyword
308 # i18n: "bookmark" is a keyword
268 _('the argument to bookmark must be a string'))
309 _('the argument to bookmark must be a string'))
269 bmrev = bookmarksmod.listbookmarks(repo).get(bm, None)
310 bmrev = bookmarksmod.listbookmarks(repo).get(bm, None)
270 if not bmrev:
311 if not bmrev:
271 raise util.Abort(_("bookmark '%s' does not exist") % bm)
312 raise util.Abort(_("bookmark '%s' does not exist") % bm)
272 bmrev = repo[bmrev].rev()
313 bmrev = repo[bmrev].rev()
273 return [r for r in subset if r == bmrev]
314 return [r for r in subset if r == bmrev]
274 bms = set([repo[r].rev()
315 bms = set([repo[r].rev()
275 for r in bookmarksmod.listbookmarks(repo).values()])
316 for r in bookmarksmod.listbookmarks(repo).values()])
276 return [r for r in subset if r in bms]
317 return [r for r in subset if r in bms]
277
318
278 def branch(repo, subset, x):
319 def branch(repo, subset, x):
279 """``branch(string or set)``
320 """``branch(string or set)``
280 All changesets belonging to the given branch or the branches of the given
321 All changesets belonging to the given branch or the branches of the given
281 changesets.
322 changesets.
282 """
323 """
283 try:
324 try:
284 b = getstring(x, '')
325 b = getstring(x, '')
285 if b in repo.branchmap():
326 if b in repo.branchmap():
286 return [r for r in subset if repo[r].branch() == b]
327 return [r for r in subset if repo[r].branch() == b]
287 except error.ParseError:
328 except error.ParseError:
288 # not a string, but another revspec, e.g. tip()
329 # not a string, but another revspec, e.g. tip()
289 pass
330 pass
290
331
291 s = getset(repo, range(len(repo)), x)
332 s = getset(repo, range(len(repo)), x)
292 b = set()
333 b = set()
293 for r in s:
334 for r in s:
294 b.add(repo[r].branch())
335 b.add(repo[r].branch())
295 s = set(s)
336 s = set(s)
296 return [r for r in subset if r in s or repo[r].branch() in b]
337 return [r for r in subset if r in s or repo[r].branch() in b]
297
338
298 def checkstatus(repo, subset, pat, field):
339 def checkstatus(repo, subset, pat, field):
299 m = None
340 m = None
300 s = []
341 s = []
301 fast = not matchmod.patkind(pat)
342 fast = not matchmod.patkind(pat)
302 for r in subset:
343 for r in subset:
303 c = repo[r]
344 c = repo[r]
304 if fast:
345 if fast:
305 if pat not in c.files():
346 if pat not in c.files():
306 continue
347 continue
307 else:
348 else:
308 if not m or matchmod.patkind(pat) == 'set':
349 if not m or matchmod.patkind(pat) == 'set':
309 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
350 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
310 for f in c.files():
351 for f in c.files():
311 if m(f):
352 if m(f):
312 break
353 break
313 else:
354 else:
314 continue
355 continue
315 files = repo.status(c.p1().node(), c.node())[field]
356 files = repo.status(c.p1().node(), c.node())[field]
316 if fast:
357 if fast:
317 if pat in files:
358 if pat in files:
318 s.append(r)
359 s.append(r)
319 else:
360 else:
320 for f in files:
361 for f in files:
321 if m(f):
362 if m(f):
322 s.append(r)
363 s.append(r)
323 break
364 break
324 return s
365 return s
325
366
326 def _children(repo, narrow, s):
367 def _children(repo, narrow, s):
327 cs = set()
368 cs = set()
328 pr = repo.changelog.parentrevs
369 pr = repo.changelog.parentrevs
329 s = set(s)
370 s = set(s)
330 for r in xrange(len(repo)):
371 for r in xrange(len(repo)):
331 for p in pr(r):
372 for p in pr(r):
332 if p in s:
373 if p in s:
333 cs.add(r)
374 cs.add(r)
334 return cs
375 return cs
335
376
336 def children(repo, subset, x):
377 def children(repo, subset, x):
337 """``children(set)``
378 """``children(set)``
338 Child changesets of changesets in set.
379 Child changesets of changesets in set.
339 """
380 """
340 s = getset(repo, range(len(repo)), x)
381 s = getset(repo, range(len(repo)), x)
341 cs = _children(repo, subset, s)
382 cs = _children(repo, subset, s)
342 return [r for r in subset if r in cs]
383 return [r for r in subset if r in cs]
343
384
344 def closed(repo, subset, x):
385 def closed(repo, subset, x):
345 """``closed()``
386 """``closed()``
346 Changeset is closed.
387 Changeset is closed.
347 """
388 """
348 # i18n: "closed" is a keyword
389 # i18n: "closed" is a keyword
349 getargs(x, 0, 0, _("closed takes no arguments"))
390 getargs(x, 0, 0, _("closed takes no arguments"))
350 return [r for r in subset if repo[r].extra().get('close')]
391 return [r for r in subset if repo[r].extra().get('close')]
351
392
352 def contains(repo, subset, x):
393 def contains(repo, subset, x):
353 """``contains(pattern)``
394 """``contains(pattern)``
354 Revision contains a file matching pattern. See :hg:`help patterns`
395 Revision contains a file matching pattern. See :hg:`help patterns`
355 for information about file patterns.
396 for information about file patterns.
356 """
397 """
357 # i18n: "contains" is a keyword
398 # i18n: "contains" is a keyword
358 pat = getstring(x, _("contains requires a pattern"))
399 pat = getstring(x, _("contains requires a pattern"))
359 m = None
400 m = None
360 s = []
401 s = []
361 if not matchmod.patkind(pat):
402 if not matchmod.patkind(pat):
362 for r in subset:
403 for r in subset:
363 if pat in repo[r]:
404 if pat in repo[r]:
364 s.append(r)
405 s.append(r)
365 else:
406 else:
366 for r in subset:
407 for r in subset:
367 c = repo[r]
408 c = repo[r]
368 if not m or matchmod.patkind(pat) == 'set':
409 if not m or matchmod.patkind(pat) == 'set':
369 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
410 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
370 for f in c.manifest():
411 for f in c.manifest():
371 if m(f):
412 if m(f):
372 s.append(r)
413 s.append(r)
373 break
414 break
374 return s
415 return s
375
416
376 def date(repo, subset, x):
417 def date(repo, subset, x):
377 """``date(interval)``
418 """``date(interval)``
378 Changesets within the interval, see :hg:`help dates`.
419 Changesets within the interval, see :hg:`help dates`.
379 """
420 """
380 # i18n: "date" is a keyword
421 # i18n: "date" is a keyword
381 ds = getstring(x, _("date requires a string"))
422 ds = getstring(x, _("date requires a string"))
382 dm = util.matchdate(ds)
423 dm = util.matchdate(ds)
383 return [r for r in subset if dm(repo[r].date()[0])]
424 return [r for r in subset if dm(repo[r].date()[0])]
384
425
385 def desc(repo, subset, x):
426 def desc(repo, subset, x):
386 """``desc(string)``
427 """``desc(string)``
387 Search commit message for string. The match is case-insensitive.
428 Search commit message for string. The match is case-insensitive.
388 """
429 """
389 # i18n: "desc" is a keyword
430 # i18n: "desc" is a keyword
390 ds = encoding.lower(getstring(x, _("desc requires a string")))
431 ds = encoding.lower(getstring(x, _("desc requires a string")))
391 l = []
432 l = []
392 for r in subset:
433 for r in subset:
393 c = repo[r]
434 c = repo[r]
394 if ds in encoding.lower(c.description()):
435 if ds in encoding.lower(c.description()):
395 l.append(r)
436 l.append(r)
396 return l
437 return l
397
438
439 def _descendants(repo, subset, x, followfirst=False):
440 args = getset(repo, range(len(repo)), x)
441 if not args:
442 return []
443 s = set(_revdescendants(repo, args, followfirst)) | set(args)
444 return [r for r in subset if r in s]
445
398 def descendants(repo, subset, x):
446 def descendants(repo, subset, x):
399 """``descendants(set)``
447 """``descendants(set)``
400 Changesets which are descendants of changesets in set.
448 Changesets which are descendants of changesets in set.
401 """
449 """
402 args = getset(repo, range(len(repo)), x)
450 return _descendants(repo, subset, x)
403 if not args:
451
404 return []
452 def _firstdescendants(repo, subset, x):
405 s = set(repo.changelog.descendants(*args)) | set(args)
453 # ``_firstdescendants(set)``
406 return [r for r in subset if r in s]
454 # Like ``descendants(set)`` but follows only the first parents.
455 return _descendants(repo, subset, x, followfirst=True)
407
456
408 def draft(repo, subset, x):
457 def draft(repo, subset, x):
409 """``draft()``
458 """``draft()``
410 Changeset in draft phase."""
459 Changeset in draft phase."""
411 getargs(x, 0, 0, _("draft takes no arguments"))
460 getargs(x, 0, 0, _("draft takes no arguments"))
412 return [r for r in subset if repo._phaserev[r] == phases.draft]
461 return [r for r in subset if repo._phaserev[r] == phases.draft]
413
462
414 def filelog(repo, subset, x):
463 def filelog(repo, subset, x):
415 """``filelog(pattern)``
464 """``filelog(pattern)``
416 Changesets connected to the specified filelog.
465 Changesets connected to the specified filelog.
417 """
466 """
418
467
419 pat = getstring(x, _("filelog requires a pattern"))
468 pat = getstring(x, _("filelog requires a pattern"))
420 m = matchmod.match(repo.root, repo.getcwd(), [pat], default='relpath',
469 m = matchmod.match(repo.root, repo.getcwd(), [pat], default='relpath',
421 ctx=repo[None])
470 ctx=repo[None])
422 s = set()
471 s = set()
423
472
424 if not matchmod.patkind(pat):
473 if not matchmod.patkind(pat):
425 for f in m.files():
474 for f in m.files():
426 fl = repo.file(f)
475 fl = repo.file(f)
427 for fr in fl:
476 for fr in fl:
428 s.add(fl.linkrev(fr))
477 s.add(fl.linkrev(fr))
429 else:
478 else:
430 for f in repo[None]:
479 for f in repo[None]:
431 if m(f):
480 if m(f):
432 fl = repo.file(f)
481 fl = repo.file(f)
433 for fr in fl:
482 for fr in fl:
434 s.add(fl.linkrev(fr))
483 s.add(fl.linkrev(fr))
435
484
436 return [r for r in subset if r in s]
485 return [r for r in subset if r in s]
437
486
438 def first(repo, subset, x):
487 def first(repo, subset, x):
439 """``first(set, [n])``
488 """``first(set, [n])``
440 An alias for limit().
489 An alias for limit().
441 """
490 """
442 return limit(repo, subset, x)
491 return limit(repo, subset, x)
443
492
444 def _follow(repo, subset, x, name, followfirst=False):
493 def _follow(repo, subset, x, name, followfirst=False):
445 l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
494 l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
446 c = repo['.']
495 c = repo['.']
447 if l:
496 if l:
448 x = getstring(l[0], _("%s expected a filename") % name)
497 x = getstring(l[0], _("%s expected a filename") % name)
449 if x in c:
498 if x in c:
450 cx = c[x]
499 cx = c[x]
451 s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
500 s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
452 # include the revision responsible for the most recent version
501 # include the revision responsible for the most recent version
453 s.add(cx.linkrev())
502 s.add(cx.linkrev())
454 else:
503 else:
455 return []
504 return []
456 else:
505 else:
457 cut = followfirst and 1 or None
506 s = set(_revancestors(repo, [c.rev()], followfirst)) | set([c.rev()])
458 cl = repo.changelog
459 s = set()
460 visit = [c.rev()]
461 while visit:
462 for prev in cl.parentrevs(visit.pop(0))[:cut]:
463 if prev not in s and prev != nodemod.nullrev:
464 visit.append(prev)
465 s.add(prev)
466 s.add(c.rev())
467
507
468 return [r for r in subset if r in s]
508 return [r for r in subset if r in s]
469
509
470 def follow(repo, subset, x):
510 def follow(repo, subset, x):
471 """``follow([file])``
511 """``follow([file])``
472 An alias for ``::.`` (ancestors of the working copy's first parent).
512 An alias for ``::.`` (ancestors of the working copy's first parent).
473 If a filename is specified, the history of the given file is followed,
513 If a filename is specified, the history of the given file is followed,
474 including copies.
514 including copies.
475 """
515 """
476 return _follow(repo, subset, x, 'follow')
516 return _follow(repo, subset, x, 'follow')
477
517
478 def _followfirst(repo, subset, x):
518 def _followfirst(repo, subset, x):
479 # ``followfirst([file])``
519 # ``followfirst([file])``
480 # Like ``follow([file])`` but follows only the first parent of
520 # Like ``follow([file])`` but follows only the first parent of
481 # every revision or file revision.
521 # every revision or file revision.
482 return _follow(repo, subset, x, '_followfirst', followfirst=True)
522 return _follow(repo, subset, x, '_followfirst', followfirst=True)
483
523
484 def getall(repo, subset, x):
524 def getall(repo, subset, x):
485 """``all()``
525 """``all()``
486 All changesets, the same as ``0:tip``.
526 All changesets, the same as ``0:tip``.
487 """
527 """
488 # i18n: "all" is a keyword
528 # i18n: "all" is a keyword
489 getargs(x, 0, 0, _("all takes no arguments"))
529 getargs(x, 0, 0, _("all takes no arguments"))
490 return subset
530 return subset
491
531
492 def grep(repo, subset, x):
532 def grep(repo, subset, x):
493 """``grep(regex)``
533 """``grep(regex)``
494 Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
534 Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')``
495 to ensure special escape characters are handled correctly. Unlike
535 to ensure special escape characters are handled correctly. Unlike
496 ``keyword(string)``, the match is case-sensitive.
536 ``keyword(string)``, the match is case-sensitive.
497 """
537 """
498 try:
538 try:
499 # i18n: "grep" is a keyword
539 # i18n: "grep" is a keyword
500 gr = re.compile(getstring(x, _("grep requires a string")))
540 gr = re.compile(getstring(x, _("grep requires a string")))
501 except re.error, e:
541 except re.error, e:
502 raise error.ParseError(_('invalid match pattern: %s') % e)
542 raise error.ParseError(_('invalid match pattern: %s') % e)
503 l = []
543 l = []
504 for r in subset:
544 for r in subset:
505 c = repo[r]
545 c = repo[r]
506 for e in c.files() + [c.user(), c.description()]:
546 for e in c.files() + [c.user(), c.description()]:
507 if gr.search(e):
547 if gr.search(e):
508 l.append(r)
548 l.append(r)
509 break
549 break
510 return l
550 return l
511
551
512 def _matchfiles(repo, subset, x):
552 def _matchfiles(repo, subset, x):
513 # _matchfiles takes a revset list of prefixed arguments:
553 # _matchfiles takes a revset list of prefixed arguments:
514 #
554 #
515 # [p:foo, i:bar, x:baz]
555 # [p:foo, i:bar, x:baz]
516 #
556 #
517 # builds a match object from them and filters subset. Allowed
557 # builds a match object from them and filters subset. Allowed
518 # prefixes are 'p:' for regular patterns, 'i:' for include
558 # prefixes are 'p:' for regular patterns, 'i:' for include
519 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
559 # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
520 # a revision identifier, or the empty string to reference the
560 # a revision identifier, or the empty string to reference the
521 # working directory, from which the match object is
561 # working directory, from which the match object is
522 # initialized. At most one 'r:' argument can be passed.
562 # initialized. At most one 'r:' argument can be passed.
523
563
524 # i18n: "_matchfiles" is a keyword
564 # i18n: "_matchfiles" is a keyword
525 l = getargs(x, 1, -1, _("_matchfiles requires at least one argument"))
565 l = getargs(x, 1, -1, _("_matchfiles requires at least one argument"))
526 pats, inc, exc = [], [], []
566 pats, inc, exc = [], [], []
527 hasset = False
567 hasset = False
528 rev = None
568 rev = None
529 for arg in l:
569 for arg in l:
530 s = getstring(arg, _("_matchfiles requires string arguments"))
570 s = getstring(arg, _("_matchfiles requires string arguments"))
531 prefix, value = s[:2], s[2:]
571 prefix, value = s[:2], s[2:]
532 if prefix == 'p:':
572 if prefix == 'p:':
533 pats.append(value)
573 pats.append(value)
534 elif prefix == 'i:':
574 elif prefix == 'i:':
535 inc.append(value)
575 inc.append(value)
536 elif prefix == 'x:':
576 elif prefix == 'x:':
537 exc.append(value)
577 exc.append(value)
538 elif prefix == 'r:':
578 elif prefix == 'r:':
539 if rev is not None:
579 if rev is not None:
540 raise error.ParseError(_('_matchfiles expected at most one '
580 raise error.ParseError(_('_matchfiles expected at most one '
541 'revision'))
581 'revision'))
542 rev = value
582 rev = value
543 else:
583 else:
544 raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix)
584 raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix)
545 if not hasset and matchmod.patkind(value) == 'set':
585 if not hasset and matchmod.patkind(value) == 'set':
546 hasset = True
586 hasset = True
547 m = None
587 m = None
548 s = []
588 s = []
549 for r in subset:
589 for r in subset:
550 c = repo[r]
590 c = repo[r]
551 if not m or (hasset and rev is None):
591 if not m or (hasset and rev is None):
552 ctx = c
592 ctx = c
553 if rev is not None:
593 if rev is not None:
554 ctx = repo[rev or None]
594 ctx = repo[rev or None]
555 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
595 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
556 exclude=exc, ctx=ctx)
596 exclude=exc, ctx=ctx)
557 for f in c.files():
597 for f in c.files():
558 if m(f):
598 if m(f):
559 s.append(r)
599 s.append(r)
560 break
600 break
561 return s
601 return s
562
602
563 def hasfile(repo, subset, x):
603 def hasfile(repo, subset, x):
564 """``file(pattern)``
604 """``file(pattern)``
565 Changesets affecting files matched by pattern.
605 Changesets affecting files matched by pattern.
566 """
606 """
567 # i18n: "file" is a keyword
607 # i18n: "file" is a keyword
568 pat = getstring(x, _("file requires a pattern"))
608 pat = getstring(x, _("file requires a pattern"))
569 return _matchfiles(repo, subset, ('string', 'p:' + pat))
609 return _matchfiles(repo, subset, ('string', 'p:' + pat))
570
610
571 def head(repo, subset, x):
611 def head(repo, subset, x):
572 """``head()``
612 """``head()``
573 Changeset is a named branch head.
613 Changeset is a named branch head.
574 """
614 """
575 # i18n: "head" is a keyword
615 # i18n: "head" is a keyword
576 getargs(x, 0, 0, _("head takes no arguments"))
616 getargs(x, 0, 0, _("head takes no arguments"))
577 hs = set()
617 hs = set()
578 for b, ls in repo.branchmap().iteritems():
618 for b, ls in repo.branchmap().iteritems():
579 hs.update(repo[h].rev() for h in ls)
619 hs.update(repo[h].rev() for h in ls)
580 return [r for r in subset if r in hs]
620 return [r for r in subset if r in hs]
581
621
582 def heads(repo, subset, x):
622 def heads(repo, subset, x):
583 """``heads(set)``
623 """``heads(set)``
584 Members of set with no children in set.
624 Members of set with no children in set.
585 """
625 """
586 s = getset(repo, subset, x)
626 s = getset(repo, subset, x)
587 ps = set(parents(repo, subset, x))
627 ps = set(parents(repo, subset, x))
588 return [r for r in s if r not in ps]
628 return [r for r in s if r not in ps]
589
629
590 def keyword(repo, subset, x):
630 def keyword(repo, subset, x):
591 """``keyword(string)``
631 """``keyword(string)``
592 Search commit message, user name, and names of changed files for
632 Search commit message, user name, and names of changed files for
593 string. The match is case-insensitive.
633 string. The match is case-insensitive.
594 """
634 """
595 # i18n: "keyword" is a keyword
635 # i18n: "keyword" is a keyword
596 kw = encoding.lower(getstring(x, _("keyword requires a string")))
636 kw = encoding.lower(getstring(x, _("keyword requires a string")))
597 l = []
637 l = []
598 for r in subset:
638 for r in subset:
599 c = repo[r]
639 c = repo[r]
600 t = " ".join(c.files() + [c.user(), c.description()])
640 t = " ".join(c.files() + [c.user(), c.description()])
601 if kw in encoding.lower(t):
641 if kw in encoding.lower(t):
602 l.append(r)
642 l.append(r)
603 return l
643 return l
604
644
605 def limit(repo, subset, x):
645 def limit(repo, subset, x):
606 """``limit(set, [n])``
646 """``limit(set, [n])``
607 First n members of set, defaulting to 1.
647 First n members of set, defaulting to 1.
608 """
648 """
609 # i18n: "limit" is a keyword
649 # i18n: "limit" is a keyword
610 l = getargs(x, 1, 2, _("limit requires one or two arguments"))
650 l = getargs(x, 1, 2, _("limit requires one or two arguments"))
611 try:
651 try:
612 lim = 1
652 lim = 1
613 if len(l) == 2:
653 if len(l) == 2:
614 # i18n: "limit" is a keyword
654 # i18n: "limit" is a keyword
615 lim = int(getstring(l[1], _("limit requires a number")))
655 lim = int(getstring(l[1], _("limit requires a number")))
616 except (TypeError, ValueError):
656 except (TypeError, ValueError):
617 # i18n: "limit" is a keyword
657 # i18n: "limit" is a keyword
618 raise error.ParseError(_("limit expects a number"))
658 raise error.ParseError(_("limit expects a number"))
619 ss = set(subset)
659 ss = set(subset)
620 os = getset(repo, range(len(repo)), l[0])[:lim]
660 os = getset(repo, range(len(repo)), l[0])[:lim]
621 return [r for r in os if r in ss]
661 return [r for r in os if r in ss]
622
662
623 def last(repo, subset, x):
663 def last(repo, subset, x):
624 """``last(set, [n])``
664 """``last(set, [n])``
625 Last n members of set, defaulting to 1.
665 Last n members of set, defaulting to 1.
626 """
666 """
627 # i18n: "last" is a keyword
667 # i18n: "last" is a keyword
628 l = getargs(x, 1, 2, _("last requires one or two arguments"))
668 l = getargs(x, 1, 2, _("last requires one or two arguments"))
629 try:
669 try:
630 lim = 1
670 lim = 1
631 if len(l) == 2:
671 if len(l) == 2:
632 # i18n: "last" is a keyword
672 # i18n: "last" is a keyword
633 lim = int(getstring(l[1], _("last requires a number")))
673 lim = int(getstring(l[1], _("last requires a number")))
634 except (TypeError, ValueError):
674 except (TypeError, ValueError):
635 # i18n: "last" is a keyword
675 # i18n: "last" is a keyword
636 raise error.ParseError(_("last expects a number"))
676 raise error.ParseError(_("last expects a number"))
637 ss = set(subset)
677 ss = set(subset)
638 os = getset(repo, range(len(repo)), l[0])[-lim:]
678 os = getset(repo, range(len(repo)), l[0])[-lim:]
639 return [r for r in os if r in ss]
679 return [r for r in os if r in ss]
640
680
641 def maxrev(repo, subset, x):
681 def maxrev(repo, subset, x):
642 """``max(set)``
682 """``max(set)``
643 Changeset with highest revision number in set.
683 Changeset with highest revision number in set.
644 """
684 """
645 os = getset(repo, range(len(repo)), x)
685 os = getset(repo, range(len(repo)), x)
646 if os:
686 if os:
647 m = max(os)
687 m = max(os)
648 if m in subset:
688 if m in subset:
649 return [m]
689 return [m]
650 return []
690 return []
651
691
652 def merge(repo, subset, x):
692 def merge(repo, subset, x):
653 """``merge()``
693 """``merge()``
654 Changeset is a merge changeset.
694 Changeset is a merge changeset.
655 """
695 """
656 # i18n: "merge" is a keyword
696 # i18n: "merge" is a keyword
657 getargs(x, 0, 0, _("merge takes no arguments"))
697 getargs(x, 0, 0, _("merge takes no arguments"))
658 cl = repo.changelog
698 cl = repo.changelog
659 return [r for r in subset if cl.parentrevs(r)[1] != -1]
699 return [r for r in subset if cl.parentrevs(r)[1] != -1]
660
700
661 def minrev(repo, subset, x):
701 def minrev(repo, subset, x):
662 """``min(set)``
702 """``min(set)``
663 Changeset with lowest revision number in set.
703 Changeset with lowest revision number in set.
664 """
704 """
665 os = getset(repo, range(len(repo)), x)
705 os = getset(repo, range(len(repo)), x)
666 if os:
706 if os:
667 m = min(os)
707 m = min(os)
668 if m in subset:
708 if m in subset:
669 return [m]
709 return [m]
670 return []
710 return []
671
711
672 def modifies(repo, subset, x):
712 def modifies(repo, subset, x):
673 """``modifies(pattern)``
713 """``modifies(pattern)``
674 Changesets modifying files matched by pattern.
714 Changesets modifying files matched by pattern.
675 """
715 """
676 # i18n: "modifies" is a keyword
716 # i18n: "modifies" is a keyword
677 pat = getstring(x, _("modifies requires a pattern"))
717 pat = getstring(x, _("modifies requires a pattern"))
678 return checkstatus(repo, subset, pat, 0)
718 return checkstatus(repo, subset, pat, 0)
679
719
680 def node(repo, subset, x):
720 def node(repo, subset, x):
681 """``id(string)``
721 """``id(string)``
682 Revision non-ambiguously specified by the given hex string prefix.
722 Revision non-ambiguously specified by the given hex string prefix.
683 """
723 """
684 # i18n: "id" is a keyword
724 # i18n: "id" is a keyword
685 l = getargs(x, 1, 1, _("id requires one argument"))
725 l = getargs(x, 1, 1, _("id requires one argument"))
686 # i18n: "id" is a keyword
726 # i18n: "id" is a keyword
687 n = getstring(l[0], _("id requires a string"))
727 n = getstring(l[0], _("id requires a string"))
688 if len(n) == 40:
728 if len(n) == 40:
689 rn = repo[n].rev()
729 rn = repo[n].rev()
690 else:
730 else:
691 rn = repo.changelog.rev(repo.changelog._partialmatch(n))
731 rn = repo.changelog.rev(repo.changelog._partialmatch(n))
692 return [r for r in subset if r == rn]
732 return [r for r in subset if r == rn]
693
733
694 def outgoing(repo, subset, x):
734 def outgoing(repo, subset, x):
695 """``outgoing([path])``
735 """``outgoing([path])``
696 Changesets not found in the specified destination repository, or the
736 Changesets not found in the specified destination repository, or the
697 default push location.
737 default push location.
698 """
738 """
699 import hg # avoid start-up nasties
739 import hg # avoid start-up nasties
700 # i18n: "outgoing" is a keyword
740 # i18n: "outgoing" is a keyword
701 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
741 l = getargs(x, 0, 1, _("outgoing takes one or no arguments"))
702 # i18n: "outgoing" is a keyword
742 # i18n: "outgoing" is a keyword
703 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
743 dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
704 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
744 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
705 dest, branches = hg.parseurl(dest)
745 dest, branches = hg.parseurl(dest)
706 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
746 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
707 if revs:
747 if revs:
708 revs = [repo.lookup(rev) for rev in revs]
748 revs = [repo.lookup(rev) for rev in revs]
709 other = hg.peer(repo, {}, dest)
749 other = hg.peer(repo, {}, dest)
710 repo.ui.pushbuffer()
750 repo.ui.pushbuffer()
711 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
751 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs)
712 repo.ui.popbuffer()
752 repo.ui.popbuffer()
713 cl = repo.changelog
753 cl = repo.changelog
714 o = set([cl.rev(r) for r in outgoing.missing])
754 o = set([cl.rev(r) for r in outgoing.missing])
715 return [r for r in subset if r in o]
755 return [r for r in subset if r in o]
716
756
717 def p1(repo, subset, x):
757 def p1(repo, subset, x):
718 """``p1([set])``
758 """``p1([set])``
719 First parent of changesets in set, or the working directory.
759 First parent of changesets in set, or the working directory.
720 """
760 """
721 if x is None:
761 if x is None:
722 p = repo[x].p1().rev()
762 p = repo[x].p1().rev()
723 return [r for r in subset if r == p]
763 return [r for r in subset if r == p]
724
764
725 ps = set()
765 ps = set()
726 cl = repo.changelog
766 cl = repo.changelog
727 for r in getset(repo, range(len(repo)), x):
767 for r in getset(repo, range(len(repo)), x):
728 ps.add(cl.parentrevs(r)[0])
768 ps.add(cl.parentrevs(r)[0])
729 return [r for r in subset if r in ps]
769 return [r for r in subset if r in ps]
730
770
731 def p2(repo, subset, x):
771 def p2(repo, subset, x):
732 """``p2([set])``
772 """``p2([set])``
733 Second parent of changesets in set, or the working directory.
773 Second parent of changesets in set, or the working directory.
734 """
774 """
735 if x is None:
775 if x is None:
736 ps = repo[x].parents()
776 ps = repo[x].parents()
737 try:
777 try:
738 p = ps[1].rev()
778 p = ps[1].rev()
739 return [r for r in subset if r == p]
779 return [r for r in subset if r == p]
740 except IndexError:
780 except IndexError:
741 return []
781 return []
742
782
743 ps = set()
783 ps = set()
744 cl = repo.changelog
784 cl = repo.changelog
745 for r in getset(repo, range(len(repo)), x):
785 for r in getset(repo, range(len(repo)), x):
746 ps.add(cl.parentrevs(r)[1])
786 ps.add(cl.parentrevs(r)[1])
747 return [r for r in subset if r in ps]
787 return [r for r in subset if r in ps]
748
788
749 def parents(repo, subset, x):
789 def parents(repo, subset, x):
750 """``parents([set])``
790 """``parents([set])``
751 The set of all parents for all changesets in set, or the working directory.
791 The set of all parents for all changesets in set, or the working directory.
752 """
792 """
753 if x is None:
793 if x is None:
754 ps = tuple(p.rev() for p in repo[x].parents())
794 ps = tuple(p.rev() for p in repo[x].parents())
755 return [r for r in subset if r in ps]
795 return [r for r in subset if r in ps]
756
796
757 ps = set()
797 ps = set()
758 cl = repo.changelog
798 cl = repo.changelog
759 for r in getset(repo, range(len(repo)), x):
799 for r in getset(repo, range(len(repo)), x):
760 ps.update(cl.parentrevs(r))
800 ps.update(cl.parentrevs(r))
761 return [r for r in subset if r in ps]
801 return [r for r in subset if r in ps]
762
802
763 def parentspec(repo, subset, x, n):
803 def parentspec(repo, subset, x, n):
764 """``set^0``
804 """``set^0``
765 The set.
805 The set.
766 ``set^1`` (or ``set^``), ``set^2``
806 ``set^1`` (or ``set^``), ``set^2``
767 First or second parent, respectively, of all changesets in set.
807 First or second parent, respectively, of all changesets in set.
768 """
808 """
769 try:
809 try:
770 n = int(n[1])
810 n = int(n[1])
771 if n not in (0, 1, 2):
811 if n not in (0, 1, 2):
772 raise ValueError
812 raise ValueError
773 except (TypeError, ValueError):
813 except (TypeError, ValueError):
774 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
814 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
775 ps = set()
815 ps = set()
776 cl = repo.changelog
816 cl = repo.changelog
777 for r in getset(repo, subset, x):
817 for r in getset(repo, subset, x):
778 if n == 0:
818 if n == 0:
779 ps.add(r)
819 ps.add(r)
780 elif n == 1:
820 elif n == 1:
781 ps.add(cl.parentrevs(r)[0])
821 ps.add(cl.parentrevs(r)[0])
782 elif n == 2:
822 elif n == 2:
783 parents = cl.parentrevs(r)
823 parents = cl.parentrevs(r)
784 if len(parents) > 1:
824 if len(parents) > 1:
785 ps.add(parents[1])
825 ps.add(parents[1])
786 return [r for r in subset if r in ps]
826 return [r for r in subset if r in ps]
787
827
788 def present(repo, subset, x):
828 def present(repo, subset, x):
789 """``present(set)``
829 """``present(set)``
790 An empty set, if any revision in set isn't found; otherwise,
830 An empty set, if any revision in set isn't found; otherwise,
791 all revisions in set.
831 all revisions in set.
792 """
832 """
793 try:
833 try:
794 return getset(repo, subset, x)
834 return getset(repo, subset, x)
795 except error.RepoLookupError:
835 except error.RepoLookupError:
796 return []
836 return []
797
837
798 def public(repo, subset, x):
838 def public(repo, subset, x):
799 """``public()``
839 """``public()``
800 Changeset in public phase."""
840 Changeset in public phase."""
801 getargs(x, 0, 0, _("public takes no arguments"))
841 getargs(x, 0, 0, _("public takes no arguments"))
802 return [r for r in subset if repo._phaserev[r] == phases.public]
842 return [r for r in subset if repo._phaserev[r] == phases.public]
803
843
804 def remote(repo, subset, x):
844 def remote(repo, subset, x):
805 """``remote([id [,path]])``
845 """``remote([id [,path]])``
806 Local revision that corresponds to the given identifier in a
846 Local revision that corresponds to the given identifier in a
807 remote repository, if present. Here, the '.' identifier is a
847 remote repository, if present. Here, the '.' identifier is a
808 synonym for the current local branch.
848 synonym for the current local branch.
809 """
849 """
810
850
811 import hg # avoid start-up nasties
851 import hg # avoid start-up nasties
812 # i18n: "remote" is a keyword
852 # i18n: "remote" is a keyword
813 l = getargs(x, 0, 2, _("remote takes one, two or no arguments"))
853 l = getargs(x, 0, 2, _("remote takes one, two or no arguments"))
814
854
815 q = '.'
855 q = '.'
816 if len(l) > 0:
856 if len(l) > 0:
817 # i18n: "remote" is a keyword
857 # i18n: "remote" is a keyword
818 q = getstring(l[0], _("remote requires a string id"))
858 q = getstring(l[0], _("remote requires a string id"))
819 if q == '.':
859 if q == '.':
820 q = repo['.'].branch()
860 q = repo['.'].branch()
821
861
822 dest = ''
862 dest = ''
823 if len(l) > 1:
863 if len(l) > 1:
824 # i18n: "remote" is a keyword
864 # i18n: "remote" is a keyword
825 dest = getstring(l[1], _("remote requires a repository path"))
865 dest = getstring(l[1], _("remote requires a repository path"))
826 dest = repo.ui.expandpath(dest or 'default')
866 dest = repo.ui.expandpath(dest or 'default')
827 dest, branches = hg.parseurl(dest)
867 dest, branches = hg.parseurl(dest)
828 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
868 revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
829 if revs:
869 if revs:
830 revs = [repo.lookup(rev) for rev in revs]
870 revs = [repo.lookup(rev) for rev in revs]
831 other = hg.peer(repo, {}, dest)
871 other = hg.peer(repo, {}, dest)
832 n = other.lookup(q)
872 n = other.lookup(q)
833 if n in repo:
873 if n in repo:
834 r = repo[n].rev()
874 r = repo[n].rev()
835 if r in subset:
875 if r in subset:
836 return [r]
876 return [r]
837 return []
877 return []
838
878
839 def removes(repo, subset, x):
879 def removes(repo, subset, x):
840 """``removes(pattern)``
880 """``removes(pattern)``
841 Changesets which remove files matching pattern.
881 Changesets which remove files matching pattern.
842 """
882 """
843 # i18n: "removes" is a keyword
883 # i18n: "removes" is a keyword
844 pat = getstring(x, _("removes requires a pattern"))
884 pat = getstring(x, _("removes requires a pattern"))
845 return checkstatus(repo, subset, pat, 2)
885 return checkstatus(repo, subset, pat, 2)
846
886
847 def rev(repo, subset, x):
887 def rev(repo, subset, x):
848 """``rev(number)``
888 """``rev(number)``
849 Revision with the given numeric identifier.
889 Revision with the given numeric identifier.
850 """
890 """
851 # i18n: "rev" is a keyword
891 # i18n: "rev" is a keyword
852 l = getargs(x, 1, 1, _("rev requires one argument"))
892 l = getargs(x, 1, 1, _("rev requires one argument"))
853 try:
893 try:
854 # i18n: "rev" is a keyword
894 # i18n: "rev" is a keyword
855 l = int(getstring(l[0], _("rev requires a number")))
895 l = int(getstring(l[0], _("rev requires a number")))
856 except (TypeError, ValueError):
896 except (TypeError, ValueError):
857 # i18n: "rev" is a keyword
897 # i18n: "rev" is a keyword
858 raise error.ParseError(_("rev expects a number"))
898 raise error.ParseError(_("rev expects a number"))
859 return [r for r in subset if r == l]
899 return [r for r in subset if r == l]
860
900
861 def matching(repo, subset, x):
901 def matching(repo, subset, x):
862 """``matching(revision [, field])``
902 """``matching(revision [, field])``
863 Changesets in which a given set of fields match the set of fields in the
903 Changesets in which a given set of fields match the set of fields in the
864 selected revision or set.
904 selected revision or set.
865 To match more than one field pass the list of fields to match separated
905 To match more than one field pass the list of fields to match separated
866 by spaces (e.g. 'author description').
906 by spaces (e.g. 'author description').
867 Valid fields are most regular revision fields and some special fields:
907 Valid fields are most regular revision fields and some special fields:
868 * regular fields:
908 * regular fields:
869 - description, author, branch, date, files, phase, parents,
909 - description, author, branch, date, files, phase, parents,
870 substate, user.
910 substate, user.
871 Note that author and user are synonyms.
911 Note that author and user are synonyms.
872 * special fields: summary, metadata.
912 * special fields: summary, metadata.
873 - summary: matches the first line of the description.
913 - summary: matches the first line of the description.
874 - metatadata: It is equivalent to matching 'description user date'
914 - metatadata: It is equivalent to matching 'description user date'
875 (i.e. it matches the main metadata fields).
915 (i.e. it matches the main metadata fields).
876 metadata is the default field which is used when no fields are specified.
916 metadata is the default field which is used when no fields are specified.
877 You can match more than one field at a time.
917 You can match more than one field at a time.
878 """
918 """
879 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
919 l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
880
920
881 revs = getset(repo, xrange(len(repo)), l[0])
921 revs = getset(repo, xrange(len(repo)), l[0])
882
922
883 fieldlist = ['metadata']
923 fieldlist = ['metadata']
884 if len(l) > 1:
924 if len(l) > 1:
885 fieldlist = getstring(l[1],
925 fieldlist = getstring(l[1],
886 _("matching requires a string "
926 _("matching requires a string "
887 "as its second argument")).split()
927 "as its second argument")).split()
888
928
889 # Make sure that there are no repeated fields, and expand the
929 # Make sure that there are no repeated fields, and expand the
890 # 'special' 'metadata' field type
930 # 'special' 'metadata' field type
891 fields = []
931 fields = []
892 for field in fieldlist:
932 for field in fieldlist:
893 if field == 'metadata':
933 if field == 'metadata':
894 fields += ['user', 'description', 'date']
934 fields += ['user', 'description', 'date']
895 else:
935 else:
896 if field == 'author':
936 if field == 'author':
897 field = 'user'
937 field = 'user'
898 fields.append(field)
938 fields.append(field)
899 fields = set(fields)
939 fields = set(fields)
900
940
901 # We may want to match more than one field
941 # We may want to match more than one field
902 # Each field will be matched with its own "getfield" function
942 # Each field will be matched with its own "getfield" function
903 # which will be added to the getfieldfuncs array of functions
943 # which will be added to the getfieldfuncs array of functions
904 getfieldfuncs = []
944 getfieldfuncs = []
905 _funcs = {
945 _funcs = {
906 'user': lambda r: repo[r].user(),
946 'user': lambda r: repo[r].user(),
907 'branch': lambda r: repo[r].branch(),
947 'branch': lambda r: repo[r].branch(),
908 'date': lambda r: repo[r].date(),
948 'date': lambda r: repo[r].date(),
909 'description': lambda r: repo[r].description(),
949 'description': lambda r: repo[r].description(),
910 'files': lambda r: repo[r].files(),
950 'files': lambda r: repo[r].files(),
911 'parents': lambda r: repo[r].parents(),
951 'parents': lambda r: repo[r].parents(),
912 'phase': lambda r: repo[r].phase(),
952 'phase': lambda r: repo[r].phase(),
913 'substate': lambda r: repo[r].substate,
953 'substate': lambda r: repo[r].substate,
914 'summary': lambda r: repo[r].description().splitlines()[0],
954 'summary': lambda r: repo[r].description().splitlines()[0],
915 }
955 }
916 for info in fields:
956 for info in fields:
917 getfield = _funcs.get(info, None)
957 getfield = _funcs.get(info, None)
918 if getfield is None:
958 if getfield is None:
919 raise error.ParseError(
959 raise error.ParseError(
920 _("unexpected field name passed to matching: %s") % info)
960 _("unexpected field name passed to matching: %s") % info)
921 getfieldfuncs.append(getfield)
961 getfieldfuncs.append(getfield)
922
962
923 # convert the getfield array of functions into a "getinfo" function
963 # convert the getfield array of functions into a "getinfo" function
924 # which returns an array of field values (or a single value if there
964 # which returns an array of field values (or a single value if there
925 # is only one field to match)
965 # is only one field to match)
926 if len(getfieldfuncs) == 1:
966 if len(getfieldfuncs) == 1:
927 getinfo = getfieldfuncs[0]
967 getinfo = getfieldfuncs[0]
928 else:
968 else:
929 getinfo = lambda r: [f(r) for f in getfieldfuncs]
969 getinfo = lambda r: [f(r) for f in getfieldfuncs]
930
970
931 matches = []
971 matches = []
932 for rev in revs:
972 for rev in revs:
933 target = getinfo(rev)
973 target = getinfo(rev)
934 matches += [r for r in subset if getinfo(r) == target]
974 matches += [r for r in subset if getinfo(r) == target]
935 if len(revs) > 1:
975 if len(revs) > 1:
936 matches = sorted(set(matches))
976 matches = sorted(set(matches))
937 return matches
977 return matches
938
978
939 def reverse(repo, subset, x):
979 def reverse(repo, subset, x):
940 """``reverse(set)``
980 """``reverse(set)``
941 Reverse order of set.
981 Reverse order of set.
942 """
982 """
943 l = getset(repo, subset, x)
983 l = getset(repo, subset, x)
944 l.reverse()
984 l.reverse()
945 return l
985 return l
946
986
947 def roots(repo, subset, x):
987 def roots(repo, subset, x):
948 """``roots(set)``
988 """``roots(set)``
949 Changesets with no parent changeset in set.
989 Changesets with no parent changeset in set.
950 """
990 """
951 s = getset(repo, xrange(len(repo)), x)
991 s = getset(repo, xrange(len(repo)), x)
952 cs = _children(repo, s, s)
992 cs = _children(repo, s, s)
953 return [r for r in s if r not in cs]
993 return [r for r in s if r not in cs]
954
994
955 def secret(repo, subset, x):
995 def secret(repo, subset, x):
956 """``secret()``
996 """``secret()``
957 Changeset in secret phase."""
997 Changeset in secret phase."""
958 getargs(x, 0, 0, _("secret takes no arguments"))
998 getargs(x, 0, 0, _("secret takes no arguments"))
959 return [r for r in subset if repo._phaserev[r] == phases.secret]
999 return [r for r in subset if repo._phaserev[r] == phases.secret]
960
1000
961 def sort(repo, subset, x):
1001 def sort(repo, subset, x):
962 """``sort(set[, [-]key...])``
1002 """``sort(set[, [-]key...])``
963 Sort set by keys. The default sort order is ascending, specify a key
1003 Sort set by keys. The default sort order is ascending, specify a key
964 as ``-key`` to sort in descending order.
1004 as ``-key`` to sort in descending order.
965
1005
966 The keys can be:
1006 The keys can be:
967
1007
968 - ``rev`` for the revision number,
1008 - ``rev`` for the revision number,
969 - ``branch`` for the branch name,
1009 - ``branch`` for the branch name,
970 - ``desc`` for the commit message (description),
1010 - ``desc`` for the commit message (description),
971 - ``user`` for user name (``author`` can be used as an alias),
1011 - ``user`` for user name (``author`` can be used as an alias),
972 - ``date`` for the commit date
1012 - ``date`` for the commit date
973 """
1013 """
974 # i18n: "sort" is a keyword
1014 # i18n: "sort" is a keyword
975 l = getargs(x, 1, 2, _("sort requires one or two arguments"))
1015 l = getargs(x, 1, 2, _("sort requires one or two arguments"))
976 keys = "rev"
1016 keys = "rev"
977 if len(l) == 2:
1017 if len(l) == 2:
978 keys = getstring(l[1], _("sort spec must be a string"))
1018 keys = getstring(l[1], _("sort spec must be a string"))
979
1019
980 s = l[0]
1020 s = l[0]
981 keys = keys.split()
1021 keys = keys.split()
982 l = []
1022 l = []
983 def invert(s):
1023 def invert(s):
984 return "".join(chr(255 - ord(c)) for c in s)
1024 return "".join(chr(255 - ord(c)) for c in s)
985 for r in getset(repo, subset, s):
1025 for r in getset(repo, subset, s):
986 c = repo[r]
1026 c = repo[r]
987 e = []
1027 e = []
988 for k in keys:
1028 for k in keys:
989 if k == 'rev':
1029 if k == 'rev':
990 e.append(r)
1030 e.append(r)
991 elif k == '-rev':
1031 elif k == '-rev':
992 e.append(-r)
1032 e.append(-r)
993 elif k == 'branch':
1033 elif k == 'branch':
994 e.append(c.branch())
1034 e.append(c.branch())
995 elif k == '-branch':
1035 elif k == '-branch':
996 e.append(invert(c.branch()))
1036 e.append(invert(c.branch()))
997 elif k == 'desc':
1037 elif k == 'desc':
998 e.append(c.description())
1038 e.append(c.description())
999 elif k == '-desc':
1039 elif k == '-desc':
1000 e.append(invert(c.description()))
1040 e.append(invert(c.description()))
1001 elif k in 'user author':
1041 elif k in 'user author':
1002 e.append(c.user())
1042 e.append(c.user())
1003 elif k in '-user -author':
1043 elif k in '-user -author':
1004 e.append(invert(c.user()))
1044 e.append(invert(c.user()))
1005 elif k == 'date':
1045 elif k == 'date':
1006 e.append(c.date()[0])
1046 e.append(c.date()[0])
1007 elif k == '-date':
1047 elif k == '-date':
1008 e.append(-c.date()[0])
1048 e.append(-c.date()[0])
1009 else:
1049 else:
1010 raise error.ParseError(_("unknown sort key %r") % k)
1050 raise error.ParseError(_("unknown sort key %r") % k)
1011 e.append(r)
1051 e.append(r)
1012 l.append(e)
1052 l.append(e)
1013 l.sort()
1053 l.sort()
1014 return [e[-1] for e in l]
1054 return [e[-1] for e in l]
1015
1055
1016 def tag(repo, subset, x):
1056 def tag(repo, subset, x):
1017 """``tag([name])``
1057 """``tag([name])``
1018 The specified tag by name, or all tagged revisions if no name is given.
1058 The specified tag by name, or all tagged revisions if no name is given.
1019 """
1059 """
1020 # i18n: "tag" is a keyword
1060 # i18n: "tag" is a keyword
1021 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1061 args = getargs(x, 0, 1, _("tag takes one or no arguments"))
1022 cl = repo.changelog
1062 cl = repo.changelog
1023 if args:
1063 if args:
1024 tn = getstring(args[0],
1064 tn = getstring(args[0],
1025 # i18n: "tag" is a keyword
1065 # i18n: "tag" is a keyword
1026 _('the argument to tag must be a string'))
1066 _('the argument to tag must be a string'))
1027 if not repo.tags().get(tn, None):
1067 if not repo.tags().get(tn, None):
1028 raise util.Abort(_("tag '%s' does not exist") % tn)
1068 raise util.Abort(_("tag '%s' does not exist") % tn)
1029 s = set([cl.rev(n) for t, n in repo.tagslist() if t == tn])
1069 s = set([cl.rev(n) for t, n in repo.tagslist() if t == tn])
1030 else:
1070 else:
1031 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
1071 s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
1032 return [r for r in subset if r in s]
1072 return [r for r in subset if r in s]
1033
1073
1034 def tagged(repo, subset, x):
1074 def tagged(repo, subset, x):
1035 return tag(repo, subset, x)
1075 return tag(repo, subset, x)
1036
1076
1037 def user(repo, subset, x):
1077 def user(repo, subset, x):
1038 """``user(string)``
1078 """``user(string)``
1039 User name contains string. The match is case-insensitive.
1079 User name contains string. The match is case-insensitive.
1040 """
1080 """
1041 return author(repo, subset, x)
1081 return author(repo, subset, x)
1042
1082
1043 # for internal use
1083 # for internal use
1044 def _list(repo, subset, x):
1084 def _list(repo, subset, x):
1045 s = getstring(x, "internal error")
1085 s = getstring(x, "internal error")
1046 if not s:
1086 if not s:
1047 return []
1087 return []
1048 if not isinstance(subset, set):
1088 if not isinstance(subset, set):
1049 subset = set(subset)
1089 subset = set(subset)
1050 ls = [repo[r].rev() for r in s.split('\0')]
1090 ls = [repo[r].rev() for r in s.split('\0')]
1051 return [r for r in ls if r in subset]
1091 return [r for r in ls if r in subset]
1052
1092
1053 symbols = {
1093 symbols = {
1054 "adds": adds,
1094 "adds": adds,
1055 "all": getall,
1095 "all": getall,
1056 "ancestor": ancestor,
1096 "ancestor": ancestor,
1057 "ancestors": ancestors,
1097 "ancestors": ancestors,
1098 "_firstancestors": _firstancestors,
1058 "author": author,
1099 "author": author,
1059 "bisect": bisect,
1100 "bisect": bisect,
1060 "bisected": bisected,
1101 "bisected": bisected,
1061 "bookmark": bookmark,
1102 "bookmark": bookmark,
1062 "branch": branch,
1103 "branch": branch,
1063 "children": children,
1104 "children": children,
1064 "closed": closed,
1105 "closed": closed,
1065 "contains": contains,
1106 "contains": contains,
1066 "date": date,
1107 "date": date,
1067 "desc": desc,
1108 "desc": desc,
1068 "descendants": descendants,
1109 "descendants": descendants,
1110 "_firstdescendants": _firstdescendants,
1069 "draft": draft,
1111 "draft": draft,
1070 "file": hasfile,
1112 "file": hasfile,
1071 "filelog": filelog,
1113 "filelog": filelog,
1072 "first": first,
1114 "first": first,
1073 "follow": follow,
1115 "follow": follow,
1074 "_followfirst": _followfirst,
1116 "_followfirst": _followfirst,
1075 "grep": grep,
1117 "grep": grep,
1076 "head": head,
1118 "head": head,
1077 "heads": heads,
1119 "heads": heads,
1078 "id": node,
1120 "id": node,
1079 "keyword": keyword,
1121 "keyword": keyword,
1080 "last": last,
1122 "last": last,
1081 "limit": limit,
1123 "limit": limit,
1082 "_matchfiles": _matchfiles,
1124 "_matchfiles": _matchfiles,
1083 "max": maxrev,
1125 "max": maxrev,
1084 "merge": merge,
1126 "merge": merge,
1085 "min": minrev,
1127 "min": minrev,
1086 "modifies": modifies,
1128 "modifies": modifies,
1087 "outgoing": outgoing,
1129 "outgoing": outgoing,
1088 "p1": p1,
1130 "p1": p1,
1089 "p2": p2,
1131 "p2": p2,
1090 "parents": parents,
1132 "parents": parents,
1091 "present": present,
1133 "present": present,
1092 "public": public,
1134 "public": public,
1093 "remote": remote,
1135 "remote": remote,
1094 "removes": removes,
1136 "removes": removes,
1095 "rev": rev,
1137 "rev": rev,
1096 "reverse": reverse,
1138 "reverse": reverse,
1097 "roots": roots,
1139 "roots": roots,
1098 "sort": sort,
1140 "sort": sort,
1099 "secret": secret,
1141 "secret": secret,
1100 "matching": matching,
1142 "matching": matching,
1101 "tag": tag,
1143 "tag": tag,
1102 "tagged": tagged,
1144 "tagged": tagged,
1103 "user": user,
1145 "user": user,
1104 "_list": _list,
1146 "_list": _list,
1105 }
1147 }
1106
1148
1107 methods = {
1149 methods = {
1108 "range": rangeset,
1150 "range": rangeset,
1109 "string": stringset,
1151 "string": stringset,
1110 "symbol": symbolset,
1152 "symbol": symbolset,
1111 "and": andset,
1153 "and": andset,
1112 "or": orset,
1154 "or": orset,
1113 "not": notset,
1155 "not": notset,
1114 "list": listset,
1156 "list": listset,
1115 "func": func,
1157 "func": func,
1116 "ancestor": ancestorspec,
1158 "ancestor": ancestorspec,
1117 "parent": parentspec,
1159 "parent": parentspec,
1118 "parentpost": p1,
1160 "parentpost": p1,
1119 }
1161 }
1120
1162
1121 def optimize(x, small):
1163 def optimize(x, small):
1122 if x is None:
1164 if x is None:
1123 return 0, x
1165 return 0, x
1124
1166
1125 smallbonus = 1
1167 smallbonus = 1
1126 if small:
1168 if small:
1127 smallbonus = .5
1169 smallbonus = .5
1128
1170
1129 op = x[0]
1171 op = x[0]
1130 if op == 'minus':
1172 if op == 'minus':
1131 return optimize(('and', x[1], ('not', x[2])), small)
1173 return optimize(('and', x[1], ('not', x[2])), small)
1132 elif op == 'dagrange':
1174 elif op == 'dagrange':
1133 return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
1175 return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
1134 ('func', ('symbol', 'ancestors'), x[2])), small)
1176 ('func', ('symbol', 'ancestors'), x[2])), small)
1135 elif op == 'dagrangepre':
1177 elif op == 'dagrangepre':
1136 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
1178 return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
1137 elif op == 'dagrangepost':
1179 elif op == 'dagrangepost':
1138 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
1180 return optimize(('func', ('symbol', 'descendants'), x[1]), small)
1139 elif op == 'rangepre':
1181 elif op == 'rangepre':
1140 return optimize(('range', ('string', '0'), x[1]), small)
1182 return optimize(('range', ('string', '0'), x[1]), small)
1141 elif op == 'rangepost':
1183 elif op == 'rangepost':
1142 return optimize(('range', x[1], ('string', 'tip')), small)
1184 return optimize(('range', x[1], ('string', 'tip')), small)
1143 elif op == 'negate':
1185 elif op == 'negate':
1144 return optimize(('string',
1186 return optimize(('string',
1145 '-' + getstring(x[1], _("can't negate that"))), small)
1187 '-' + getstring(x[1], _("can't negate that"))), small)
1146 elif op in 'string symbol negate':
1188 elif op in 'string symbol negate':
1147 return smallbonus, x # single revisions are small
1189 return smallbonus, x # single revisions are small
1148 elif op == 'and' or op == 'dagrange':
1190 elif op == 'and' or op == 'dagrange':
1149 wa, ta = optimize(x[1], True)
1191 wa, ta = optimize(x[1], True)
1150 wb, tb = optimize(x[2], True)
1192 wb, tb = optimize(x[2], True)
1151 w = min(wa, wb)
1193 w = min(wa, wb)
1152 if wa > wb:
1194 if wa > wb:
1153 return w, (op, tb, ta)
1195 return w, (op, tb, ta)
1154 return w, (op, ta, tb)
1196 return w, (op, ta, tb)
1155 elif op == 'or':
1197 elif op == 'or':
1156 wa, ta = optimize(x[1], False)
1198 wa, ta = optimize(x[1], False)
1157 wb, tb = optimize(x[2], False)
1199 wb, tb = optimize(x[2], False)
1158 if wb < wa:
1200 if wb < wa:
1159 wb, wa = wa, wb
1201 wb, wa = wa, wb
1160 return max(wa, wb), (op, ta, tb)
1202 return max(wa, wb), (op, ta, tb)
1161 elif op == 'not':
1203 elif op == 'not':
1162 o = optimize(x[1], not small)
1204 o = optimize(x[1], not small)
1163 return o[0], (op, o[1])
1205 return o[0], (op, o[1])
1164 elif op == 'parentpost':
1206 elif op == 'parentpost':
1165 o = optimize(x[1], small)
1207 o = optimize(x[1], small)
1166 return o[0], (op, o[1])
1208 return o[0], (op, o[1])
1167 elif op == 'group':
1209 elif op == 'group':
1168 return optimize(x[1], small)
1210 return optimize(x[1], small)
1169 elif op in 'range list parent ancestorspec':
1211 elif op in 'range list parent ancestorspec':
1170 if op == 'parent':
1212 if op == 'parent':
1171 # x^:y means (x^) : y, not x ^ (:y)
1213 # x^:y means (x^) : y, not x ^ (:y)
1172 post = ('parentpost', x[1])
1214 post = ('parentpost', x[1])
1173 if x[2][0] == 'dagrangepre':
1215 if x[2][0] == 'dagrangepre':
1174 return optimize(('dagrange', post, x[2][1]), small)
1216 return optimize(('dagrange', post, x[2][1]), small)
1175 elif x[2][0] == 'rangepre':
1217 elif x[2][0] == 'rangepre':
1176 return optimize(('range', post, x[2][1]), small)
1218 return optimize(('range', post, x[2][1]), small)
1177
1219
1178 wa, ta = optimize(x[1], small)
1220 wa, ta = optimize(x[1], small)
1179 wb, tb = optimize(x[2], small)
1221 wb, tb = optimize(x[2], small)
1180 return wa + wb, (op, ta, tb)
1222 return wa + wb, (op, ta, tb)
1181 elif op == 'func':
1223 elif op == 'func':
1182 f = getstring(x[1], _("not a symbol"))
1224 f = getstring(x[1], _("not a symbol"))
1183 wa, ta = optimize(x[2], small)
1225 wa, ta = optimize(x[2], small)
1184 if f in ("author branch closed date desc file grep keyword "
1226 if f in ("author branch closed date desc file grep keyword "
1185 "outgoing user"):
1227 "outgoing user"):
1186 w = 10 # slow
1228 w = 10 # slow
1187 elif f in "modifies adds removes":
1229 elif f in "modifies adds removes":
1188 w = 30 # slower
1230 w = 30 # slower
1189 elif f == "contains":
1231 elif f == "contains":
1190 w = 100 # very slow
1232 w = 100 # very slow
1191 elif f == "ancestor":
1233 elif f == "ancestor":
1192 w = 1 * smallbonus
1234 w = 1 * smallbonus
1193 elif f in "reverse limit first":
1235 elif f in "reverse limit first":
1194 w = 0
1236 w = 0
1195 elif f in "sort":
1237 elif f in "sort":
1196 w = 10 # assume most sorts look at changelog
1238 w = 10 # assume most sorts look at changelog
1197 else:
1239 else:
1198 w = 1
1240 w = 1
1199 return w + wa, (op, x[1], ta)
1241 return w + wa, (op, x[1], ta)
1200 return 1, x
1242 return 1, x
1201
1243
1202 class revsetalias(object):
1244 class revsetalias(object):
1203 funcre = re.compile('^([^(]+)\(([^)]+)\)$')
1245 funcre = re.compile('^([^(]+)\(([^)]+)\)$')
1204 args = None
1246 args = None
1205
1247
1206 def __init__(self, name, value):
1248 def __init__(self, name, value):
1207 '''Aliases like:
1249 '''Aliases like:
1208
1250
1209 h = heads(default)
1251 h = heads(default)
1210 b($1) = ancestors($1) - ancestors(default)
1252 b($1) = ancestors($1) - ancestors(default)
1211 '''
1253 '''
1212 m = self.funcre.search(name)
1254 m = self.funcre.search(name)
1213 if m:
1255 if m:
1214 self.name = m.group(1)
1256 self.name = m.group(1)
1215 self.tree = ('func', ('symbol', m.group(1)))
1257 self.tree = ('func', ('symbol', m.group(1)))
1216 self.args = [x.strip() for x in m.group(2).split(',')]
1258 self.args = [x.strip() for x in m.group(2).split(',')]
1217 for arg in self.args:
1259 for arg in self.args:
1218 value = value.replace(arg, repr(arg))
1260 value = value.replace(arg, repr(arg))
1219 else:
1261 else:
1220 self.name = name
1262 self.name = name
1221 self.tree = ('symbol', name)
1263 self.tree = ('symbol', name)
1222
1264
1223 self.replacement, pos = parse(value)
1265 self.replacement, pos = parse(value)
1224 if pos != len(value):
1266 if pos != len(value):
1225 raise error.ParseError(_('invalid token'), pos)
1267 raise error.ParseError(_('invalid token'), pos)
1226
1268
1227 def _getalias(aliases, tree):
1269 def _getalias(aliases, tree):
1228 """If tree looks like an unexpanded alias, return it. Return None
1270 """If tree looks like an unexpanded alias, return it. Return None
1229 otherwise.
1271 otherwise.
1230 """
1272 """
1231 if isinstance(tree, tuple) and tree:
1273 if isinstance(tree, tuple) and tree:
1232 if tree[0] == 'symbol' and len(tree) == 2:
1274 if tree[0] == 'symbol' and len(tree) == 2:
1233 name = tree[1]
1275 name = tree[1]
1234 alias = aliases.get(name)
1276 alias = aliases.get(name)
1235 if alias and alias.args is None and alias.tree == tree:
1277 if alias and alias.args is None and alias.tree == tree:
1236 return alias
1278 return alias
1237 if tree[0] == 'func' and len(tree) > 1:
1279 if tree[0] == 'func' and len(tree) > 1:
1238 if tree[1][0] == 'symbol' and len(tree[1]) == 2:
1280 if tree[1][0] == 'symbol' and len(tree[1]) == 2:
1239 name = tree[1][1]
1281 name = tree[1][1]
1240 alias = aliases.get(name)
1282 alias = aliases.get(name)
1241 if alias and alias.args is not None and alias.tree == tree[:2]:
1283 if alias and alias.args is not None and alias.tree == tree[:2]:
1242 return alias
1284 return alias
1243 return None
1285 return None
1244
1286
1245 def _expandargs(tree, args):
1287 def _expandargs(tree, args):
1246 """Replace all occurences of ('string', name) with the
1288 """Replace all occurences of ('string', name) with the
1247 substitution value of the same name in args, recursively.
1289 substitution value of the same name in args, recursively.
1248 """
1290 """
1249 if not isinstance(tree, tuple):
1291 if not isinstance(tree, tuple):
1250 return tree
1292 return tree
1251 if len(tree) == 2 and tree[0] == 'string':
1293 if len(tree) == 2 and tree[0] == 'string':
1252 return args.get(tree[1], tree)
1294 return args.get(tree[1], tree)
1253 return tuple(_expandargs(t, args) for t in tree)
1295 return tuple(_expandargs(t, args) for t in tree)
1254
1296
1255 def _expandaliases(aliases, tree, expanding):
1297 def _expandaliases(aliases, tree, expanding):
1256 """Expand aliases in tree, recursively.
1298 """Expand aliases in tree, recursively.
1257
1299
1258 'aliases' is a dictionary mapping user defined aliases to
1300 'aliases' is a dictionary mapping user defined aliases to
1259 revsetalias objects.
1301 revsetalias objects.
1260 """
1302 """
1261 if not isinstance(tree, tuple):
1303 if not isinstance(tree, tuple):
1262 # Do not expand raw strings
1304 # Do not expand raw strings
1263 return tree
1305 return tree
1264 alias = _getalias(aliases, tree)
1306 alias = _getalias(aliases, tree)
1265 if alias is not None:
1307 if alias is not None:
1266 if alias in expanding:
1308 if alias in expanding:
1267 raise error.ParseError(_('infinite expansion of revset alias "%s" '
1309 raise error.ParseError(_('infinite expansion of revset alias "%s" '
1268 'detected') % alias.name)
1310 'detected') % alias.name)
1269 expanding.append(alias)
1311 expanding.append(alias)
1270 result = alias.replacement
1312 result = alias.replacement
1271 if alias.args is not None:
1313 if alias.args is not None:
1272 l = getlist(tree[2])
1314 l = getlist(tree[2])
1273 if len(l) != len(alias.args):
1315 if len(l) != len(alias.args):
1274 raise error.ParseError(
1316 raise error.ParseError(
1275 _('invalid number of arguments: %s') % len(l))
1317 _('invalid number of arguments: %s') % len(l))
1276 result = _expandargs(result, dict(zip(alias.args, l)))
1318 result = _expandargs(result, dict(zip(alias.args, l)))
1277 # Recurse in place, the base expression may have been rewritten
1319 # Recurse in place, the base expression may have been rewritten
1278 result = _expandaliases(aliases, result, expanding)
1320 result = _expandaliases(aliases, result, expanding)
1279 expanding.pop()
1321 expanding.pop()
1280 else:
1322 else:
1281 result = tuple(_expandaliases(aliases, t, expanding)
1323 result = tuple(_expandaliases(aliases, t, expanding)
1282 for t in tree)
1324 for t in tree)
1283 return result
1325 return result
1284
1326
1285 def findaliases(ui, tree):
1327 def findaliases(ui, tree):
1286 aliases = {}
1328 aliases = {}
1287 for k, v in ui.configitems('revsetalias'):
1329 for k, v in ui.configitems('revsetalias'):
1288 alias = revsetalias(k, v)
1330 alias = revsetalias(k, v)
1289 aliases[alias.name] = alias
1331 aliases[alias.name] = alias
1290 return _expandaliases(aliases, tree, [])
1332 return _expandaliases(aliases, tree, [])
1291
1333
1292 parse = parser.parser(tokenize, elements).parse
1334 parse = parser.parser(tokenize, elements).parse
1293
1335
1294 def match(ui, spec):
1336 def match(ui, spec):
1295 if not spec:
1337 if not spec:
1296 raise error.ParseError(_("empty query"))
1338 raise error.ParseError(_("empty query"))
1297 tree, pos = parse(spec)
1339 tree, pos = parse(spec)
1298 if (pos != len(spec)):
1340 if (pos != len(spec)):
1299 raise error.ParseError(_("invalid token"), pos)
1341 raise error.ParseError(_("invalid token"), pos)
1300 if ui:
1342 if ui:
1301 tree = findaliases(ui, tree)
1343 tree = findaliases(ui, tree)
1302 weight, tree = optimize(tree, True)
1344 weight, tree = optimize(tree, True)
1303 def mfunc(repo, subset):
1345 def mfunc(repo, subset):
1304 return getset(repo, subset, tree)
1346 return getset(repo, subset, tree)
1305 return mfunc
1347 return mfunc
1306
1348
1307 def formatspec(expr, *args):
1349 def formatspec(expr, *args):
1308 '''
1350 '''
1309 This is a convenience function for using revsets internally, and
1351 This is a convenience function for using revsets internally, and
1310 escapes arguments appropriately. Aliases are intentionally ignored
1352 escapes arguments appropriately. Aliases are intentionally ignored
1311 so that intended expression behavior isn't accidentally subverted.
1353 so that intended expression behavior isn't accidentally subverted.
1312
1354
1313 Supported arguments:
1355 Supported arguments:
1314
1356
1315 %r = revset expression, parenthesized
1357 %r = revset expression, parenthesized
1316 %d = int(arg), no quoting
1358 %d = int(arg), no quoting
1317 %s = string(arg), escaped and single-quoted
1359 %s = string(arg), escaped and single-quoted
1318 %b = arg.branch(), escaped and single-quoted
1360 %b = arg.branch(), escaped and single-quoted
1319 %n = hex(arg), single-quoted
1361 %n = hex(arg), single-quoted
1320 %% = a literal '%'
1362 %% = a literal '%'
1321
1363
1322 Prefixing the type with 'l' specifies a parenthesized list of that type.
1364 Prefixing the type with 'l' specifies a parenthesized list of that type.
1323
1365
1324 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
1366 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
1325 '(10 or 11):: and ((this()) or (that()))'
1367 '(10 or 11):: and ((this()) or (that()))'
1326 >>> formatspec('%d:: and not %d::', 10, 20)
1368 >>> formatspec('%d:: and not %d::', 10, 20)
1327 '10:: and not 20::'
1369 '10:: and not 20::'
1328 >>> formatspec('%ld or %ld', [], [1])
1370 >>> formatspec('%ld or %ld', [], [1])
1329 "_list('') or 1"
1371 "_list('') or 1"
1330 >>> formatspec('keyword(%s)', 'foo\\xe9')
1372 >>> formatspec('keyword(%s)', 'foo\\xe9')
1331 "keyword('foo\\\\xe9')"
1373 "keyword('foo\\\\xe9')"
1332 >>> b = lambda: 'default'
1374 >>> b = lambda: 'default'
1333 >>> b.branch = b
1375 >>> b.branch = b
1334 >>> formatspec('branch(%b)', b)
1376 >>> formatspec('branch(%b)', b)
1335 "branch('default')"
1377 "branch('default')"
1336 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
1378 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
1337 "root(_list('a\\x00b\\x00c\\x00d'))"
1379 "root(_list('a\\x00b\\x00c\\x00d'))"
1338 '''
1380 '''
1339
1381
1340 def quote(s):
1382 def quote(s):
1341 return repr(str(s))
1383 return repr(str(s))
1342
1384
1343 def argtype(c, arg):
1385 def argtype(c, arg):
1344 if c == 'd':
1386 if c == 'd':
1345 return str(int(arg))
1387 return str(int(arg))
1346 elif c == 's':
1388 elif c == 's':
1347 return quote(arg)
1389 return quote(arg)
1348 elif c == 'r':
1390 elif c == 'r':
1349 parse(arg) # make sure syntax errors are confined
1391 parse(arg) # make sure syntax errors are confined
1350 return '(%s)' % arg
1392 return '(%s)' % arg
1351 elif c == 'n':
1393 elif c == 'n':
1352 return quote(nodemod.hex(arg))
1394 return quote(nodemod.hex(arg))
1353 elif c == 'b':
1395 elif c == 'b':
1354 return quote(arg.branch())
1396 return quote(arg.branch())
1355
1397
1356 def listexp(s, t):
1398 def listexp(s, t):
1357 l = len(s)
1399 l = len(s)
1358 if l == 0:
1400 if l == 0:
1359 return "_list('')"
1401 return "_list('')"
1360 elif l == 1:
1402 elif l == 1:
1361 return argtype(t, s[0])
1403 return argtype(t, s[0])
1362 elif t == 'd':
1404 elif t == 'd':
1363 return "_list('%s')" % "\0".join(str(int(a)) for a in s)
1405 return "_list('%s')" % "\0".join(str(int(a)) for a in s)
1364 elif t == 's':
1406 elif t == 's':
1365 return "_list('%s')" % "\0".join(s)
1407 return "_list('%s')" % "\0".join(s)
1366 elif t == 'n':
1408 elif t == 'n':
1367 return "_list('%s')" % "\0".join(nodemod.hex(a) for a in s)
1409 return "_list('%s')" % "\0".join(nodemod.hex(a) for a in s)
1368 elif t == 'b':
1410 elif t == 'b':
1369 return "_list('%s')" % "\0".join(a.branch() for a in s)
1411 return "_list('%s')" % "\0".join(a.branch() for a in s)
1370
1412
1371 m = l // 2
1413 m = l // 2
1372 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
1414 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
1373
1415
1374 ret = ''
1416 ret = ''
1375 pos = 0
1417 pos = 0
1376 arg = 0
1418 arg = 0
1377 while pos < len(expr):
1419 while pos < len(expr):
1378 c = expr[pos]
1420 c = expr[pos]
1379 if c == '%':
1421 if c == '%':
1380 pos += 1
1422 pos += 1
1381 d = expr[pos]
1423 d = expr[pos]
1382 if d == '%':
1424 if d == '%':
1383 ret += d
1425 ret += d
1384 elif d in 'dsnbr':
1426 elif d in 'dsnbr':
1385 ret += argtype(d, args[arg])
1427 ret += argtype(d, args[arg])
1386 arg += 1
1428 arg += 1
1387 elif d == 'l':
1429 elif d == 'l':
1388 # a list of some type
1430 # a list of some type
1389 pos += 1
1431 pos += 1
1390 d = expr[pos]
1432 d = expr[pos]
1391 ret += listexp(list(args[arg]), d)
1433 ret += listexp(list(args[arg]), d)
1392 arg += 1
1434 arg += 1
1393 else:
1435 else:
1394 raise util.Abort('unexpected revspec format character %s' % d)
1436 raise util.Abort('unexpected revspec format character %s' % d)
1395 else:
1437 else:
1396 ret += c
1438 ret += c
1397 pos += 1
1439 pos += 1
1398
1440
1399 return ret
1441 return ret
1400
1442
1401 def prettyformat(tree):
1443 def prettyformat(tree):
1402 def _prettyformat(tree, level, lines):
1444 def _prettyformat(tree, level, lines):
1403 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
1445 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
1404 lines.append((level, str(tree)))
1446 lines.append((level, str(tree)))
1405 else:
1447 else:
1406 lines.append((level, '(%s' % tree[0]))
1448 lines.append((level, '(%s' % tree[0]))
1407 for s in tree[1:]:
1449 for s in tree[1:]:
1408 _prettyformat(s, level + 1, lines)
1450 _prettyformat(s, level + 1, lines)
1409 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')]
1451 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')]
1410
1452
1411 lines = []
1453 lines = []
1412 _prettyformat(tree, 0, lines)
1454 _prettyformat(tree, 0, lines)
1413 output = '\n'.join((' '*l + s) for l, s in lines)
1455 output = '\n'.join((' '*l + s) for l, s in lines)
1414 return output
1456 return output
1415
1457
1416 # tell hggettext to extract docstrings from these functions:
1458 # tell hggettext to extract docstrings from these functions:
1417 i18nfunctions = symbols.values()
1459 i18nfunctions = symbols.values()
@@ -1,1978 +1,2003 b''
1 @ (34) head
1 @ (34) head
2 |
2 |
3 | o (33) head
3 | o (33) head
4 | |
4 | |
5 o | (32) expand
5 o | (32) expand
6 |\ \
6 |\ \
7 | o \ (31) expand
7 | o \ (31) expand
8 | |\ \
8 | |\ \
9 | | o \ (30) expand
9 | | o \ (30) expand
10 | | |\ \
10 | | |\ \
11 | | | o | (29) regular commit
11 | | | o | (29) regular commit
12 | | | | |
12 | | | | |
13 | | o | | (28) merge zero known
13 | | o | | (28) merge zero known
14 | | |\ \ \
14 | | |\ \ \
15 o | | | | | (27) collapse
15 o | | | | | (27) collapse
16 |/ / / / /
16 |/ / / / /
17 | | o---+ (26) merge one known; far right
17 | | o---+ (26) merge one known; far right
18 | | | | |
18 | | | | |
19 +---o | | (25) merge one known; far left
19 +---o | | (25) merge one known; far left
20 | | | | |
20 | | | | |
21 | | o | | (24) merge one known; immediate right
21 | | o | | (24) merge one known; immediate right
22 | | |\| |
22 | | |\| |
23 | | o | | (23) merge one known; immediate left
23 | | o | | (23) merge one known; immediate left
24 | |/| | |
24 | |/| | |
25 +---o---+ (22) merge two known; one far left, one far right
25 +---o---+ (22) merge two known; one far left, one far right
26 | | / /
26 | | / /
27 o | | | (21) expand
27 o | | | (21) expand
28 |\ \ \ \
28 |\ \ \ \
29 | o---+-+ (20) merge two known; two far right
29 | o---+-+ (20) merge two known; two far right
30 | / / /
30 | / / /
31 o | | | (19) expand
31 o | | | (19) expand
32 |\ \ \ \
32 |\ \ \ \
33 +---+---o (18) merge two known; two far left
33 +---+---o (18) merge two known; two far left
34 | | | |
34 | | | |
35 | o | | (17) expand
35 | o | | (17) expand
36 | |\ \ \
36 | |\ \ \
37 | | o---+ (16) merge two known; one immediate right, one near right
37 | | o---+ (16) merge two known; one immediate right, one near right
38 | | |/ /
38 | | |/ /
39 o | | | (15) expand
39 o | | | (15) expand
40 |\ \ \ \
40 |\ \ \ \
41 | o-----+ (14) merge two known; one immediate right, one far right
41 | o-----+ (14) merge two known; one immediate right, one far right
42 | |/ / /
42 | |/ / /
43 o | | | (13) expand
43 o | | | (13) expand
44 |\ \ \ \
44 |\ \ \ \
45 +---o | | (12) merge two known; one immediate right, one far left
45 +---o | | (12) merge two known; one immediate right, one far left
46 | | |/ /
46 | | |/ /
47 | o | | (11) expand
47 | o | | (11) expand
48 | |\ \ \
48 | |\ \ \
49 | | o---+ (10) merge two known; one immediate left, one near right
49 | | o---+ (10) merge two known; one immediate left, one near right
50 | |/ / /
50 | |/ / /
51 o | | | (9) expand
51 o | | | (9) expand
52 |\ \ \ \
52 |\ \ \ \
53 | o-----+ (8) merge two known; one immediate left, one far right
53 | o-----+ (8) merge two known; one immediate left, one far right
54 |/ / / /
54 |/ / / /
55 o | | | (7) expand
55 o | | | (7) expand
56 |\ \ \ \
56 |\ \ \ \
57 +---o | | (6) merge two known; one immediate left, one far left
57 +---o | | (6) merge two known; one immediate left, one far left
58 | |/ / /
58 | |/ / /
59 | o | | (5) expand
59 | o | | (5) expand
60 | |\ \ \
60 | |\ \ \
61 | | o | | (4) merge two known; one immediate left, one immediate right
61 | | o | | (4) merge two known; one immediate left, one immediate right
62 | |/|/ /
62 | |/|/ /
63 | o / / (3) collapse
63 | o / / (3) collapse
64 |/ / /
64 |/ / /
65 o / / (2) collapse
65 o / / (2) collapse
66 |/ /
66 |/ /
67 o / (1) collapse
67 o / (1) collapse
68 |/
68 |/
69 o (0) root
69 o (0) root
70
70
71
71
72 $ "$TESTDIR/hghave" no-outer-repo || exit 80
72 $ "$TESTDIR/hghave" no-outer-repo || exit 80
73
73
74 $ commit()
74 $ commit()
75 > {
75 > {
76 > rev=$1
76 > rev=$1
77 > msg=$2
77 > msg=$2
78 > shift 2
78 > shift 2
79 > if [ "$#" -gt 0 ]; then
79 > if [ "$#" -gt 0 ]; then
80 > hg debugsetparents "$@"
80 > hg debugsetparents "$@"
81 > fi
81 > fi
82 > echo $rev > a
82 > echo $rev > a
83 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
83 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
84 > }
84 > }
85
85
86 $ cat > printrevset.py <<EOF
86 $ cat > printrevset.py <<EOF
87 > from mercurial import extensions, revset, commands
87 > from mercurial import extensions, revset, commands
88 > from hgext import graphlog
88 > from hgext import graphlog
89 >
89 >
90 > def uisetup(ui):
90 > def uisetup(ui):
91 > def printrevset(orig, ui, repo, *pats, **opts):
91 > def printrevset(orig, ui, repo, *pats, **opts):
92 > if opts.get('print_revset'):
92 > if opts.get('print_revset'):
93 > expr = graphlog.getlogrevs(repo, pats, opts)[1]
93 > expr = graphlog.getlogrevs(repo, pats, opts)[1]
94 > if expr:
94 > if expr:
95 > tree = revset.parse(expr)[0]
95 > tree = revset.parse(expr)[0]
96 > else:
96 > else:
97 > tree = []
97 > tree = []
98 > ui.write('%r\n' % (opts.get('rev', []),))
98 > ui.write('%r\n' % (opts.get('rev', []),))
99 > ui.write(revset.prettyformat(tree) + '\n')
99 > ui.write(revset.prettyformat(tree) + '\n')
100 > return 0
100 > return 0
101 > return orig(ui, repo, *pats, **opts)
101 > return orig(ui, repo, *pats, **opts)
102 > entry = extensions.wrapcommand(commands.table, 'log', printrevset)
102 > entry = extensions.wrapcommand(commands.table, 'log', printrevset)
103 > entry[1].append(('', 'print-revset', False,
103 > entry[1].append(('', 'print-revset', False,
104 > 'print generated revset and exit (DEPRECATED)'))
104 > 'print generated revset and exit (DEPRECATED)'))
105 > EOF
105 > EOF
106
106
107 $ echo "[extensions]" >> $HGRCPATH
107 $ echo "[extensions]" >> $HGRCPATH
108 $ echo "graphlog=" >> $HGRCPATH
108 $ echo "graphlog=" >> $HGRCPATH
109 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
109 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
110
110
111 $ hg init repo
111 $ hg init repo
112 $ cd repo
112 $ cd repo
113
113
114 Empty repo:
114 Empty repo:
115
115
116 $ hg glog
116 $ hg glog
117
117
118
118
119 Building DAG:
119 Building DAG:
120
120
121 $ commit 0 "root"
121 $ commit 0 "root"
122 $ commit 1 "collapse" 0
122 $ commit 1 "collapse" 0
123 $ commit 2 "collapse" 1
123 $ commit 2 "collapse" 1
124 $ commit 3 "collapse" 2
124 $ commit 3 "collapse" 2
125 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
125 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
126 $ commit 5 "expand" 3 4
126 $ commit 5 "expand" 3 4
127 $ commit 6 "merge two known; one immediate left, one far left" 2 5
127 $ commit 6 "merge two known; one immediate left, one far left" 2 5
128 $ commit 7 "expand" 2 5
128 $ commit 7 "expand" 2 5
129 $ commit 8 "merge two known; one immediate left, one far right" 0 7
129 $ commit 8 "merge two known; one immediate left, one far right" 0 7
130 $ commit 9 "expand" 7 8
130 $ commit 9 "expand" 7 8
131 $ commit 10 "merge two known; one immediate left, one near right" 0 6
131 $ commit 10 "merge two known; one immediate left, one near right" 0 6
132 $ commit 11 "expand" 6 10
132 $ commit 11 "expand" 6 10
133 $ commit 12 "merge two known; one immediate right, one far left" 1 9
133 $ commit 12 "merge two known; one immediate right, one far left" 1 9
134 $ commit 13 "expand" 9 11
134 $ commit 13 "expand" 9 11
135 $ commit 14 "merge two known; one immediate right, one far right" 0 12
135 $ commit 14 "merge two known; one immediate right, one far right" 0 12
136 $ commit 15 "expand" 13 14
136 $ commit 15 "expand" 13 14
137 $ commit 16 "merge two known; one immediate right, one near right" 0 1
137 $ commit 16 "merge two known; one immediate right, one near right" 0 1
138 $ commit 17 "expand" 12 16
138 $ commit 17 "expand" 12 16
139 $ commit 18 "merge two known; two far left" 1 15
139 $ commit 18 "merge two known; two far left" 1 15
140 $ commit 19 "expand" 15 17
140 $ commit 19 "expand" 15 17
141 $ commit 20 "merge two known; two far right" 0 18
141 $ commit 20 "merge two known; two far right" 0 18
142 $ commit 21 "expand" 19 20
142 $ commit 21 "expand" 19 20
143 $ commit 22 "merge two known; one far left, one far right" 18 21
143 $ commit 22 "merge two known; one far left, one far right" 18 21
144 $ commit 23 "merge one known; immediate left" 1 22
144 $ commit 23 "merge one known; immediate left" 1 22
145 $ commit 24 "merge one known; immediate right" 0 23
145 $ commit 24 "merge one known; immediate right" 0 23
146 $ commit 25 "merge one known; far left" 21 24
146 $ commit 25 "merge one known; far left" 21 24
147 $ commit 26 "merge one known; far right" 18 25
147 $ commit 26 "merge one known; far right" 18 25
148 $ commit 27 "collapse" 21
148 $ commit 27 "collapse" 21
149 $ commit 28 "merge zero known" 1 26
149 $ commit 28 "merge zero known" 1 26
150 $ commit 29 "regular commit" 0
150 $ commit 29 "regular commit" 0
151 $ commit 30 "expand" 28 29
151 $ commit 30 "expand" 28 29
152 $ commit 31 "expand" 21 30
152 $ commit 31 "expand" 21 30
153 $ commit 32 "expand" 27 31
153 $ commit 32 "expand" 27 31
154 $ commit 33 "head" 18
154 $ commit 33 "head" 18
155 $ commit 34 "head" 32
155 $ commit 34 "head" 32
156
156
157
157
158 $ hg glog -q
158 $ hg glog -q
159 @ 34:fea3ac5810e0
159 @ 34:fea3ac5810e0
160 |
160 |
161 | o 33:68608f5145f9
161 | o 33:68608f5145f9
162 | |
162 | |
163 o | 32:d06dffa21a31
163 o | 32:d06dffa21a31
164 |\ \
164 |\ \
165 | o \ 31:621d83e11f67
165 | o \ 31:621d83e11f67
166 | |\ \
166 | |\ \
167 | | o \ 30:6e11cd4b648f
167 | | o \ 30:6e11cd4b648f
168 | | |\ \
168 | | |\ \
169 | | | o | 29:cd9bb2be7593
169 | | | o | 29:cd9bb2be7593
170 | | | | |
170 | | | | |
171 | | o | | 28:44ecd0b9ae99
171 | | o | | 28:44ecd0b9ae99
172 | | |\ \ \
172 | | |\ \ \
173 o | | | | | 27:886ed638191b
173 o | | | | | 27:886ed638191b
174 |/ / / / /
174 |/ / / / /
175 | | o---+ 26:7f25b6c2f0b9
175 | | o---+ 26:7f25b6c2f0b9
176 | | | | |
176 | | | | |
177 +---o | | 25:91da8ed57247
177 +---o | | 25:91da8ed57247
178 | | | | |
178 | | | | |
179 | | o | | 24:a9c19a3d96b7
179 | | o | | 24:a9c19a3d96b7
180 | | |\| |
180 | | |\| |
181 | | o | | 23:a01cddf0766d
181 | | o | | 23:a01cddf0766d
182 | |/| | |
182 | |/| | |
183 +---o---+ 22:e0d9cccacb5d
183 +---o---+ 22:e0d9cccacb5d
184 | | / /
184 | | / /
185 o | | | 21:d42a756af44d
185 o | | | 21:d42a756af44d
186 |\ \ \ \
186 |\ \ \ \
187 | o---+-+ 20:d30ed6450e32
187 | o---+-+ 20:d30ed6450e32
188 | / / /
188 | / / /
189 o | | | 19:31ddc2c1573b
189 o | | | 19:31ddc2c1573b
190 |\ \ \ \
190 |\ \ \ \
191 +---+---o 18:1aa84d96232a
191 +---+---o 18:1aa84d96232a
192 | | | |
192 | | | |
193 | o | | 17:44765d7c06e0
193 | o | | 17:44765d7c06e0
194 | |\ \ \
194 | |\ \ \
195 | | o---+ 16:3677d192927d
195 | | o---+ 16:3677d192927d
196 | | |/ /
196 | | |/ /
197 o | | | 15:1dda3f72782d
197 o | | | 15:1dda3f72782d
198 |\ \ \ \
198 |\ \ \ \
199 | o-----+ 14:8eac370358ef
199 | o-----+ 14:8eac370358ef
200 | |/ / /
200 | |/ / /
201 o | | | 13:22d8966a97e3
201 o | | | 13:22d8966a97e3
202 |\ \ \ \
202 |\ \ \ \
203 +---o | | 12:86b91144a6e9
203 +---o | | 12:86b91144a6e9
204 | | |/ /
204 | | |/ /
205 | o | | 11:832d76e6bdf2
205 | o | | 11:832d76e6bdf2
206 | |\ \ \
206 | |\ \ \
207 | | o---+ 10:74c64d036d72
207 | | o---+ 10:74c64d036d72
208 | |/ / /
208 | |/ / /
209 o | | | 9:7010c0af0a35
209 o | | | 9:7010c0af0a35
210 |\ \ \ \
210 |\ \ \ \
211 | o-----+ 8:7a0b11f71937
211 | o-----+ 8:7a0b11f71937
212 |/ / / /
212 |/ / / /
213 o | | | 7:b632bb1b1224
213 o | | | 7:b632bb1b1224
214 |\ \ \ \
214 |\ \ \ \
215 +---o | | 6:b105a072e251
215 +---o | | 6:b105a072e251
216 | |/ / /
216 | |/ / /
217 | o | | 5:4409d547b708
217 | o | | 5:4409d547b708
218 | |\ \ \
218 | |\ \ \
219 | | o | | 4:26a8bac39d9f
219 | | o | | 4:26a8bac39d9f
220 | |/|/ /
220 | |/|/ /
221 | o / / 3:27eef8ed80b4
221 | o / / 3:27eef8ed80b4
222 |/ / /
222 |/ / /
223 o / / 2:3d9a33b8d1e1
223 o / / 2:3d9a33b8d1e1
224 |/ /
224 |/ /
225 o / 1:6db2ef61d156
225 o / 1:6db2ef61d156
226 |/
226 |/
227 o 0:e6eb3150255d
227 o 0:e6eb3150255d
228
228
229
229
230 $ hg glog
230 $ hg glog
231 @ changeset: 34:fea3ac5810e0
231 @ changeset: 34:fea3ac5810e0
232 | tag: tip
232 | tag: tip
233 | parent: 32:d06dffa21a31
233 | parent: 32:d06dffa21a31
234 | user: test
234 | user: test
235 | date: Thu Jan 01 00:00:34 1970 +0000
235 | date: Thu Jan 01 00:00:34 1970 +0000
236 | summary: (34) head
236 | summary: (34) head
237 |
237 |
238 | o changeset: 33:68608f5145f9
238 | o changeset: 33:68608f5145f9
239 | | parent: 18:1aa84d96232a
239 | | parent: 18:1aa84d96232a
240 | | user: test
240 | | user: test
241 | | date: Thu Jan 01 00:00:33 1970 +0000
241 | | date: Thu Jan 01 00:00:33 1970 +0000
242 | | summary: (33) head
242 | | summary: (33) head
243 | |
243 | |
244 o | changeset: 32:d06dffa21a31
244 o | changeset: 32:d06dffa21a31
245 |\ \ parent: 27:886ed638191b
245 |\ \ parent: 27:886ed638191b
246 | | | parent: 31:621d83e11f67
246 | | | parent: 31:621d83e11f67
247 | | | user: test
247 | | | user: test
248 | | | date: Thu Jan 01 00:00:32 1970 +0000
248 | | | date: Thu Jan 01 00:00:32 1970 +0000
249 | | | summary: (32) expand
249 | | | summary: (32) expand
250 | | |
250 | | |
251 | o | changeset: 31:621d83e11f67
251 | o | changeset: 31:621d83e11f67
252 | |\ \ parent: 21:d42a756af44d
252 | |\ \ parent: 21:d42a756af44d
253 | | | | parent: 30:6e11cd4b648f
253 | | | | parent: 30:6e11cd4b648f
254 | | | | user: test
254 | | | | user: test
255 | | | | date: Thu Jan 01 00:00:31 1970 +0000
255 | | | | date: Thu Jan 01 00:00:31 1970 +0000
256 | | | | summary: (31) expand
256 | | | | summary: (31) expand
257 | | | |
257 | | | |
258 | | o | changeset: 30:6e11cd4b648f
258 | | o | changeset: 30:6e11cd4b648f
259 | | |\ \ parent: 28:44ecd0b9ae99
259 | | |\ \ parent: 28:44ecd0b9ae99
260 | | | | | parent: 29:cd9bb2be7593
260 | | | | | parent: 29:cd9bb2be7593
261 | | | | | user: test
261 | | | | | user: test
262 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
262 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
263 | | | | | summary: (30) expand
263 | | | | | summary: (30) expand
264 | | | | |
264 | | | | |
265 | | | o | changeset: 29:cd9bb2be7593
265 | | | o | changeset: 29:cd9bb2be7593
266 | | | | | parent: 0:e6eb3150255d
266 | | | | | parent: 0:e6eb3150255d
267 | | | | | user: test
267 | | | | | user: test
268 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
268 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
269 | | | | | summary: (29) regular commit
269 | | | | | summary: (29) regular commit
270 | | | | |
270 | | | | |
271 | | o | | changeset: 28:44ecd0b9ae99
271 | | o | | changeset: 28:44ecd0b9ae99
272 | | |\ \ \ parent: 1:6db2ef61d156
272 | | |\ \ \ parent: 1:6db2ef61d156
273 | | | | | | parent: 26:7f25b6c2f0b9
273 | | | | | | parent: 26:7f25b6c2f0b9
274 | | | | | | user: test
274 | | | | | | user: test
275 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
275 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
276 | | | | | | summary: (28) merge zero known
276 | | | | | | summary: (28) merge zero known
277 | | | | | |
277 | | | | | |
278 o | | | | | changeset: 27:886ed638191b
278 o | | | | | changeset: 27:886ed638191b
279 |/ / / / / parent: 21:d42a756af44d
279 |/ / / / / parent: 21:d42a756af44d
280 | | | | | user: test
280 | | | | | user: test
281 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
281 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
282 | | | | | summary: (27) collapse
282 | | | | | summary: (27) collapse
283 | | | | |
283 | | | | |
284 | | o---+ changeset: 26:7f25b6c2f0b9
284 | | o---+ changeset: 26:7f25b6c2f0b9
285 | | | | | parent: 18:1aa84d96232a
285 | | | | | parent: 18:1aa84d96232a
286 | | | | | parent: 25:91da8ed57247
286 | | | | | parent: 25:91da8ed57247
287 | | | | | user: test
287 | | | | | user: test
288 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
288 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
289 | | | | | summary: (26) merge one known; far right
289 | | | | | summary: (26) merge one known; far right
290 | | | | |
290 | | | | |
291 +---o | | changeset: 25:91da8ed57247
291 +---o | | changeset: 25:91da8ed57247
292 | | | | | parent: 21:d42a756af44d
292 | | | | | parent: 21:d42a756af44d
293 | | | | | parent: 24:a9c19a3d96b7
293 | | | | | parent: 24:a9c19a3d96b7
294 | | | | | user: test
294 | | | | | user: test
295 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
295 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
296 | | | | | summary: (25) merge one known; far left
296 | | | | | summary: (25) merge one known; far left
297 | | | | |
297 | | | | |
298 | | o | | changeset: 24:a9c19a3d96b7
298 | | o | | changeset: 24:a9c19a3d96b7
299 | | |\| | parent: 0:e6eb3150255d
299 | | |\| | parent: 0:e6eb3150255d
300 | | | | | parent: 23:a01cddf0766d
300 | | | | | parent: 23:a01cddf0766d
301 | | | | | user: test
301 | | | | | user: test
302 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
302 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
303 | | | | | summary: (24) merge one known; immediate right
303 | | | | | summary: (24) merge one known; immediate right
304 | | | | |
304 | | | | |
305 | | o | | changeset: 23:a01cddf0766d
305 | | o | | changeset: 23:a01cddf0766d
306 | |/| | | parent: 1:6db2ef61d156
306 | |/| | | parent: 1:6db2ef61d156
307 | | | | | parent: 22:e0d9cccacb5d
307 | | | | | parent: 22:e0d9cccacb5d
308 | | | | | user: test
308 | | | | | user: test
309 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
309 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
310 | | | | | summary: (23) merge one known; immediate left
310 | | | | | summary: (23) merge one known; immediate left
311 | | | | |
311 | | | | |
312 +---o---+ changeset: 22:e0d9cccacb5d
312 +---o---+ changeset: 22:e0d9cccacb5d
313 | | | | parent: 18:1aa84d96232a
313 | | | | parent: 18:1aa84d96232a
314 | | / / parent: 21:d42a756af44d
314 | | / / parent: 21:d42a756af44d
315 | | | | user: test
315 | | | | user: test
316 | | | | date: Thu Jan 01 00:00:22 1970 +0000
316 | | | | date: Thu Jan 01 00:00:22 1970 +0000
317 | | | | summary: (22) merge two known; one far left, one far right
317 | | | | summary: (22) merge two known; one far left, one far right
318 | | | |
318 | | | |
319 o | | | changeset: 21:d42a756af44d
319 o | | | changeset: 21:d42a756af44d
320 |\ \ \ \ parent: 19:31ddc2c1573b
320 |\ \ \ \ parent: 19:31ddc2c1573b
321 | | | | | parent: 20:d30ed6450e32
321 | | | | | parent: 20:d30ed6450e32
322 | | | | | user: test
322 | | | | | user: test
323 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
323 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
324 | | | | | summary: (21) expand
324 | | | | | summary: (21) expand
325 | | | | |
325 | | | | |
326 | o---+-+ changeset: 20:d30ed6450e32
326 | o---+-+ changeset: 20:d30ed6450e32
327 | | | | parent: 0:e6eb3150255d
327 | | | | parent: 0:e6eb3150255d
328 | / / / parent: 18:1aa84d96232a
328 | / / / parent: 18:1aa84d96232a
329 | | | | user: test
329 | | | | user: test
330 | | | | date: Thu Jan 01 00:00:20 1970 +0000
330 | | | | date: Thu Jan 01 00:00:20 1970 +0000
331 | | | | summary: (20) merge two known; two far right
331 | | | | summary: (20) merge two known; two far right
332 | | | |
332 | | | |
333 o | | | changeset: 19:31ddc2c1573b
333 o | | | changeset: 19:31ddc2c1573b
334 |\ \ \ \ parent: 15:1dda3f72782d
334 |\ \ \ \ parent: 15:1dda3f72782d
335 | | | | | parent: 17:44765d7c06e0
335 | | | | | parent: 17:44765d7c06e0
336 | | | | | user: test
336 | | | | | user: test
337 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
337 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
338 | | | | | summary: (19) expand
338 | | | | | summary: (19) expand
339 | | | | |
339 | | | | |
340 +---+---o changeset: 18:1aa84d96232a
340 +---+---o changeset: 18:1aa84d96232a
341 | | | | parent: 1:6db2ef61d156
341 | | | | parent: 1:6db2ef61d156
342 | | | | parent: 15:1dda3f72782d
342 | | | | parent: 15:1dda3f72782d
343 | | | | user: test
343 | | | | user: test
344 | | | | date: Thu Jan 01 00:00:18 1970 +0000
344 | | | | date: Thu Jan 01 00:00:18 1970 +0000
345 | | | | summary: (18) merge two known; two far left
345 | | | | summary: (18) merge two known; two far left
346 | | | |
346 | | | |
347 | o | | changeset: 17:44765d7c06e0
347 | o | | changeset: 17:44765d7c06e0
348 | |\ \ \ parent: 12:86b91144a6e9
348 | |\ \ \ parent: 12:86b91144a6e9
349 | | | | | parent: 16:3677d192927d
349 | | | | | parent: 16:3677d192927d
350 | | | | | user: test
350 | | | | | user: test
351 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
351 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
352 | | | | | summary: (17) expand
352 | | | | | summary: (17) expand
353 | | | | |
353 | | | | |
354 | | o---+ changeset: 16:3677d192927d
354 | | o---+ changeset: 16:3677d192927d
355 | | | | | parent: 0:e6eb3150255d
355 | | | | | parent: 0:e6eb3150255d
356 | | |/ / parent: 1:6db2ef61d156
356 | | |/ / parent: 1:6db2ef61d156
357 | | | | user: test
357 | | | | user: test
358 | | | | date: Thu Jan 01 00:00:16 1970 +0000
358 | | | | date: Thu Jan 01 00:00:16 1970 +0000
359 | | | | summary: (16) merge two known; one immediate right, one near right
359 | | | | summary: (16) merge two known; one immediate right, one near right
360 | | | |
360 | | | |
361 o | | | changeset: 15:1dda3f72782d
361 o | | | changeset: 15:1dda3f72782d
362 |\ \ \ \ parent: 13:22d8966a97e3
362 |\ \ \ \ parent: 13:22d8966a97e3
363 | | | | | parent: 14:8eac370358ef
363 | | | | | parent: 14:8eac370358ef
364 | | | | | user: test
364 | | | | | user: test
365 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
365 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
366 | | | | | summary: (15) expand
366 | | | | | summary: (15) expand
367 | | | | |
367 | | | | |
368 | o-----+ changeset: 14:8eac370358ef
368 | o-----+ changeset: 14:8eac370358ef
369 | | | | | parent: 0:e6eb3150255d
369 | | | | | parent: 0:e6eb3150255d
370 | |/ / / parent: 12:86b91144a6e9
370 | |/ / / parent: 12:86b91144a6e9
371 | | | | user: test
371 | | | | user: test
372 | | | | date: Thu Jan 01 00:00:14 1970 +0000
372 | | | | date: Thu Jan 01 00:00:14 1970 +0000
373 | | | | summary: (14) merge two known; one immediate right, one far right
373 | | | | summary: (14) merge two known; one immediate right, one far right
374 | | | |
374 | | | |
375 o | | | changeset: 13:22d8966a97e3
375 o | | | changeset: 13:22d8966a97e3
376 |\ \ \ \ parent: 9:7010c0af0a35
376 |\ \ \ \ parent: 9:7010c0af0a35
377 | | | | | parent: 11:832d76e6bdf2
377 | | | | | parent: 11:832d76e6bdf2
378 | | | | | user: test
378 | | | | | user: test
379 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
379 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
380 | | | | | summary: (13) expand
380 | | | | | summary: (13) expand
381 | | | | |
381 | | | | |
382 +---o | | changeset: 12:86b91144a6e9
382 +---o | | changeset: 12:86b91144a6e9
383 | | |/ / parent: 1:6db2ef61d156
383 | | |/ / parent: 1:6db2ef61d156
384 | | | | parent: 9:7010c0af0a35
384 | | | | parent: 9:7010c0af0a35
385 | | | | user: test
385 | | | | user: test
386 | | | | date: Thu Jan 01 00:00:12 1970 +0000
386 | | | | date: Thu Jan 01 00:00:12 1970 +0000
387 | | | | summary: (12) merge two known; one immediate right, one far left
387 | | | | summary: (12) merge two known; one immediate right, one far left
388 | | | |
388 | | | |
389 | o | | changeset: 11:832d76e6bdf2
389 | o | | changeset: 11:832d76e6bdf2
390 | |\ \ \ parent: 6:b105a072e251
390 | |\ \ \ parent: 6:b105a072e251
391 | | | | | parent: 10:74c64d036d72
391 | | | | | parent: 10:74c64d036d72
392 | | | | | user: test
392 | | | | | user: test
393 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
393 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
394 | | | | | summary: (11) expand
394 | | | | | summary: (11) expand
395 | | | | |
395 | | | | |
396 | | o---+ changeset: 10:74c64d036d72
396 | | o---+ changeset: 10:74c64d036d72
397 | | | | | parent: 0:e6eb3150255d
397 | | | | | parent: 0:e6eb3150255d
398 | |/ / / parent: 6:b105a072e251
398 | |/ / / parent: 6:b105a072e251
399 | | | | user: test
399 | | | | user: test
400 | | | | date: Thu Jan 01 00:00:10 1970 +0000
400 | | | | date: Thu Jan 01 00:00:10 1970 +0000
401 | | | | summary: (10) merge two known; one immediate left, one near right
401 | | | | summary: (10) merge two known; one immediate left, one near right
402 | | | |
402 | | | |
403 o | | | changeset: 9:7010c0af0a35
403 o | | | changeset: 9:7010c0af0a35
404 |\ \ \ \ parent: 7:b632bb1b1224
404 |\ \ \ \ parent: 7:b632bb1b1224
405 | | | | | parent: 8:7a0b11f71937
405 | | | | | parent: 8:7a0b11f71937
406 | | | | | user: test
406 | | | | | user: test
407 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
407 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
408 | | | | | summary: (9) expand
408 | | | | | summary: (9) expand
409 | | | | |
409 | | | | |
410 | o-----+ changeset: 8:7a0b11f71937
410 | o-----+ changeset: 8:7a0b11f71937
411 | | | | | parent: 0:e6eb3150255d
411 | | | | | parent: 0:e6eb3150255d
412 |/ / / / parent: 7:b632bb1b1224
412 |/ / / / parent: 7:b632bb1b1224
413 | | | | user: test
413 | | | | user: test
414 | | | | date: Thu Jan 01 00:00:08 1970 +0000
414 | | | | date: Thu Jan 01 00:00:08 1970 +0000
415 | | | | summary: (8) merge two known; one immediate left, one far right
415 | | | | summary: (8) merge two known; one immediate left, one far right
416 | | | |
416 | | | |
417 o | | | changeset: 7:b632bb1b1224
417 o | | | changeset: 7:b632bb1b1224
418 |\ \ \ \ parent: 2:3d9a33b8d1e1
418 |\ \ \ \ parent: 2:3d9a33b8d1e1
419 | | | | | parent: 5:4409d547b708
419 | | | | | parent: 5:4409d547b708
420 | | | | | user: test
420 | | | | | user: test
421 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
421 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
422 | | | | | summary: (7) expand
422 | | | | | summary: (7) expand
423 | | | | |
423 | | | | |
424 +---o | | changeset: 6:b105a072e251
424 +---o | | changeset: 6:b105a072e251
425 | |/ / / parent: 2:3d9a33b8d1e1
425 | |/ / / parent: 2:3d9a33b8d1e1
426 | | | | parent: 5:4409d547b708
426 | | | | parent: 5:4409d547b708
427 | | | | user: test
427 | | | | user: test
428 | | | | date: Thu Jan 01 00:00:06 1970 +0000
428 | | | | date: Thu Jan 01 00:00:06 1970 +0000
429 | | | | summary: (6) merge two known; one immediate left, one far left
429 | | | | summary: (6) merge two known; one immediate left, one far left
430 | | | |
430 | | | |
431 | o | | changeset: 5:4409d547b708
431 | o | | changeset: 5:4409d547b708
432 | |\ \ \ parent: 3:27eef8ed80b4
432 | |\ \ \ parent: 3:27eef8ed80b4
433 | | | | | parent: 4:26a8bac39d9f
433 | | | | | parent: 4:26a8bac39d9f
434 | | | | | user: test
434 | | | | | user: test
435 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
435 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
436 | | | | | summary: (5) expand
436 | | | | | summary: (5) expand
437 | | | | |
437 | | | | |
438 | | o | | changeset: 4:26a8bac39d9f
438 | | o | | changeset: 4:26a8bac39d9f
439 | |/|/ / parent: 1:6db2ef61d156
439 | |/|/ / parent: 1:6db2ef61d156
440 | | | | parent: 3:27eef8ed80b4
440 | | | | parent: 3:27eef8ed80b4
441 | | | | user: test
441 | | | | user: test
442 | | | | date: Thu Jan 01 00:00:04 1970 +0000
442 | | | | date: Thu Jan 01 00:00:04 1970 +0000
443 | | | | summary: (4) merge two known; one immediate left, one immediate right
443 | | | | summary: (4) merge two known; one immediate left, one immediate right
444 | | | |
444 | | | |
445 | o | | changeset: 3:27eef8ed80b4
445 | o | | changeset: 3:27eef8ed80b4
446 |/ / / user: test
446 |/ / / user: test
447 | | | date: Thu Jan 01 00:00:03 1970 +0000
447 | | | date: Thu Jan 01 00:00:03 1970 +0000
448 | | | summary: (3) collapse
448 | | | summary: (3) collapse
449 | | |
449 | | |
450 o | | changeset: 2:3d9a33b8d1e1
450 o | | changeset: 2:3d9a33b8d1e1
451 |/ / user: test
451 |/ / user: test
452 | | date: Thu Jan 01 00:00:02 1970 +0000
452 | | date: Thu Jan 01 00:00:02 1970 +0000
453 | | summary: (2) collapse
453 | | summary: (2) collapse
454 | |
454 | |
455 o | changeset: 1:6db2ef61d156
455 o | changeset: 1:6db2ef61d156
456 |/ user: test
456 |/ user: test
457 | date: Thu Jan 01 00:00:01 1970 +0000
457 | date: Thu Jan 01 00:00:01 1970 +0000
458 | summary: (1) collapse
458 | summary: (1) collapse
459 |
459 |
460 o changeset: 0:e6eb3150255d
460 o changeset: 0:e6eb3150255d
461 user: test
461 user: test
462 date: Thu Jan 01 00:00:00 1970 +0000
462 date: Thu Jan 01 00:00:00 1970 +0000
463 summary: (0) root
463 summary: (0) root
464
464
465
465
466 File glog:
466 File glog:
467 $ hg glog a
467 $ hg glog a
468 @ changeset: 34:fea3ac5810e0
468 @ changeset: 34:fea3ac5810e0
469 | tag: tip
469 | tag: tip
470 | parent: 32:d06dffa21a31
470 | parent: 32:d06dffa21a31
471 | user: test
471 | user: test
472 | date: Thu Jan 01 00:00:34 1970 +0000
472 | date: Thu Jan 01 00:00:34 1970 +0000
473 | summary: (34) head
473 | summary: (34) head
474 |
474 |
475 | o changeset: 33:68608f5145f9
475 | o changeset: 33:68608f5145f9
476 | | parent: 18:1aa84d96232a
476 | | parent: 18:1aa84d96232a
477 | | user: test
477 | | user: test
478 | | date: Thu Jan 01 00:00:33 1970 +0000
478 | | date: Thu Jan 01 00:00:33 1970 +0000
479 | | summary: (33) head
479 | | summary: (33) head
480 | |
480 | |
481 o | changeset: 32:d06dffa21a31
481 o | changeset: 32:d06dffa21a31
482 |\ \ parent: 27:886ed638191b
482 |\ \ parent: 27:886ed638191b
483 | | | parent: 31:621d83e11f67
483 | | | parent: 31:621d83e11f67
484 | | | user: test
484 | | | user: test
485 | | | date: Thu Jan 01 00:00:32 1970 +0000
485 | | | date: Thu Jan 01 00:00:32 1970 +0000
486 | | | summary: (32) expand
486 | | | summary: (32) expand
487 | | |
487 | | |
488 | o | changeset: 31:621d83e11f67
488 | o | changeset: 31:621d83e11f67
489 | |\ \ parent: 21:d42a756af44d
489 | |\ \ parent: 21:d42a756af44d
490 | | | | parent: 30:6e11cd4b648f
490 | | | | parent: 30:6e11cd4b648f
491 | | | | user: test
491 | | | | user: test
492 | | | | date: Thu Jan 01 00:00:31 1970 +0000
492 | | | | date: Thu Jan 01 00:00:31 1970 +0000
493 | | | | summary: (31) expand
493 | | | | summary: (31) expand
494 | | | |
494 | | | |
495 | | o | changeset: 30:6e11cd4b648f
495 | | o | changeset: 30:6e11cd4b648f
496 | | |\ \ parent: 28:44ecd0b9ae99
496 | | |\ \ parent: 28:44ecd0b9ae99
497 | | | | | parent: 29:cd9bb2be7593
497 | | | | | parent: 29:cd9bb2be7593
498 | | | | | user: test
498 | | | | | user: test
499 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
499 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
500 | | | | | summary: (30) expand
500 | | | | | summary: (30) expand
501 | | | | |
501 | | | | |
502 | | | o | changeset: 29:cd9bb2be7593
502 | | | o | changeset: 29:cd9bb2be7593
503 | | | | | parent: 0:e6eb3150255d
503 | | | | | parent: 0:e6eb3150255d
504 | | | | | user: test
504 | | | | | user: test
505 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
505 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
506 | | | | | summary: (29) regular commit
506 | | | | | summary: (29) regular commit
507 | | | | |
507 | | | | |
508 | | o | | changeset: 28:44ecd0b9ae99
508 | | o | | changeset: 28:44ecd0b9ae99
509 | | |\ \ \ parent: 1:6db2ef61d156
509 | | |\ \ \ parent: 1:6db2ef61d156
510 | | | | | | parent: 26:7f25b6c2f0b9
510 | | | | | | parent: 26:7f25b6c2f0b9
511 | | | | | | user: test
511 | | | | | | user: test
512 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
512 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
513 | | | | | | summary: (28) merge zero known
513 | | | | | | summary: (28) merge zero known
514 | | | | | |
514 | | | | | |
515 o | | | | | changeset: 27:886ed638191b
515 o | | | | | changeset: 27:886ed638191b
516 |/ / / / / parent: 21:d42a756af44d
516 |/ / / / / parent: 21:d42a756af44d
517 | | | | | user: test
517 | | | | | user: test
518 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
518 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
519 | | | | | summary: (27) collapse
519 | | | | | summary: (27) collapse
520 | | | | |
520 | | | | |
521 | | o---+ changeset: 26:7f25b6c2f0b9
521 | | o---+ changeset: 26:7f25b6c2f0b9
522 | | | | | parent: 18:1aa84d96232a
522 | | | | | parent: 18:1aa84d96232a
523 | | | | | parent: 25:91da8ed57247
523 | | | | | parent: 25:91da8ed57247
524 | | | | | user: test
524 | | | | | user: test
525 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
525 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
526 | | | | | summary: (26) merge one known; far right
526 | | | | | summary: (26) merge one known; far right
527 | | | | |
527 | | | | |
528 +---o | | changeset: 25:91da8ed57247
528 +---o | | changeset: 25:91da8ed57247
529 | | | | | parent: 21:d42a756af44d
529 | | | | | parent: 21:d42a756af44d
530 | | | | | parent: 24:a9c19a3d96b7
530 | | | | | parent: 24:a9c19a3d96b7
531 | | | | | user: test
531 | | | | | user: test
532 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
532 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
533 | | | | | summary: (25) merge one known; far left
533 | | | | | summary: (25) merge one known; far left
534 | | | | |
534 | | | | |
535 | | o | | changeset: 24:a9c19a3d96b7
535 | | o | | changeset: 24:a9c19a3d96b7
536 | | |\| | parent: 0:e6eb3150255d
536 | | |\| | parent: 0:e6eb3150255d
537 | | | | | parent: 23:a01cddf0766d
537 | | | | | parent: 23:a01cddf0766d
538 | | | | | user: test
538 | | | | | user: test
539 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
539 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
540 | | | | | summary: (24) merge one known; immediate right
540 | | | | | summary: (24) merge one known; immediate right
541 | | | | |
541 | | | | |
542 | | o | | changeset: 23:a01cddf0766d
542 | | o | | changeset: 23:a01cddf0766d
543 | |/| | | parent: 1:6db2ef61d156
543 | |/| | | parent: 1:6db2ef61d156
544 | | | | | parent: 22:e0d9cccacb5d
544 | | | | | parent: 22:e0d9cccacb5d
545 | | | | | user: test
545 | | | | | user: test
546 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
546 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
547 | | | | | summary: (23) merge one known; immediate left
547 | | | | | summary: (23) merge one known; immediate left
548 | | | | |
548 | | | | |
549 +---o---+ changeset: 22:e0d9cccacb5d
549 +---o---+ changeset: 22:e0d9cccacb5d
550 | | | | parent: 18:1aa84d96232a
550 | | | | parent: 18:1aa84d96232a
551 | | / / parent: 21:d42a756af44d
551 | | / / parent: 21:d42a756af44d
552 | | | | user: test
552 | | | | user: test
553 | | | | date: Thu Jan 01 00:00:22 1970 +0000
553 | | | | date: Thu Jan 01 00:00:22 1970 +0000
554 | | | | summary: (22) merge two known; one far left, one far right
554 | | | | summary: (22) merge two known; one far left, one far right
555 | | | |
555 | | | |
556 o | | | changeset: 21:d42a756af44d
556 o | | | changeset: 21:d42a756af44d
557 |\ \ \ \ parent: 19:31ddc2c1573b
557 |\ \ \ \ parent: 19:31ddc2c1573b
558 | | | | | parent: 20:d30ed6450e32
558 | | | | | parent: 20:d30ed6450e32
559 | | | | | user: test
559 | | | | | user: test
560 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
560 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
561 | | | | | summary: (21) expand
561 | | | | | summary: (21) expand
562 | | | | |
562 | | | | |
563 | o---+-+ changeset: 20:d30ed6450e32
563 | o---+-+ changeset: 20:d30ed6450e32
564 | | | | parent: 0:e6eb3150255d
564 | | | | parent: 0:e6eb3150255d
565 | / / / parent: 18:1aa84d96232a
565 | / / / parent: 18:1aa84d96232a
566 | | | | user: test
566 | | | | user: test
567 | | | | date: Thu Jan 01 00:00:20 1970 +0000
567 | | | | date: Thu Jan 01 00:00:20 1970 +0000
568 | | | | summary: (20) merge two known; two far right
568 | | | | summary: (20) merge two known; two far right
569 | | | |
569 | | | |
570 o | | | changeset: 19:31ddc2c1573b
570 o | | | changeset: 19:31ddc2c1573b
571 |\ \ \ \ parent: 15:1dda3f72782d
571 |\ \ \ \ parent: 15:1dda3f72782d
572 | | | | | parent: 17:44765d7c06e0
572 | | | | | parent: 17:44765d7c06e0
573 | | | | | user: test
573 | | | | | user: test
574 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
574 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
575 | | | | | summary: (19) expand
575 | | | | | summary: (19) expand
576 | | | | |
576 | | | | |
577 +---+---o changeset: 18:1aa84d96232a
577 +---+---o changeset: 18:1aa84d96232a
578 | | | | parent: 1:6db2ef61d156
578 | | | | parent: 1:6db2ef61d156
579 | | | | parent: 15:1dda3f72782d
579 | | | | parent: 15:1dda3f72782d
580 | | | | user: test
580 | | | | user: test
581 | | | | date: Thu Jan 01 00:00:18 1970 +0000
581 | | | | date: Thu Jan 01 00:00:18 1970 +0000
582 | | | | summary: (18) merge two known; two far left
582 | | | | summary: (18) merge two known; two far left
583 | | | |
583 | | | |
584 | o | | changeset: 17:44765d7c06e0
584 | o | | changeset: 17:44765d7c06e0
585 | |\ \ \ parent: 12:86b91144a6e9
585 | |\ \ \ parent: 12:86b91144a6e9
586 | | | | | parent: 16:3677d192927d
586 | | | | | parent: 16:3677d192927d
587 | | | | | user: test
587 | | | | | user: test
588 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
588 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
589 | | | | | summary: (17) expand
589 | | | | | summary: (17) expand
590 | | | | |
590 | | | | |
591 | | o---+ changeset: 16:3677d192927d
591 | | o---+ changeset: 16:3677d192927d
592 | | | | | parent: 0:e6eb3150255d
592 | | | | | parent: 0:e6eb3150255d
593 | | |/ / parent: 1:6db2ef61d156
593 | | |/ / parent: 1:6db2ef61d156
594 | | | | user: test
594 | | | | user: test
595 | | | | date: Thu Jan 01 00:00:16 1970 +0000
595 | | | | date: Thu Jan 01 00:00:16 1970 +0000
596 | | | | summary: (16) merge two known; one immediate right, one near right
596 | | | | summary: (16) merge two known; one immediate right, one near right
597 | | | |
597 | | | |
598 o | | | changeset: 15:1dda3f72782d
598 o | | | changeset: 15:1dda3f72782d
599 |\ \ \ \ parent: 13:22d8966a97e3
599 |\ \ \ \ parent: 13:22d8966a97e3
600 | | | | | parent: 14:8eac370358ef
600 | | | | | parent: 14:8eac370358ef
601 | | | | | user: test
601 | | | | | user: test
602 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
602 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
603 | | | | | summary: (15) expand
603 | | | | | summary: (15) expand
604 | | | | |
604 | | | | |
605 | o-----+ changeset: 14:8eac370358ef
605 | o-----+ changeset: 14:8eac370358ef
606 | | | | | parent: 0:e6eb3150255d
606 | | | | | parent: 0:e6eb3150255d
607 | |/ / / parent: 12:86b91144a6e9
607 | |/ / / parent: 12:86b91144a6e9
608 | | | | user: test
608 | | | | user: test
609 | | | | date: Thu Jan 01 00:00:14 1970 +0000
609 | | | | date: Thu Jan 01 00:00:14 1970 +0000
610 | | | | summary: (14) merge two known; one immediate right, one far right
610 | | | | summary: (14) merge two known; one immediate right, one far right
611 | | | |
611 | | | |
612 o | | | changeset: 13:22d8966a97e3
612 o | | | changeset: 13:22d8966a97e3
613 |\ \ \ \ parent: 9:7010c0af0a35
613 |\ \ \ \ parent: 9:7010c0af0a35
614 | | | | | parent: 11:832d76e6bdf2
614 | | | | | parent: 11:832d76e6bdf2
615 | | | | | user: test
615 | | | | | user: test
616 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
616 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
617 | | | | | summary: (13) expand
617 | | | | | summary: (13) expand
618 | | | | |
618 | | | | |
619 +---o | | changeset: 12:86b91144a6e9
619 +---o | | changeset: 12:86b91144a6e9
620 | | |/ / parent: 1:6db2ef61d156
620 | | |/ / parent: 1:6db2ef61d156
621 | | | | parent: 9:7010c0af0a35
621 | | | | parent: 9:7010c0af0a35
622 | | | | user: test
622 | | | | user: test
623 | | | | date: Thu Jan 01 00:00:12 1970 +0000
623 | | | | date: Thu Jan 01 00:00:12 1970 +0000
624 | | | | summary: (12) merge two known; one immediate right, one far left
624 | | | | summary: (12) merge two known; one immediate right, one far left
625 | | | |
625 | | | |
626 | o | | changeset: 11:832d76e6bdf2
626 | o | | changeset: 11:832d76e6bdf2
627 | |\ \ \ parent: 6:b105a072e251
627 | |\ \ \ parent: 6:b105a072e251
628 | | | | | parent: 10:74c64d036d72
628 | | | | | parent: 10:74c64d036d72
629 | | | | | user: test
629 | | | | | user: test
630 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
630 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
631 | | | | | summary: (11) expand
631 | | | | | summary: (11) expand
632 | | | | |
632 | | | | |
633 | | o---+ changeset: 10:74c64d036d72
633 | | o---+ changeset: 10:74c64d036d72
634 | | | | | parent: 0:e6eb3150255d
634 | | | | | parent: 0:e6eb3150255d
635 | |/ / / parent: 6:b105a072e251
635 | |/ / / parent: 6:b105a072e251
636 | | | | user: test
636 | | | | user: test
637 | | | | date: Thu Jan 01 00:00:10 1970 +0000
637 | | | | date: Thu Jan 01 00:00:10 1970 +0000
638 | | | | summary: (10) merge two known; one immediate left, one near right
638 | | | | summary: (10) merge two known; one immediate left, one near right
639 | | | |
639 | | | |
640 o | | | changeset: 9:7010c0af0a35
640 o | | | changeset: 9:7010c0af0a35
641 |\ \ \ \ parent: 7:b632bb1b1224
641 |\ \ \ \ parent: 7:b632bb1b1224
642 | | | | | parent: 8:7a0b11f71937
642 | | | | | parent: 8:7a0b11f71937
643 | | | | | user: test
643 | | | | | user: test
644 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
644 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
645 | | | | | summary: (9) expand
645 | | | | | summary: (9) expand
646 | | | | |
646 | | | | |
647 | o-----+ changeset: 8:7a0b11f71937
647 | o-----+ changeset: 8:7a0b11f71937
648 | | | | | parent: 0:e6eb3150255d
648 | | | | | parent: 0:e6eb3150255d
649 |/ / / / parent: 7:b632bb1b1224
649 |/ / / / parent: 7:b632bb1b1224
650 | | | | user: test
650 | | | | user: test
651 | | | | date: Thu Jan 01 00:00:08 1970 +0000
651 | | | | date: Thu Jan 01 00:00:08 1970 +0000
652 | | | | summary: (8) merge two known; one immediate left, one far right
652 | | | | summary: (8) merge two known; one immediate left, one far right
653 | | | |
653 | | | |
654 o | | | changeset: 7:b632bb1b1224
654 o | | | changeset: 7:b632bb1b1224
655 |\ \ \ \ parent: 2:3d9a33b8d1e1
655 |\ \ \ \ parent: 2:3d9a33b8d1e1
656 | | | | | parent: 5:4409d547b708
656 | | | | | parent: 5:4409d547b708
657 | | | | | user: test
657 | | | | | user: test
658 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
658 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
659 | | | | | summary: (7) expand
659 | | | | | summary: (7) expand
660 | | | | |
660 | | | | |
661 +---o | | changeset: 6:b105a072e251
661 +---o | | changeset: 6:b105a072e251
662 | |/ / / parent: 2:3d9a33b8d1e1
662 | |/ / / parent: 2:3d9a33b8d1e1
663 | | | | parent: 5:4409d547b708
663 | | | | parent: 5:4409d547b708
664 | | | | user: test
664 | | | | user: test
665 | | | | date: Thu Jan 01 00:00:06 1970 +0000
665 | | | | date: Thu Jan 01 00:00:06 1970 +0000
666 | | | | summary: (6) merge two known; one immediate left, one far left
666 | | | | summary: (6) merge two known; one immediate left, one far left
667 | | | |
667 | | | |
668 | o | | changeset: 5:4409d547b708
668 | o | | changeset: 5:4409d547b708
669 | |\ \ \ parent: 3:27eef8ed80b4
669 | |\ \ \ parent: 3:27eef8ed80b4
670 | | | | | parent: 4:26a8bac39d9f
670 | | | | | parent: 4:26a8bac39d9f
671 | | | | | user: test
671 | | | | | user: test
672 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
672 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
673 | | | | | summary: (5) expand
673 | | | | | summary: (5) expand
674 | | | | |
674 | | | | |
675 | | o | | changeset: 4:26a8bac39d9f
675 | | o | | changeset: 4:26a8bac39d9f
676 | |/|/ / parent: 1:6db2ef61d156
676 | |/|/ / parent: 1:6db2ef61d156
677 | | | | parent: 3:27eef8ed80b4
677 | | | | parent: 3:27eef8ed80b4
678 | | | | user: test
678 | | | | user: test
679 | | | | date: Thu Jan 01 00:00:04 1970 +0000
679 | | | | date: Thu Jan 01 00:00:04 1970 +0000
680 | | | | summary: (4) merge two known; one immediate left, one immediate right
680 | | | | summary: (4) merge two known; one immediate left, one immediate right
681 | | | |
681 | | | |
682 | o | | changeset: 3:27eef8ed80b4
682 | o | | changeset: 3:27eef8ed80b4
683 |/ / / user: test
683 |/ / / user: test
684 | | | date: Thu Jan 01 00:00:03 1970 +0000
684 | | | date: Thu Jan 01 00:00:03 1970 +0000
685 | | | summary: (3) collapse
685 | | | summary: (3) collapse
686 | | |
686 | | |
687 o | | changeset: 2:3d9a33b8d1e1
687 o | | changeset: 2:3d9a33b8d1e1
688 |/ / user: test
688 |/ / user: test
689 | | date: Thu Jan 01 00:00:02 1970 +0000
689 | | date: Thu Jan 01 00:00:02 1970 +0000
690 | | summary: (2) collapse
690 | | summary: (2) collapse
691 | |
691 | |
692 o | changeset: 1:6db2ef61d156
692 o | changeset: 1:6db2ef61d156
693 |/ user: test
693 |/ user: test
694 | date: Thu Jan 01 00:00:01 1970 +0000
694 | date: Thu Jan 01 00:00:01 1970 +0000
695 | summary: (1) collapse
695 | summary: (1) collapse
696 |
696 |
697 o changeset: 0:e6eb3150255d
697 o changeset: 0:e6eb3150255d
698 user: test
698 user: test
699 date: Thu Jan 01 00:00:00 1970 +0000
699 date: Thu Jan 01 00:00:00 1970 +0000
700 summary: (0) root
700 summary: (0) root
701
701
702
702
703 File glog per revset:
703 File glog per revset:
704
704
705 $ hg glog -r 'file("a")'
705 $ hg glog -r 'file("a")'
706 @ changeset: 34:fea3ac5810e0
706 @ changeset: 34:fea3ac5810e0
707 | tag: tip
707 | tag: tip
708 | parent: 32:d06dffa21a31
708 | parent: 32:d06dffa21a31
709 | user: test
709 | user: test
710 | date: Thu Jan 01 00:00:34 1970 +0000
710 | date: Thu Jan 01 00:00:34 1970 +0000
711 | summary: (34) head
711 | summary: (34) head
712 |
712 |
713 | o changeset: 33:68608f5145f9
713 | o changeset: 33:68608f5145f9
714 | | parent: 18:1aa84d96232a
714 | | parent: 18:1aa84d96232a
715 | | user: test
715 | | user: test
716 | | date: Thu Jan 01 00:00:33 1970 +0000
716 | | date: Thu Jan 01 00:00:33 1970 +0000
717 | | summary: (33) head
717 | | summary: (33) head
718 | |
718 | |
719 o | changeset: 32:d06dffa21a31
719 o | changeset: 32:d06dffa21a31
720 |\ \ parent: 27:886ed638191b
720 |\ \ parent: 27:886ed638191b
721 | | | parent: 31:621d83e11f67
721 | | | parent: 31:621d83e11f67
722 | | | user: test
722 | | | user: test
723 | | | date: Thu Jan 01 00:00:32 1970 +0000
723 | | | date: Thu Jan 01 00:00:32 1970 +0000
724 | | | summary: (32) expand
724 | | | summary: (32) expand
725 | | |
725 | | |
726 | o | changeset: 31:621d83e11f67
726 | o | changeset: 31:621d83e11f67
727 | |\ \ parent: 21:d42a756af44d
727 | |\ \ parent: 21:d42a756af44d
728 | | | | parent: 30:6e11cd4b648f
728 | | | | parent: 30:6e11cd4b648f
729 | | | | user: test
729 | | | | user: test
730 | | | | date: Thu Jan 01 00:00:31 1970 +0000
730 | | | | date: Thu Jan 01 00:00:31 1970 +0000
731 | | | | summary: (31) expand
731 | | | | summary: (31) expand
732 | | | |
732 | | | |
733 | | o | changeset: 30:6e11cd4b648f
733 | | o | changeset: 30:6e11cd4b648f
734 | | |\ \ parent: 28:44ecd0b9ae99
734 | | |\ \ parent: 28:44ecd0b9ae99
735 | | | | | parent: 29:cd9bb2be7593
735 | | | | | parent: 29:cd9bb2be7593
736 | | | | | user: test
736 | | | | | user: test
737 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
737 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
738 | | | | | summary: (30) expand
738 | | | | | summary: (30) expand
739 | | | | |
739 | | | | |
740 | | | o | changeset: 29:cd9bb2be7593
740 | | | o | changeset: 29:cd9bb2be7593
741 | | | | | parent: 0:e6eb3150255d
741 | | | | | parent: 0:e6eb3150255d
742 | | | | | user: test
742 | | | | | user: test
743 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
743 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
744 | | | | | summary: (29) regular commit
744 | | | | | summary: (29) regular commit
745 | | | | |
745 | | | | |
746 | | o | | changeset: 28:44ecd0b9ae99
746 | | o | | changeset: 28:44ecd0b9ae99
747 | | |\ \ \ parent: 1:6db2ef61d156
747 | | |\ \ \ parent: 1:6db2ef61d156
748 | | | | | | parent: 26:7f25b6c2f0b9
748 | | | | | | parent: 26:7f25b6c2f0b9
749 | | | | | | user: test
749 | | | | | | user: test
750 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
750 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
751 | | | | | | summary: (28) merge zero known
751 | | | | | | summary: (28) merge zero known
752 | | | | | |
752 | | | | | |
753 o | | | | | changeset: 27:886ed638191b
753 o | | | | | changeset: 27:886ed638191b
754 |/ / / / / parent: 21:d42a756af44d
754 |/ / / / / parent: 21:d42a756af44d
755 | | | | | user: test
755 | | | | | user: test
756 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
756 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
757 | | | | | summary: (27) collapse
757 | | | | | summary: (27) collapse
758 | | | | |
758 | | | | |
759 | | o---+ changeset: 26:7f25b6c2f0b9
759 | | o---+ changeset: 26:7f25b6c2f0b9
760 | | | | | parent: 18:1aa84d96232a
760 | | | | | parent: 18:1aa84d96232a
761 | | | | | parent: 25:91da8ed57247
761 | | | | | parent: 25:91da8ed57247
762 | | | | | user: test
762 | | | | | user: test
763 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
763 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
764 | | | | | summary: (26) merge one known; far right
764 | | | | | summary: (26) merge one known; far right
765 | | | | |
765 | | | | |
766 +---o | | changeset: 25:91da8ed57247
766 +---o | | changeset: 25:91da8ed57247
767 | | | | | parent: 21:d42a756af44d
767 | | | | | parent: 21:d42a756af44d
768 | | | | | parent: 24:a9c19a3d96b7
768 | | | | | parent: 24:a9c19a3d96b7
769 | | | | | user: test
769 | | | | | user: test
770 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
770 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
771 | | | | | summary: (25) merge one known; far left
771 | | | | | summary: (25) merge one known; far left
772 | | | | |
772 | | | | |
773 | | o | | changeset: 24:a9c19a3d96b7
773 | | o | | changeset: 24:a9c19a3d96b7
774 | | |\| | parent: 0:e6eb3150255d
774 | | |\| | parent: 0:e6eb3150255d
775 | | | | | parent: 23:a01cddf0766d
775 | | | | | parent: 23:a01cddf0766d
776 | | | | | user: test
776 | | | | | user: test
777 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
777 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
778 | | | | | summary: (24) merge one known; immediate right
778 | | | | | summary: (24) merge one known; immediate right
779 | | | | |
779 | | | | |
780 | | o | | changeset: 23:a01cddf0766d
780 | | o | | changeset: 23:a01cddf0766d
781 | |/| | | parent: 1:6db2ef61d156
781 | |/| | | parent: 1:6db2ef61d156
782 | | | | | parent: 22:e0d9cccacb5d
782 | | | | | parent: 22:e0d9cccacb5d
783 | | | | | user: test
783 | | | | | user: test
784 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
784 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
785 | | | | | summary: (23) merge one known; immediate left
785 | | | | | summary: (23) merge one known; immediate left
786 | | | | |
786 | | | | |
787 +---o---+ changeset: 22:e0d9cccacb5d
787 +---o---+ changeset: 22:e0d9cccacb5d
788 | | | | parent: 18:1aa84d96232a
788 | | | | parent: 18:1aa84d96232a
789 | | / / parent: 21:d42a756af44d
789 | | / / parent: 21:d42a756af44d
790 | | | | user: test
790 | | | | user: test
791 | | | | date: Thu Jan 01 00:00:22 1970 +0000
791 | | | | date: Thu Jan 01 00:00:22 1970 +0000
792 | | | | summary: (22) merge two known; one far left, one far right
792 | | | | summary: (22) merge two known; one far left, one far right
793 | | | |
793 | | | |
794 o | | | changeset: 21:d42a756af44d
794 o | | | changeset: 21:d42a756af44d
795 |\ \ \ \ parent: 19:31ddc2c1573b
795 |\ \ \ \ parent: 19:31ddc2c1573b
796 | | | | | parent: 20:d30ed6450e32
796 | | | | | parent: 20:d30ed6450e32
797 | | | | | user: test
797 | | | | | user: test
798 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
798 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
799 | | | | | summary: (21) expand
799 | | | | | summary: (21) expand
800 | | | | |
800 | | | | |
801 | o---+-+ changeset: 20:d30ed6450e32
801 | o---+-+ changeset: 20:d30ed6450e32
802 | | | | parent: 0:e6eb3150255d
802 | | | | parent: 0:e6eb3150255d
803 | / / / parent: 18:1aa84d96232a
803 | / / / parent: 18:1aa84d96232a
804 | | | | user: test
804 | | | | user: test
805 | | | | date: Thu Jan 01 00:00:20 1970 +0000
805 | | | | date: Thu Jan 01 00:00:20 1970 +0000
806 | | | | summary: (20) merge two known; two far right
806 | | | | summary: (20) merge two known; two far right
807 | | | |
807 | | | |
808 o | | | changeset: 19:31ddc2c1573b
808 o | | | changeset: 19:31ddc2c1573b
809 |\ \ \ \ parent: 15:1dda3f72782d
809 |\ \ \ \ parent: 15:1dda3f72782d
810 | | | | | parent: 17:44765d7c06e0
810 | | | | | parent: 17:44765d7c06e0
811 | | | | | user: test
811 | | | | | user: test
812 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
812 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
813 | | | | | summary: (19) expand
813 | | | | | summary: (19) expand
814 | | | | |
814 | | | | |
815 +---+---o changeset: 18:1aa84d96232a
815 +---+---o changeset: 18:1aa84d96232a
816 | | | | parent: 1:6db2ef61d156
816 | | | | parent: 1:6db2ef61d156
817 | | | | parent: 15:1dda3f72782d
817 | | | | parent: 15:1dda3f72782d
818 | | | | user: test
818 | | | | user: test
819 | | | | date: Thu Jan 01 00:00:18 1970 +0000
819 | | | | date: Thu Jan 01 00:00:18 1970 +0000
820 | | | | summary: (18) merge two known; two far left
820 | | | | summary: (18) merge two known; two far left
821 | | | |
821 | | | |
822 | o | | changeset: 17:44765d7c06e0
822 | o | | changeset: 17:44765d7c06e0
823 | |\ \ \ parent: 12:86b91144a6e9
823 | |\ \ \ parent: 12:86b91144a6e9
824 | | | | | parent: 16:3677d192927d
824 | | | | | parent: 16:3677d192927d
825 | | | | | user: test
825 | | | | | user: test
826 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
826 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
827 | | | | | summary: (17) expand
827 | | | | | summary: (17) expand
828 | | | | |
828 | | | | |
829 | | o---+ changeset: 16:3677d192927d
829 | | o---+ changeset: 16:3677d192927d
830 | | | | | parent: 0:e6eb3150255d
830 | | | | | parent: 0:e6eb3150255d
831 | | |/ / parent: 1:6db2ef61d156
831 | | |/ / parent: 1:6db2ef61d156
832 | | | | user: test
832 | | | | user: test
833 | | | | date: Thu Jan 01 00:00:16 1970 +0000
833 | | | | date: Thu Jan 01 00:00:16 1970 +0000
834 | | | | summary: (16) merge two known; one immediate right, one near right
834 | | | | summary: (16) merge two known; one immediate right, one near right
835 | | | |
835 | | | |
836 o | | | changeset: 15:1dda3f72782d
836 o | | | changeset: 15:1dda3f72782d
837 |\ \ \ \ parent: 13:22d8966a97e3
837 |\ \ \ \ parent: 13:22d8966a97e3
838 | | | | | parent: 14:8eac370358ef
838 | | | | | parent: 14:8eac370358ef
839 | | | | | user: test
839 | | | | | user: test
840 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
840 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
841 | | | | | summary: (15) expand
841 | | | | | summary: (15) expand
842 | | | | |
842 | | | | |
843 | o-----+ changeset: 14:8eac370358ef
843 | o-----+ changeset: 14:8eac370358ef
844 | | | | | parent: 0:e6eb3150255d
844 | | | | | parent: 0:e6eb3150255d
845 | |/ / / parent: 12:86b91144a6e9
845 | |/ / / parent: 12:86b91144a6e9
846 | | | | user: test
846 | | | | user: test
847 | | | | date: Thu Jan 01 00:00:14 1970 +0000
847 | | | | date: Thu Jan 01 00:00:14 1970 +0000
848 | | | | summary: (14) merge two known; one immediate right, one far right
848 | | | | summary: (14) merge two known; one immediate right, one far right
849 | | | |
849 | | | |
850 o | | | changeset: 13:22d8966a97e3
850 o | | | changeset: 13:22d8966a97e3
851 |\ \ \ \ parent: 9:7010c0af0a35
851 |\ \ \ \ parent: 9:7010c0af0a35
852 | | | | | parent: 11:832d76e6bdf2
852 | | | | | parent: 11:832d76e6bdf2
853 | | | | | user: test
853 | | | | | user: test
854 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
854 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
855 | | | | | summary: (13) expand
855 | | | | | summary: (13) expand
856 | | | | |
856 | | | | |
857 +---o | | changeset: 12:86b91144a6e9
857 +---o | | changeset: 12:86b91144a6e9
858 | | |/ / parent: 1:6db2ef61d156
858 | | |/ / parent: 1:6db2ef61d156
859 | | | | parent: 9:7010c0af0a35
859 | | | | parent: 9:7010c0af0a35
860 | | | | user: test
860 | | | | user: test
861 | | | | date: Thu Jan 01 00:00:12 1970 +0000
861 | | | | date: Thu Jan 01 00:00:12 1970 +0000
862 | | | | summary: (12) merge two known; one immediate right, one far left
862 | | | | summary: (12) merge two known; one immediate right, one far left
863 | | | |
863 | | | |
864 | o | | changeset: 11:832d76e6bdf2
864 | o | | changeset: 11:832d76e6bdf2
865 | |\ \ \ parent: 6:b105a072e251
865 | |\ \ \ parent: 6:b105a072e251
866 | | | | | parent: 10:74c64d036d72
866 | | | | | parent: 10:74c64d036d72
867 | | | | | user: test
867 | | | | | user: test
868 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
868 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
869 | | | | | summary: (11) expand
869 | | | | | summary: (11) expand
870 | | | | |
870 | | | | |
871 | | o---+ changeset: 10:74c64d036d72
871 | | o---+ changeset: 10:74c64d036d72
872 | | | | | parent: 0:e6eb3150255d
872 | | | | | parent: 0:e6eb3150255d
873 | |/ / / parent: 6:b105a072e251
873 | |/ / / parent: 6:b105a072e251
874 | | | | user: test
874 | | | | user: test
875 | | | | date: Thu Jan 01 00:00:10 1970 +0000
875 | | | | date: Thu Jan 01 00:00:10 1970 +0000
876 | | | | summary: (10) merge two known; one immediate left, one near right
876 | | | | summary: (10) merge two known; one immediate left, one near right
877 | | | |
877 | | | |
878 o | | | changeset: 9:7010c0af0a35
878 o | | | changeset: 9:7010c0af0a35
879 |\ \ \ \ parent: 7:b632bb1b1224
879 |\ \ \ \ parent: 7:b632bb1b1224
880 | | | | | parent: 8:7a0b11f71937
880 | | | | | parent: 8:7a0b11f71937
881 | | | | | user: test
881 | | | | | user: test
882 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
882 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
883 | | | | | summary: (9) expand
883 | | | | | summary: (9) expand
884 | | | | |
884 | | | | |
885 | o-----+ changeset: 8:7a0b11f71937
885 | o-----+ changeset: 8:7a0b11f71937
886 | | | | | parent: 0:e6eb3150255d
886 | | | | | parent: 0:e6eb3150255d
887 |/ / / / parent: 7:b632bb1b1224
887 |/ / / / parent: 7:b632bb1b1224
888 | | | | user: test
888 | | | | user: test
889 | | | | date: Thu Jan 01 00:00:08 1970 +0000
889 | | | | date: Thu Jan 01 00:00:08 1970 +0000
890 | | | | summary: (8) merge two known; one immediate left, one far right
890 | | | | summary: (8) merge two known; one immediate left, one far right
891 | | | |
891 | | | |
892 o | | | changeset: 7:b632bb1b1224
892 o | | | changeset: 7:b632bb1b1224
893 |\ \ \ \ parent: 2:3d9a33b8d1e1
893 |\ \ \ \ parent: 2:3d9a33b8d1e1
894 | | | | | parent: 5:4409d547b708
894 | | | | | parent: 5:4409d547b708
895 | | | | | user: test
895 | | | | | user: test
896 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
896 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
897 | | | | | summary: (7) expand
897 | | | | | summary: (7) expand
898 | | | | |
898 | | | | |
899 +---o | | changeset: 6:b105a072e251
899 +---o | | changeset: 6:b105a072e251
900 | |/ / / parent: 2:3d9a33b8d1e1
900 | |/ / / parent: 2:3d9a33b8d1e1
901 | | | | parent: 5:4409d547b708
901 | | | | parent: 5:4409d547b708
902 | | | | user: test
902 | | | | user: test
903 | | | | date: Thu Jan 01 00:00:06 1970 +0000
903 | | | | date: Thu Jan 01 00:00:06 1970 +0000
904 | | | | summary: (6) merge two known; one immediate left, one far left
904 | | | | summary: (6) merge two known; one immediate left, one far left
905 | | | |
905 | | | |
906 | o | | changeset: 5:4409d547b708
906 | o | | changeset: 5:4409d547b708
907 | |\ \ \ parent: 3:27eef8ed80b4
907 | |\ \ \ parent: 3:27eef8ed80b4
908 | | | | | parent: 4:26a8bac39d9f
908 | | | | | parent: 4:26a8bac39d9f
909 | | | | | user: test
909 | | | | | user: test
910 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
910 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
911 | | | | | summary: (5) expand
911 | | | | | summary: (5) expand
912 | | | | |
912 | | | | |
913 | | o | | changeset: 4:26a8bac39d9f
913 | | o | | changeset: 4:26a8bac39d9f
914 | |/|/ / parent: 1:6db2ef61d156
914 | |/|/ / parent: 1:6db2ef61d156
915 | | | | parent: 3:27eef8ed80b4
915 | | | | parent: 3:27eef8ed80b4
916 | | | | user: test
916 | | | | user: test
917 | | | | date: Thu Jan 01 00:00:04 1970 +0000
917 | | | | date: Thu Jan 01 00:00:04 1970 +0000
918 | | | | summary: (4) merge two known; one immediate left, one immediate right
918 | | | | summary: (4) merge two known; one immediate left, one immediate right
919 | | | |
919 | | | |
920 | o | | changeset: 3:27eef8ed80b4
920 | o | | changeset: 3:27eef8ed80b4
921 |/ / / user: test
921 |/ / / user: test
922 | | | date: Thu Jan 01 00:00:03 1970 +0000
922 | | | date: Thu Jan 01 00:00:03 1970 +0000
923 | | | summary: (3) collapse
923 | | | summary: (3) collapse
924 | | |
924 | | |
925 o | | changeset: 2:3d9a33b8d1e1
925 o | | changeset: 2:3d9a33b8d1e1
926 |/ / user: test
926 |/ / user: test
927 | | date: Thu Jan 01 00:00:02 1970 +0000
927 | | date: Thu Jan 01 00:00:02 1970 +0000
928 | | summary: (2) collapse
928 | | summary: (2) collapse
929 | |
929 | |
930 o | changeset: 1:6db2ef61d156
930 o | changeset: 1:6db2ef61d156
931 |/ user: test
931 |/ user: test
932 | date: Thu Jan 01 00:00:01 1970 +0000
932 | date: Thu Jan 01 00:00:01 1970 +0000
933 | summary: (1) collapse
933 | summary: (1) collapse
934 |
934 |
935 o changeset: 0:e6eb3150255d
935 o changeset: 0:e6eb3150255d
936 user: test
936 user: test
937 date: Thu Jan 01 00:00:00 1970 +0000
937 date: Thu Jan 01 00:00:00 1970 +0000
938 summary: (0) root
938 summary: (0) root
939
939
940
940
941
941
942 File glog per revset (only merges):
942 File glog per revset (only merges):
943
943
944 $ hg log -G -r 'file("a")' -m
944 $ hg log -G -r 'file("a")' -m
945 o changeset: 32:d06dffa21a31
945 o changeset: 32:d06dffa21a31
946 |\ parent: 27:886ed638191b
946 |\ parent: 27:886ed638191b
947 | | parent: 31:621d83e11f67
947 | | parent: 31:621d83e11f67
948 | | user: test
948 | | user: test
949 | | date: Thu Jan 01 00:00:32 1970 +0000
949 | | date: Thu Jan 01 00:00:32 1970 +0000
950 | | summary: (32) expand
950 | | summary: (32) expand
951 | |
951 | |
952 o | changeset: 31:621d83e11f67
952 o | changeset: 31:621d83e11f67
953 |\| parent: 21:d42a756af44d
953 |\| parent: 21:d42a756af44d
954 | | parent: 30:6e11cd4b648f
954 | | parent: 30:6e11cd4b648f
955 | | user: test
955 | | user: test
956 | | date: Thu Jan 01 00:00:31 1970 +0000
956 | | date: Thu Jan 01 00:00:31 1970 +0000
957 | | summary: (31) expand
957 | | summary: (31) expand
958 | |
958 | |
959 o | changeset: 30:6e11cd4b648f
959 o | changeset: 30:6e11cd4b648f
960 |\ \ parent: 28:44ecd0b9ae99
960 |\ \ parent: 28:44ecd0b9ae99
961 | | | parent: 29:cd9bb2be7593
961 | | | parent: 29:cd9bb2be7593
962 | | | user: test
962 | | | user: test
963 | | | date: Thu Jan 01 00:00:30 1970 +0000
963 | | | date: Thu Jan 01 00:00:30 1970 +0000
964 | | | summary: (30) expand
964 | | | summary: (30) expand
965 | | |
965 | | |
966 o | | changeset: 28:44ecd0b9ae99
966 o | | changeset: 28:44ecd0b9ae99
967 |\ \ \ parent: 1:6db2ef61d156
967 |\ \ \ parent: 1:6db2ef61d156
968 | | | | parent: 26:7f25b6c2f0b9
968 | | | | parent: 26:7f25b6c2f0b9
969 | | | | user: test
969 | | | | user: test
970 | | | | date: Thu Jan 01 00:00:28 1970 +0000
970 | | | | date: Thu Jan 01 00:00:28 1970 +0000
971 | | | | summary: (28) merge zero known
971 | | | | summary: (28) merge zero known
972 | | | |
972 | | | |
973 o | | | changeset: 26:7f25b6c2f0b9
973 o | | | changeset: 26:7f25b6c2f0b9
974 |\ \ \ \ parent: 18:1aa84d96232a
974 |\ \ \ \ parent: 18:1aa84d96232a
975 | | | | | parent: 25:91da8ed57247
975 | | | | | parent: 25:91da8ed57247
976 | | | | | user: test
976 | | | | | user: test
977 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
977 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
978 | | | | | summary: (26) merge one known; far right
978 | | | | | summary: (26) merge one known; far right
979 | | | | |
979 | | | | |
980 | o-----+ changeset: 25:91da8ed57247
980 | o-----+ changeset: 25:91da8ed57247
981 | | | | | parent: 21:d42a756af44d
981 | | | | | parent: 21:d42a756af44d
982 | | | | | parent: 24:a9c19a3d96b7
982 | | | | | parent: 24:a9c19a3d96b7
983 | | | | | user: test
983 | | | | | user: test
984 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
984 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
985 | | | | | summary: (25) merge one known; far left
985 | | | | | summary: (25) merge one known; far left
986 | | | | |
986 | | | | |
987 | o | | | changeset: 24:a9c19a3d96b7
987 | o | | | changeset: 24:a9c19a3d96b7
988 | |\ \ \ \ parent: 0:e6eb3150255d
988 | |\ \ \ \ parent: 0:e6eb3150255d
989 | | | | | | parent: 23:a01cddf0766d
989 | | | | | | parent: 23:a01cddf0766d
990 | | | | | | user: test
990 | | | | | | user: test
991 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
991 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
992 | | | | | | summary: (24) merge one known; immediate right
992 | | | | | | summary: (24) merge one known; immediate right
993 | | | | | |
993 | | | | | |
994 | o---+ | | changeset: 23:a01cddf0766d
994 | o---+ | | changeset: 23:a01cddf0766d
995 | | | | | | parent: 1:6db2ef61d156
995 | | | | | | parent: 1:6db2ef61d156
996 | | | | | | parent: 22:e0d9cccacb5d
996 | | | | | | parent: 22:e0d9cccacb5d
997 | | | | | | user: test
997 | | | | | | user: test
998 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
998 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
999 | | | | | | summary: (23) merge one known; immediate left
999 | | | | | | summary: (23) merge one known; immediate left
1000 | | | | | |
1000 | | | | | |
1001 | o-------+ changeset: 22:e0d9cccacb5d
1001 | o-------+ changeset: 22:e0d9cccacb5d
1002 | | | | | | parent: 18:1aa84d96232a
1002 | | | | | | parent: 18:1aa84d96232a
1003 |/ / / / / parent: 21:d42a756af44d
1003 |/ / / / / parent: 21:d42a756af44d
1004 | | | | | user: test
1004 | | | | | user: test
1005 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
1005 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
1006 | | | | | summary: (22) merge two known; one far left, one far right
1006 | | | | | summary: (22) merge two known; one far left, one far right
1007 | | | | |
1007 | | | | |
1008 | | | | o changeset: 21:d42a756af44d
1008 | | | | o changeset: 21:d42a756af44d
1009 | | | | |\ parent: 19:31ddc2c1573b
1009 | | | | |\ parent: 19:31ddc2c1573b
1010 | | | | | | parent: 20:d30ed6450e32
1010 | | | | | | parent: 20:d30ed6450e32
1011 | | | | | | user: test
1011 | | | | | | user: test
1012 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
1012 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
1013 | | | | | | summary: (21) expand
1013 | | | | | | summary: (21) expand
1014 | | | | | |
1014 | | | | | |
1015 +-+-------o changeset: 20:d30ed6450e32
1015 +-+-------o changeset: 20:d30ed6450e32
1016 | | | | | parent: 0:e6eb3150255d
1016 | | | | | parent: 0:e6eb3150255d
1017 | | | | | parent: 18:1aa84d96232a
1017 | | | | | parent: 18:1aa84d96232a
1018 | | | | | user: test
1018 | | | | | user: test
1019 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
1019 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
1020 | | | | | summary: (20) merge two known; two far right
1020 | | | | | summary: (20) merge two known; two far right
1021 | | | | |
1021 | | | | |
1022 | | | | o changeset: 19:31ddc2c1573b
1022 | | | | o changeset: 19:31ddc2c1573b
1023 | | | | |\ parent: 15:1dda3f72782d
1023 | | | | |\ parent: 15:1dda3f72782d
1024 | | | | | | parent: 17:44765d7c06e0
1024 | | | | | | parent: 17:44765d7c06e0
1025 | | | | | | user: test
1025 | | | | | | user: test
1026 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
1026 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
1027 | | | | | | summary: (19) expand
1027 | | | | | | summary: (19) expand
1028 | | | | | |
1028 | | | | | |
1029 o---+---+ | changeset: 18:1aa84d96232a
1029 o---+---+ | changeset: 18:1aa84d96232a
1030 | | | | | parent: 1:6db2ef61d156
1030 | | | | | parent: 1:6db2ef61d156
1031 / / / / / parent: 15:1dda3f72782d
1031 / / / / / parent: 15:1dda3f72782d
1032 | | | | | user: test
1032 | | | | | user: test
1033 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
1033 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
1034 | | | | | summary: (18) merge two known; two far left
1034 | | | | | summary: (18) merge two known; two far left
1035 | | | | |
1035 | | | | |
1036 | | | | o changeset: 17:44765d7c06e0
1036 | | | | o changeset: 17:44765d7c06e0
1037 | | | | |\ parent: 12:86b91144a6e9
1037 | | | | |\ parent: 12:86b91144a6e9
1038 | | | | | | parent: 16:3677d192927d
1038 | | | | | | parent: 16:3677d192927d
1039 | | | | | | user: test
1039 | | | | | | user: test
1040 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
1040 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
1041 | | | | | | summary: (17) expand
1041 | | | | | | summary: (17) expand
1042 | | | | | |
1042 | | | | | |
1043 +-+-------o changeset: 16:3677d192927d
1043 +-+-------o changeset: 16:3677d192927d
1044 | | | | | parent: 0:e6eb3150255d
1044 | | | | | parent: 0:e6eb3150255d
1045 | | | | | parent: 1:6db2ef61d156
1045 | | | | | parent: 1:6db2ef61d156
1046 | | | | | user: test
1046 | | | | | user: test
1047 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
1047 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
1048 | | | | | summary: (16) merge two known; one immediate right, one near right
1048 | | | | | summary: (16) merge two known; one immediate right, one near right
1049 | | | | |
1049 | | | | |
1050 | | | o | changeset: 15:1dda3f72782d
1050 | | | o | changeset: 15:1dda3f72782d
1051 | | | |\ \ parent: 13:22d8966a97e3
1051 | | | |\ \ parent: 13:22d8966a97e3
1052 | | | | | | parent: 14:8eac370358ef
1052 | | | | | | parent: 14:8eac370358ef
1053 | | | | | | user: test
1053 | | | | | | user: test
1054 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
1054 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
1055 | | | | | | summary: (15) expand
1055 | | | | | | summary: (15) expand
1056 | | | | | |
1056 | | | | | |
1057 +-------o | changeset: 14:8eac370358ef
1057 +-------o | changeset: 14:8eac370358ef
1058 | | | | |/ parent: 0:e6eb3150255d
1058 | | | | |/ parent: 0:e6eb3150255d
1059 | | | | | parent: 12:86b91144a6e9
1059 | | | | | parent: 12:86b91144a6e9
1060 | | | | | user: test
1060 | | | | | user: test
1061 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
1061 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
1062 | | | | | summary: (14) merge two known; one immediate right, one far right
1062 | | | | | summary: (14) merge two known; one immediate right, one far right
1063 | | | | |
1063 | | | | |
1064 | | | o | changeset: 13:22d8966a97e3
1064 | | | o | changeset: 13:22d8966a97e3
1065 | | | |\ \ parent: 9:7010c0af0a35
1065 | | | |\ \ parent: 9:7010c0af0a35
1066 | | | | | | parent: 11:832d76e6bdf2
1066 | | | | | | parent: 11:832d76e6bdf2
1067 | | | | | | user: test
1067 | | | | | | user: test
1068 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
1068 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
1069 | | | | | | summary: (13) expand
1069 | | | | | | summary: (13) expand
1070 | | | | | |
1070 | | | | | |
1071 | +---+---o changeset: 12:86b91144a6e9
1071 | +---+---o changeset: 12:86b91144a6e9
1072 | | | | | parent: 1:6db2ef61d156
1072 | | | | | parent: 1:6db2ef61d156
1073 | | | | | parent: 9:7010c0af0a35
1073 | | | | | parent: 9:7010c0af0a35
1074 | | | | | user: test
1074 | | | | | user: test
1075 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
1075 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
1076 | | | | | summary: (12) merge two known; one immediate right, one far left
1076 | | | | | summary: (12) merge two known; one immediate right, one far left
1077 | | | | |
1077 | | | | |
1078 | | | | o changeset: 11:832d76e6bdf2
1078 | | | | o changeset: 11:832d76e6bdf2
1079 | | | | |\ parent: 6:b105a072e251
1079 | | | | |\ parent: 6:b105a072e251
1080 | | | | | | parent: 10:74c64d036d72
1080 | | | | | | parent: 10:74c64d036d72
1081 | | | | | | user: test
1081 | | | | | | user: test
1082 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
1082 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
1083 | | | | | | summary: (11) expand
1083 | | | | | | summary: (11) expand
1084 | | | | | |
1084 | | | | | |
1085 +---------o changeset: 10:74c64d036d72
1085 +---------o changeset: 10:74c64d036d72
1086 | | | | |/ parent: 0:e6eb3150255d
1086 | | | | |/ parent: 0:e6eb3150255d
1087 | | | | | parent: 6:b105a072e251
1087 | | | | | parent: 6:b105a072e251
1088 | | | | | user: test
1088 | | | | | user: test
1089 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
1089 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
1090 | | | | | summary: (10) merge two known; one immediate left, one near right
1090 | | | | | summary: (10) merge two known; one immediate left, one near right
1091 | | | | |
1091 | | | | |
1092 | | | o | changeset: 9:7010c0af0a35
1092 | | | o | changeset: 9:7010c0af0a35
1093 | | | |\ \ parent: 7:b632bb1b1224
1093 | | | |\ \ parent: 7:b632bb1b1224
1094 | | | | | | parent: 8:7a0b11f71937
1094 | | | | | | parent: 8:7a0b11f71937
1095 | | | | | | user: test
1095 | | | | | | user: test
1096 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
1096 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
1097 | | | | | | summary: (9) expand
1097 | | | | | | summary: (9) expand
1098 | | | | | |
1098 | | | | | |
1099 +-------o | changeset: 8:7a0b11f71937
1099 +-------o | changeset: 8:7a0b11f71937
1100 | | | |/ / parent: 0:e6eb3150255d
1100 | | | |/ / parent: 0:e6eb3150255d
1101 | | | | | parent: 7:b632bb1b1224
1101 | | | | | parent: 7:b632bb1b1224
1102 | | | | | user: test
1102 | | | | | user: test
1103 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
1103 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
1104 | | | | | summary: (8) merge two known; one immediate left, one far right
1104 | | | | | summary: (8) merge two known; one immediate left, one far right
1105 | | | | |
1105 | | | | |
1106 | | | o | changeset: 7:b632bb1b1224
1106 | | | o | changeset: 7:b632bb1b1224
1107 | | | |\ \ parent: 2:3d9a33b8d1e1
1107 | | | |\ \ parent: 2:3d9a33b8d1e1
1108 | | | | | | parent: 5:4409d547b708
1108 | | | | | | parent: 5:4409d547b708
1109 | | | | | | user: test
1109 | | | | | | user: test
1110 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
1110 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
1111 | | | | | | summary: (7) expand
1111 | | | | | | summary: (7) expand
1112 | | | | | |
1112 | | | | | |
1113 | | | +---o changeset: 6:b105a072e251
1113 | | | +---o changeset: 6:b105a072e251
1114 | | | | |/ parent: 2:3d9a33b8d1e1
1114 | | | | |/ parent: 2:3d9a33b8d1e1
1115 | | | | | parent: 5:4409d547b708
1115 | | | | | parent: 5:4409d547b708
1116 | | | | | user: test
1116 | | | | | user: test
1117 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
1117 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
1118 | | | | | summary: (6) merge two known; one immediate left, one far left
1118 | | | | | summary: (6) merge two known; one immediate left, one far left
1119 | | | | |
1119 | | | | |
1120 | | | o | changeset: 5:4409d547b708
1120 | | | o | changeset: 5:4409d547b708
1121 | | | |\ \ parent: 3:27eef8ed80b4
1121 | | | |\ \ parent: 3:27eef8ed80b4
1122 | | | | | | parent: 4:26a8bac39d9f
1122 | | | | | | parent: 4:26a8bac39d9f
1123 | | | | | | user: test
1123 | | | | | | user: test
1124 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
1124 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
1125 | | | | | | summary: (5) expand
1125 | | | | | | summary: (5) expand
1126 | | | | | |
1126 | | | | | |
1127 | +---o | | changeset: 4:26a8bac39d9f
1127 | +---o | | changeset: 4:26a8bac39d9f
1128 | | | |/ / parent: 1:6db2ef61d156
1128 | | | |/ / parent: 1:6db2ef61d156
1129 | | | | | parent: 3:27eef8ed80b4
1129 | | | | | parent: 3:27eef8ed80b4
1130 | | | | | user: test
1130 | | | | | user: test
1131 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
1131 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
1132 | | | | | summary: (4) merge two known; one immediate left, one immediate right
1132 | | | | | summary: (4) merge two known; one immediate left, one immediate right
1133 | | | | |
1133 | | | | |
1134
1134
1135
1135
1136 Empty revision range - display nothing:
1136 Empty revision range - display nothing:
1137 $ hg glog -r 1..0
1137 $ hg glog -r 1..0
1138
1138
1139 From outer space:
1139 From outer space:
1140 $ cd ..
1140 $ cd ..
1141 $ hg glog -l1 repo
1141 $ hg glog -l1 repo
1142 @ changeset: 34:fea3ac5810e0
1142 @ changeset: 34:fea3ac5810e0
1143 | tag: tip
1143 | tag: tip
1144 | parent: 32:d06dffa21a31
1144 | parent: 32:d06dffa21a31
1145 | user: test
1145 | user: test
1146 | date: Thu Jan 01 00:00:34 1970 +0000
1146 | date: Thu Jan 01 00:00:34 1970 +0000
1147 | summary: (34) head
1147 | summary: (34) head
1148 |
1148 |
1149 $ hg glog -l1 repo/a
1149 $ hg glog -l1 repo/a
1150 @ changeset: 34:fea3ac5810e0
1150 @ changeset: 34:fea3ac5810e0
1151 | tag: tip
1151 | tag: tip
1152 | parent: 32:d06dffa21a31
1152 | parent: 32:d06dffa21a31
1153 | user: test
1153 | user: test
1154 | date: Thu Jan 01 00:00:34 1970 +0000
1154 | date: Thu Jan 01 00:00:34 1970 +0000
1155 | summary: (34) head
1155 | summary: (34) head
1156 |
1156 |
1157 $ hg glog -l1 repo/missing
1157 $ hg glog -l1 repo/missing
1158
1158
1159 File log with revs != cset revs:
1159 File log with revs != cset revs:
1160 $ hg init flog
1160 $ hg init flog
1161 $ cd flog
1161 $ cd flog
1162 $ echo one >one
1162 $ echo one >one
1163 $ hg add one
1163 $ hg add one
1164 $ hg commit -mone
1164 $ hg commit -mone
1165 $ echo two >two
1165 $ echo two >two
1166 $ hg add two
1166 $ hg add two
1167 $ hg commit -mtwo
1167 $ hg commit -mtwo
1168 $ echo more >two
1168 $ echo more >two
1169 $ hg commit -mmore
1169 $ hg commit -mmore
1170 $ hg glog two
1170 $ hg glog two
1171 @ changeset: 2:12c28321755b
1171 @ changeset: 2:12c28321755b
1172 | tag: tip
1172 | tag: tip
1173 | user: test
1173 | user: test
1174 | date: Thu Jan 01 00:00:00 1970 +0000
1174 | date: Thu Jan 01 00:00:00 1970 +0000
1175 | summary: more
1175 | summary: more
1176 |
1176 |
1177 o changeset: 1:5ac72c0599bf
1177 o changeset: 1:5ac72c0599bf
1178 | user: test
1178 | user: test
1179 | date: Thu Jan 01 00:00:00 1970 +0000
1179 | date: Thu Jan 01 00:00:00 1970 +0000
1180 | summary: two
1180 | summary: two
1181 |
1181 |
1182
1182
1183 Issue1896: File log with explicit style
1183 Issue1896: File log with explicit style
1184 $ hg glog --style=default one
1184 $ hg glog --style=default one
1185 o changeset: 0:3d578b4a1f53
1185 o changeset: 0:3d578b4a1f53
1186 user: test
1186 user: test
1187 date: Thu Jan 01 00:00:00 1970 +0000
1187 date: Thu Jan 01 00:00:00 1970 +0000
1188 summary: one
1188 summary: one
1189
1189
1190 Issue2395: glog --style header and footer
1190 Issue2395: glog --style header and footer
1191 $ hg glog --style=xml one
1191 $ hg glog --style=xml one
1192 <?xml version="1.0"?>
1192 <?xml version="1.0"?>
1193 <log>
1193 <log>
1194 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1194 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1195 <author email="test">test</author>
1195 <author email="test">test</author>
1196 <date>1970-01-01T00:00:00+00:00</date>
1196 <date>1970-01-01T00:00:00+00:00</date>
1197 <msg xml:space="preserve">one</msg>
1197 <msg xml:space="preserve">one</msg>
1198 </logentry>
1198 </logentry>
1199 </log>
1199 </log>
1200
1200
1201 $ cd ..
1201 $ cd ..
1202
1202
1203 Incoming and outgoing:
1203 Incoming and outgoing:
1204
1204
1205 $ hg clone -U -r31 repo repo2
1205 $ hg clone -U -r31 repo repo2
1206 adding changesets
1206 adding changesets
1207 adding manifests
1207 adding manifests
1208 adding file changes
1208 adding file changes
1209 added 31 changesets with 31 changes to 1 files
1209 added 31 changesets with 31 changes to 1 files
1210 $ cd repo2
1210 $ cd repo2
1211
1211
1212 $ hg incoming --graph ../repo
1212 $ hg incoming --graph ../repo
1213 comparing with ../repo
1213 comparing with ../repo
1214 searching for changes
1214 searching for changes
1215 o changeset: 34:fea3ac5810e0
1215 o changeset: 34:fea3ac5810e0
1216 | tag: tip
1216 | tag: tip
1217 | parent: 32:d06dffa21a31
1217 | parent: 32:d06dffa21a31
1218 | user: test
1218 | user: test
1219 | date: Thu Jan 01 00:00:34 1970 +0000
1219 | date: Thu Jan 01 00:00:34 1970 +0000
1220 | summary: (34) head
1220 | summary: (34) head
1221 |
1221 |
1222 | o changeset: 33:68608f5145f9
1222 | o changeset: 33:68608f5145f9
1223 | parent: 18:1aa84d96232a
1223 | parent: 18:1aa84d96232a
1224 | user: test
1224 | user: test
1225 | date: Thu Jan 01 00:00:33 1970 +0000
1225 | date: Thu Jan 01 00:00:33 1970 +0000
1226 | summary: (33) head
1226 | summary: (33) head
1227 |
1227 |
1228 o changeset: 32:d06dffa21a31
1228 o changeset: 32:d06dffa21a31
1229 | parent: 27:886ed638191b
1229 | parent: 27:886ed638191b
1230 | parent: 31:621d83e11f67
1230 | parent: 31:621d83e11f67
1231 | user: test
1231 | user: test
1232 | date: Thu Jan 01 00:00:32 1970 +0000
1232 | date: Thu Jan 01 00:00:32 1970 +0000
1233 | summary: (32) expand
1233 | summary: (32) expand
1234 |
1234 |
1235 o changeset: 27:886ed638191b
1235 o changeset: 27:886ed638191b
1236 parent: 21:d42a756af44d
1236 parent: 21:d42a756af44d
1237 user: test
1237 user: test
1238 date: Thu Jan 01 00:00:27 1970 +0000
1238 date: Thu Jan 01 00:00:27 1970 +0000
1239 summary: (27) collapse
1239 summary: (27) collapse
1240
1240
1241 $ cd ..
1241 $ cd ..
1242
1242
1243 $ hg -R repo outgoing --graph repo2
1243 $ hg -R repo outgoing --graph repo2
1244 comparing with repo2
1244 comparing with repo2
1245 searching for changes
1245 searching for changes
1246 @ changeset: 34:fea3ac5810e0
1246 @ changeset: 34:fea3ac5810e0
1247 | tag: tip
1247 | tag: tip
1248 | parent: 32:d06dffa21a31
1248 | parent: 32:d06dffa21a31
1249 | user: test
1249 | user: test
1250 | date: Thu Jan 01 00:00:34 1970 +0000
1250 | date: Thu Jan 01 00:00:34 1970 +0000
1251 | summary: (34) head
1251 | summary: (34) head
1252 |
1252 |
1253 | o changeset: 33:68608f5145f9
1253 | o changeset: 33:68608f5145f9
1254 | parent: 18:1aa84d96232a
1254 | parent: 18:1aa84d96232a
1255 | user: test
1255 | user: test
1256 | date: Thu Jan 01 00:00:33 1970 +0000
1256 | date: Thu Jan 01 00:00:33 1970 +0000
1257 | summary: (33) head
1257 | summary: (33) head
1258 |
1258 |
1259 o changeset: 32:d06dffa21a31
1259 o changeset: 32:d06dffa21a31
1260 | parent: 27:886ed638191b
1260 | parent: 27:886ed638191b
1261 | parent: 31:621d83e11f67
1261 | parent: 31:621d83e11f67
1262 | user: test
1262 | user: test
1263 | date: Thu Jan 01 00:00:32 1970 +0000
1263 | date: Thu Jan 01 00:00:32 1970 +0000
1264 | summary: (32) expand
1264 | summary: (32) expand
1265 |
1265 |
1266 o changeset: 27:886ed638191b
1266 o changeset: 27:886ed638191b
1267 parent: 21:d42a756af44d
1267 parent: 21:d42a756af44d
1268 user: test
1268 user: test
1269 date: Thu Jan 01 00:00:27 1970 +0000
1269 date: Thu Jan 01 00:00:27 1970 +0000
1270 summary: (27) collapse
1270 summary: (27) collapse
1271
1271
1272
1272
1273 File + limit with revs != cset revs:
1273 File + limit with revs != cset revs:
1274 $ cd repo
1274 $ cd repo
1275 $ touch b
1275 $ touch b
1276 $ hg ci -Aqm0
1276 $ hg ci -Aqm0
1277 $ hg glog -l2 a
1277 $ hg glog -l2 a
1278 o changeset: 34:fea3ac5810e0
1278 o changeset: 34:fea3ac5810e0
1279 | parent: 32:d06dffa21a31
1279 | parent: 32:d06dffa21a31
1280 | user: test
1280 | user: test
1281 | date: Thu Jan 01 00:00:34 1970 +0000
1281 | date: Thu Jan 01 00:00:34 1970 +0000
1282 | summary: (34) head
1282 | summary: (34) head
1283 |
1283 |
1284 | o changeset: 33:68608f5145f9
1284 | o changeset: 33:68608f5145f9
1285 | | parent: 18:1aa84d96232a
1285 | | parent: 18:1aa84d96232a
1286 | | user: test
1286 | | user: test
1287 | | date: Thu Jan 01 00:00:33 1970 +0000
1287 | | date: Thu Jan 01 00:00:33 1970 +0000
1288 | | summary: (33) head
1288 | | summary: (33) head
1289 | |
1289 | |
1290
1290
1291 File + limit + -ra:b, (b - a) < limit:
1291 File + limit + -ra:b, (b - a) < limit:
1292 $ hg glog -l3000 -r32:tip a
1292 $ hg glog -l3000 -r32:tip a
1293 o changeset: 34:fea3ac5810e0
1293 o changeset: 34:fea3ac5810e0
1294 | parent: 32:d06dffa21a31
1294 | parent: 32:d06dffa21a31
1295 | user: test
1295 | user: test
1296 | date: Thu Jan 01 00:00:34 1970 +0000
1296 | date: Thu Jan 01 00:00:34 1970 +0000
1297 | summary: (34) head
1297 | summary: (34) head
1298 |
1298 |
1299 | o changeset: 33:68608f5145f9
1299 | o changeset: 33:68608f5145f9
1300 | | parent: 18:1aa84d96232a
1300 | | parent: 18:1aa84d96232a
1301 | | user: test
1301 | | user: test
1302 | | date: Thu Jan 01 00:00:33 1970 +0000
1302 | | date: Thu Jan 01 00:00:33 1970 +0000
1303 | | summary: (33) head
1303 | | summary: (33) head
1304 | |
1304 | |
1305 o | changeset: 32:d06dffa21a31
1305 o | changeset: 32:d06dffa21a31
1306 |\ \ parent: 27:886ed638191b
1306 |\ \ parent: 27:886ed638191b
1307 | | | parent: 31:621d83e11f67
1307 | | | parent: 31:621d83e11f67
1308 | | | user: test
1308 | | | user: test
1309 | | | date: Thu Jan 01 00:00:32 1970 +0000
1309 | | | date: Thu Jan 01 00:00:32 1970 +0000
1310 | | | summary: (32) expand
1310 | | | summary: (32) expand
1311 | | |
1311 | | |
1312
1312
1313 Point out a common and an uncommon unshown parent
1313 Point out a common and an uncommon unshown parent
1314
1314
1315 $ hg glog -r 'rev(8) or rev(9)'
1315 $ hg glog -r 'rev(8) or rev(9)'
1316 o changeset: 9:7010c0af0a35
1316 o changeset: 9:7010c0af0a35
1317 |\ parent: 7:b632bb1b1224
1317 |\ parent: 7:b632bb1b1224
1318 | | parent: 8:7a0b11f71937
1318 | | parent: 8:7a0b11f71937
1319 | | user: test
1319 | | user: test
1320 | | date: Thu Jan 01 00:00:09 1970 +0000
1320 | | date: Thu Jan 01 00:00:09 1970 +0000
1321 | | summary: (9) expand
1321 | | summary: (9) expand
1322 | |
1322 | |
1323 o | changeset: 8:7a0b11f71937
1323 o | changeset: 8:7a0b11f71937
1324 |\| parent: 0:e6eb3150255d
1324 |\| parent: 0:e6eb3150255d
1325 | | parent: 7:b632bb1b1224
1325 | | parent: 7:b632bb1b1224
1326 | | user: test
1326 | | user: test
1327 | | date: Thu Jan 01 00:00:08 1970 +0000
1327 | | date: Thu Jan 01 00:00:08 1970 +0000
1328 | | summary: (8) merge two known; one immediate left, one far right
1328 | | summary: (8) merge two known; one immediate left, one far right
1329 | |
1329 | |
1330
1330
1331 File + limit + -ra:b, b < tip:
1331 File + limit + -ra:b, b < tip:
1332
1332
1333 $ hg glog -l1 -r32:34 a
1333 $ hg glog -l1 -r32:34 a
1334 o changeset: 34:fea3ac5810e0
1334 o changeset: 34:fea3ac5810e0
1335 | parent: 32:d06dffa21a31
1335 | parent: 32:d06dffa21a31
1336 | user: test
1336 | user: test
1337 | date: Thu Jan 01 00:00:34 1970 +0000
1337 | date: Thu Jan 01 00:00:34 1970 +0000
1338 | summary: (34) head
1338 | summary: (34) head
1339 |
1339 |
1340
1340
1341 file(File) + limit + -ra:b, b < tip:
1341 file(File) + limit + -ra:b, b < tip:
1342
1342
1343 $ hg glog -l1 -r32:34 -r 'file("a")'
1343 $ hg glog -l1 -r32:34 -r 'file("a")'
1344 o changeset: 34:fea3ac5810e0
1344 o changeset: 34:fea3ac5810e0
1345 | parent: 32:d06dffa21a31
1345 | parent: 32:d06dffa21a31
1346 | user: test
1346 | user: test
1347 | date: Thu Jan 01 00:00:34 1970 +0000
1347 | date: Thu Jan 01 00:00:34 1970 +0000
1348 | summary: (34) head
1348 | summary: (34) head
1349 |
1349 |
1350
1350
1351 limit(file(File) and a::b), b < tip:
1351 limit(file(File) and a::b), b < tip:
1352
1352
1353 $ hg glog -r 'limit(file("a") and 32::34, 1)'
1353 $ hg glog -r 'limit(file("a") and 32::34, 1)'
1354 o changeset: 32:d06dffa21a31
1354 o changeset: 32:d06dffa21a31
1355 |\ parent: 27:886ed638191b
1355 |\ parent: 27:886ed638191b
1356 | | parent: 31:621d83e11f67
1356 | | parent: 31:621d83e11f67
1357 | | user: test
1357 | | user: test
1358 | | date: Thu Jan 01 00:00:32 1970 +0000
1358 | | date: Thu Jan 01 00:00:32 1970 +0000
1359 | | summary: (32) expand
1359 | | summary: (32) expand
1360 | |
1360 | |
1361
1361
1362 File + limit + -ra:b, b < tip:
1362 File + limit + -ra:b, b < tip:
1363
1363
1364 $ hg glog -r 'limit(file("a") and 34::32, 1)'
1364 $ hg glog -r 'limit(file("a") and 34::32, 1)'
1365
1365
1366 File + limit + -ra:b, b < tip, (b - a) < limit:
1366 File + limit + -ra:b, b < tip, (b - a) < limit:
1367
1367
1368 $ hg glog -l10 -r33:34 a
1368 $ hg glog -l10 -r33:34 a
1369 o changeset: 34:fea3ac5810e0
1369 o changeset: 34:fea3ac5810e0
1370 | parent: 32:d06dffa21a31
1370 | parent: 32:d06dffa21a31
1371 | user: test
1371 | user: test
1372 | date: Thu Jan 01 00:00:34 1970 +0000
1372 | date: Thu Jan 01 00:00:34 1970 +0000
1373 | summary: (34) head
1373 | summary: (34) head
1374 |
1374 |
1375 | o changeset: 33:68608f5145f9
1375 | o changeset: 33:68608f5145f9
1376 | | parent: 18:1aa84d96232a
1376 | | parent: 18:1aa84d96232a
1377 | | user: test
1377 | | user: test
1378 | | date: Thu Jan 01 00:00:33 1970 +0000
1378 | | date: Thu Jan 01 00:00:33 1970 +0000
1379 | | summary: (33) head
1379 | | summary: (33) head
1380 | |
1380 | |
1381
1381
1382 Do not crash or produce strange graphs if history is buggy
1382 Do not crash or produce strange graphs if history is buggy
1383
1383
1384 $ hg branch branch
1384 $ hg branch branch
1385 marked working directory as branch branch
1385 marked working directory as branch branch
1386 (branches are permanent and global, did you want a bookmark?)
1386 (branches are permanent and global, did you want a bookmark?)
1387 $ commit 36 "buggy merge: identical parents" 35 35
1387 $ commit 36 "buggy merge: identical parents" 35 35
1388 $ hg glog -l5
1388 $ hg glog -l5
1389 @ changeset: 36:08a19a744424
1389 @ changeset: 36:08a19a744424
1390 | branch: branch
1390 | branch: branch
1391 | tag: tip
1391 | tag: tip
1392 | parent: 35:9159c3644c5e
1392 | parent: 35:9159c3644c5e
1393 | parent: 35:9159c3644c5e
1393 | parent: 35:9159c3644c5e
1394 | user: test
1394 | user: test
1395 | date: Thu Jan 01 00:00:36 1970 +0000
1395 | date: Thu Jan 01 00:00:36 1970 +0000
1396 | summary: (36) buggy merge: identical parents
1396 | summary: (36) buggy merge: identical parents
1397 |
1397 |
1398 o changeset: 35:9159c3644c5e
1398 o changeset: 35:9159c3644c5e
1399 | user: test
1399 | user: test
1400 | date: Thu Jan 01 00:00:00 1970 +0000
1400 | date: Thu Jan 01 00:00:00 1970 +0000
1401 | summary: 0
1401 | summary: 0
1402 |
1402 |
1403 o changeset: 34:fea3ac5810e0
1403 o changeset: 34:fea3ac5810e0
1404 | parent: 32:d06dffa21a31
1404 | parent: 32:d06dffa21a31
1405 | user: test
1405 | user: test
1406 | date: Thu Jan 01 00:00:34 1970 +0000
1406 | date: Thu Jan 01 00:00:34 1970 +0000
1407 | summary: (34) head
1407 | summary: (34) head
1408 |
1408 |
1409 | o changeset: 33:68608f5145f9
1409 | o changeset: 33:68608f5145f9
1410 | | parent: 18:1aa84d96232a
1410 | | parent: 18:1aa84d96232a
1411 | | user: test
1411 | | user: test
1412 | | date: Thu Jan 01 00:00:33 1970 +0000
1412 | | date: Thu Jan 01 00:00:33 1970 +0000
1413 | | summary: (33) head
1413 | | summary: (33) head
1414 | |
1414 | |
1415 o | changeset: 32:d06dffa21a31
1415 o | changeset: 32:d06dffa21a31
1416 |\ \ parent: 27:886ed638191b
1416 |\ \ parent: 27:886ed638191b
1417 | | | parent: 31:621d83e11f67
1417 | | | parent: 31:621d83e11f67
1418 | | | user: test
1418 | | | user: test
1419 | | | date: Thu Jan 01 00:00:32 1970 +0000
1419 | | | date: Thu Jan 01 00:00:32 1970 +0000
1420 | | | summary: (32) expand
1420 | | | summary: (32) expand
1421 | | |
1421 | | |
1422
1422
1423 Test log -G options
1423 Test log -G options
1424
1424
1425 $ testlog() {
1425 $ testlog() {
1426 > hg log -G --print-revset "$@"
1426 > hg log -G --print-revset "$@"
1427 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1427 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1428 > | sed 's/.*nodetag/nodetag/' > log.nodes
1428 > | sed 's/.*nodetag/nodetag/' > log.nodes
1429 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1429 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1430 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1430 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1431 > diff -u log.nodes glog.nodes
1431 > diff -u log.nodes glog.nodes
1432 > }
1432 > }
1433
1433
1434 glog always reorders nodes which explains the difference with log
1434 glog always reorders nodes which explains the difference with log
1435
1435
1436 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1436 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1437 ['27', '25', '21', '34', '32', '31']
1437 ['27', '25', '21', '34', '32', '31']
1438 []
1438 []
1439 --- log.nodes * (glob)
1439 --- log.nodes * (glob)
1440 +++ glog.nodes * (glob)
1440 +++ glog.nodes * (glob)
1441 @@ -1,6 +1,6 @@
1441 @@ -1,6 +1,6 @@
1442 -nodetag 27
1442 -nodetag 27
1443 -nodetag 25
1443 -nodetag 25
1444 -nodetag 21
1444 -nodetag 21
1445 nodetag 34
1445 nodetag 34
1446 nodetag 32
1446 nodetag 32
1447 nodetag 31
1447 nodetag 31
1448 +nodetag 27
1448 +nodetag 27
1449 +nodetag 25
1449 +nodetag 25
1450 +nodetag 21
1450 +nodetag 21
1451 [1]
1451 [1]
1452 $ testlog -u test -u not-a-user
1452 $ testlog -u test -u not-a-user
1453 []
1453 []
1454 (group
1454 (group
1455 (group
1455 (group
1456 (or
1456 (or
1457 (func
1457 (func
1458 ('symbol', 'user')
1458 ('symbol', 'user')
1459 ('string', 'test'))
1459 ('string', 'test'))
1460 (func
1460 (func
1461 ('symbol', 'user')
1461 ('symbol', 'user')
1462 ('string', 'not-a-user')))))
1462 ('string', 'not-a-user')))))
1463 $ testlog -b not-a-branch
1463 $ testlog -b not-a-branch
1464 abort: unknown revision 'not-a-branch'!
1464 abort: unknown revision 'not-a-branch'!
1465 abort: unknown revision 'not-a-branch'!
1465 abort: unknown revision 'not-a-branch'!
1466 abort: unknown revision 'not-a-branch'!
1466 abort: unknown revision 'not-a-branch'!
1467 $ testlog -b 35 -b 36 --only-branch branch
1467 $ testlog -b 35 -b 36 --only-branch branch
1468 []
1468 []
1469 (group
1469 (group
1470 (group
1470 (group
1471 (or
1471 (or
1472 (or
1472 (or
1473 (func
1473 (func
1474 ('symbol', 'branch')
1474 ('symbol', 'branch')
1475 ('string', 'default'))
1475 ('string', 'default'))
1476 (func
1476 (func
1477 ('symbol', 'branch')
1477 ('symbol', 'branch')
1478 ('string', 'branch')))
1478 ('string', 'branch')))
1479 (func
1479 (func
1480 ('symbol', 'branch')
1480 ('symbol', 'branch')
1481 ('string', 'branch')))))
1481 ('string', 'branch')))))
1482 $ testlog -k expand -k merge
1482 $ testlog -k expand -k merge
1483 []
1483 []
1484 (group
1484 (group
1485 (group
1485 (group
1486 (or
1486 (or
1487 (func
1487 (func
1488 ('symbol', 'keyword')
1488 ('symbol', 'keyword')
1489 ('string', 'expand'))
1489 ('string', 'expand'))
1490 (func
1490 (func
1491 ('symbol', 'keyword')
1491 ('symbol', 'keyword')
1492 ('string', 'merge')))))
1492 ('string', 'merge')))))
1493 $ testlog --only-merges
1493 $ testlog --only-merges
1494 []
1494 []
1495 (group
1495 (group
1496 (func
1496 (func
1497 ('symbol', 'merge')
1497 ('symbol', 'merge')
1498 None))
1498 None))
1499 $ testlog --no-merges
1499 $ testlog --no-merges
1500 []
1500 []
1501 (group
1501 (group
1502 (not
1502 (not
1503 (func
1503 (func
1504 ('symbol', 'merge')
1504 ('symbol', 'merge')
1505 None)))
1505 None)))
1506 $ testlog --date '2 0 to 4 0'
1506 $ testlog --date '2 0 to 4 0'
1507 []
1507 []
1508 (group
1508 (group
1509 (func
1509 (func
1510 ('symbol', 'date')
1510 ('symbol', 'date')
1511 ('string', '2 0 to 4 0')))
1511 ('string', '2 0 to 4 0')))
1512 $ hg log -G -d 'brace ) in a date'
1512 $ hg log -G -d 'brace ) in a date'
1513 abort: invalid date: 'brace ) in a date'
1513 abort: invalid date: 'brace ) in a date'
1514 [255]
1514 [255]
1515 $ testlog --prune 31 --prune 32
1515 $ testlog --prune 31 --prune 32
1516 []
1516 []
1517 (group
1517 (group
1518 (group
1518 (group
1519 (and
1519 (and
1520 (not
1520 (not
1521 (group
1521 (group
1522 (or
1522 (or
1523 ('string', '31')
1523 ('string', '31')
1524 (func
1524 (func
1525 ('symbol', 'ancestors')
1525 ('symbol', 'ancestors')
1526 ('string', '31')))))
1526 ('string', '31')))))
1527 (not
1527 (not
1528 (group
1528 (group
1529 (or
1529 (or
1530 ('string', '32')
1530 ('string', '32')
1531 (func
1531 (func
1532 ('symbol', 'ancestors')
1532 ('symbol', 'ancestors')
1533 ('string', '32'))))))))
1533 ('string', '32'))))))))
1534
1534
1535 Dedicated repo for --follow and paths filtering. The g is crafted to
1535 Dedicated repo for --follow and paths filtering. The g is crafted to
1536 have 2 filelog topological heads in a linear changeset graph.
1536 have 2 filelog topological heads in a linear changeset graph.
1537
1537
1538 $ cd ..
1538 $ cd ..
1539 $ hg init follow
1539 $ hg init follow
1540 $ cd follow
1540 $ cd follow
1541 $ testlog --follow
1541 $ testlog --follow
1542 []
1542 []
1543 []
1543 []
1544 $ echo a > a
1544 $ echo a > a
1545 $ echo aa > aa
1545 $ echo aa > aa
1546 $ echo f > f
1546 $ echo f > f
1547 $ hg ci -Am "add a" a aa f
1547 $ hg ci -Am "add a" a aa f
1548 $ hg cp a b
1548 $ hg cp a b
1549 $ hg cp f g
1549 $ hg cp f g
1550 $ hg ci -m "copy a b"
1550 $ hg ci -m "copy a b"
1551 $ mkdir dir
1551 $ mkdir dir
1552 $ hg mv b dir
1552 $ hg mv b dir
1553 $ echo g >> g
1553 $ echo g >> g
1554 $ echo f >> f
1554 $ echo f >> f
1555 $ hg ci -m "mv b dir/b"
1555 $ hg ci -m "mv b dir/b"
1556 $ hg mv a b
1556 $ hg mv a b
1557 $ hg cp -f f g
1557 $ hg cp -f f g
1558 $ echo a > d
1558 $ echo a > d
1559 $ hg add d
1559 $ hg add d
1560 $ hg ci -m "mv a b; add d"
1560 $ hg ci -m "mv a b; add d"
1561 $ hg mv dir/b e
1561 $ hg mv dir/b e
1562 $ hg ci -m "mv dir/b e"
1562 $ hg ci -m "mv dir/b e"
1563 $ hg glog --template '({rev}) {desc|firstline}\n'
1563 $ hg glog --template '({rev}) {desc|firstline}\n'
1564 @ (4) mv dir/b e
1564 @ (4) mv dir/b e
1565 |
1565 |
1566 o (3) mv a b; add d
1566 o (3) mv a b; add d
1567 |
1567 |
1568 o (2) mv b dir/b
1568 o (2) mv b dir/b
1569 |
1569 |
1570 o (1) copy a b
1570 o (1) copy a b
1571 |
1571 |
1572 o (0) add a
1572 o (0) add a
1573
1573
1574
1574
1575 $ testlog a
1575 $ testlog a
1576 []
1576 []
1577 (group
1577 (group
1578 (group
1578 (group
1579 (func
1579 (func
1580 ('symbol', 'filelog')
1580 ('symbol', 'filelog')
1581 ('string', 'a'))))
1581 ('string', 'a'))))
1582 $ testlog a b
1582 $ testlog a b
1583 []
1583 []
1584 (group
1584 (group
1585 (group
1585 (group
1586 (or
1586 (or
1587 (func
1587 (func
1588 ('symbol', 'filelog')
1588 ('symbol', 'filelog')
1589 ('string', 'a'))
1589 ('string', 'a'))
1590 (func
1590 (func
1591 ('symbol', 'filelog')
1591 ('symbol', 'filelog')
1592 ('string', 'b')))))
1592 ('string', 'b')))))
1593
1593
1594 Test falling back to slow path for non-existing files
1594 Test falling back to slow path for non-existing files
1595
1595
1596 $ testlog a c
1596 $ testlog a c
1597 []
1597 []
1598 (group
1598 (group
1599 (func
1599 (func
1600 ('symbol', '_matchfiles')
1600 ('symbol', '_matchfiles')
1601 (list
1601 (list
1602 (list
1602 (list
1603 ('string', 'r:')
1603 ('string', 'r:')
1604 ('string', 'p:a'))
1604 ('string', 'p:a'))
1605 ('string', 'p:c'))))
1605 ('string', 'p:c'))))
1606
1606
1607 Test multiple --include/--exclude/paths
1607 Test multiple --include/--exclude/paths
1608
1608
1609 $ testlog --include a --include e --exclude b --exclude e a e
1609 $ testlog --include a --include e --exclude b --exclude e a e
1610 []
1610 []
1611 (group
1611 (group
1612 (func
1612 (func
1613 ('symbol', '_matchfiles')
1613 ('symbol', '_matchfiles')
1614 (list
1614 (list
1615 (list
1615 (list
1616 (list
1616 (list
1617 (list
1617 (list
1618 (list
1618 (list
1619 (list
1619 (list
1620 ('string', 'r:')
1620 ('string', 'r:')
1621 ('string', 'p:a'))
1621 ('string', 'p:a'))
1622 ('string', 'p:e'))
1622 ('string', 'p:e'))
1623 ('string', 'i:a'))
1623 ('string', 'i:a'))
1624 ('string', 'i:e'))
1624 ('string', 'i:e'))
1625 ('string', 'x:b'))
1625 ('string', 'x:b'))
1626 ('string', 'x:e'))))
1626 ('string', 'x:e'))))
1627
1627
1628 Test glob expansion of pats
1628 Test glob expansion of pats
1629
1629
1630 $ expandglobs=`python -c "import mercurial.util; \
1630 $ expandglobs=`python -c "import mercurial.util; \
1631 > print mercurial.util.expandglobs and 'true' or 'false'"`
1631 > print mercurial.util.expandglobs and 'true' or 'false'"`
1632 $ if [ $expandglobs = "true" ]; then
1632 $ if [ $expandglobs = "true" ]; then
1633 > testlog 'a*';
1633 > testlog 'a*';
1634 > else
1634 > else
1635 > testlog a*;
1635 > testlog a*;
1636 > fi;
1636 > fi;
1637 []
1637 []
1638 (group
1638 (group
1639 (group
1639 (group
1640 (func
1640 (func
1641 ('symbol', 'filelog')
1641 ('symbol', 'filelog')
1642 ('string', 'aa'))))
1642 ('string', 'aa'))))
1643
1643
1644 Test --follow on a directory
1644 Test --follow on a directory
1645
1645
1646 $ testlog -f dir
1646 $ testlog -f dir
1647 abort: cannot follow file not in parent revision: "dir"
1647 abort: cannot follow file not in parent revision: "dir"
1648 abort: cannot follow file not in parent revision: "dir"
1648 abort: cannot follow file not in parent revision: "dir"
1649 abort: cannot follow file not in parent revision: "dir"
1649 abort: cannot follow file not in parent revision: "dir"
1650
1650
1651 Test --follow on file not in parent revision
1651 Test --follow on file not in parent revision
1652
1652
1653 $ testlog -f a
1653 $ testlog -f a
1654 abort: cannot follow file not in parent revision: "a"
1654 abort: cannot follow file not in parent revision: "a"
1655 abort: cannot follow file not in parent revision: "a"
1655 abort: cannot follow file not in parent revision: "a"
1656 abort: cannot follow file not in parent revision: "a"
1656 abort: cannot follow file not in parent revision: "a"
1657
1657
1658 Test --follow and patterns
1658 Test --follow and patterns
1659
1659
1660 $ testlog -f 'glob:*'
1660 $ testlog -f 'glob:*'
1661 abort: can only follow copies/renames for explicit filenames
1661 abort: can only follow copies/renames for explicit filenames
1662 abort: can only follow copies/renames for explicit filenames
1662 abort: can only follow copies/renames for explicit filenames
1663 abort: can only follow copies/renames for explicit filenames
1663 abort: can only follow copies/renames for explicit filenames
1664
1664
1665 Test --follow on a single rename
1665 Test --follow on a single rename
1666
1666
1667 $ hg up -q 2
1667 $ hg up -q 2
1668 $ testlog -f a
1668 $ testlog -f a
1669 []
1669 []
1670 (group
1670 (group
1671 (group
1671 (group
1672 (func
1672 (func
1673 ('symbol', 'follow')
1673 ('symbol', 'follow')
1674 ('string', 'a'))))
1674 ('string', 'a'))))
1675
1675
1676 Test --follow and multiple renames
1676 Test --follow and multiple renames
1677
1677
1678 $ hg up -q tip
1678 $ hg up -q tip
1679 $ testlog -f e
1679 $ testlog -f e
1680 []
1680 []
1681 (group
1681 (group
1682 (group
1682 (group
1683 (func
1683 (func
1684 ('symbol', 'follow')
1684 ('symbol', 'follow')
1685 ('string', 'e'))))
1685 ('string', 'e'))))
1686
1686
1687 Test --follow and multiple filelog heads
1687 Test --follow and multiple filelog heads
1688
1688
1689 $ hg up -q 2
1689 $ hg up -q 2
1690 $ testlog -f g
1690 $ testlog -f g
1691 []
1691 []
1692 (group
1692 (group
1693 (group
1693 (group
1694 (func
1694 (func
1695 ('symbol', 'follow')
1695 ('symbol', 'follow')
1696 ('string', 'g'))))
1696 ('string', 'g'))))
1697 $ cat log.nodes
1697 $ cat log.nodes
1698 nodetag 2
1698 nodetag 2
1699 nodetag 1
1699 nodetag 1
1700 nodetag 0
1700 nodetag 0
1701 $ hg up -q tip
1701 $ hg up -q tip
1702 $ testlog -f g
1702 $ testlog -f g
1703 []
1703 []
1704 (group
1704 (group
1705 (group
1705 (group
1706 (func
1706 (func
1707 ('symbol', 'follow')
1707 ('symbol', 'follow')
1708 ('string', 'g'))))
1708 ('string', 'g'))))
1709 $ cat log.nodes
1709 $ cat log.nodes
1710 nodetag 3
1710 nodetag 3
1711 nodetag 2
1711 nodetag 2
1712 nodetag 0
1712 nodetag 0
1713
1713
1714 Test --follow and multiple files
1714 Test --follow and multiple files
1715
1715
1716 $ testlog -f g e
1716 $ testlog -f g e
1717 []
1717 []
1718 (group
1718 (group
1719 (group
1719 (group
1720 (or
1720 (or
1721 (func
1721 (func
1722 ('symbol', 'follow')
1722 ('symbol', 'follow')
1723 ('string', 'g'))
1723 ('string', 'g'))
1724 (func
1724 (func
1725 ('symbol', 'follow')
1725 ('symbol', 'follow')
1726 ('string', 'e')))))
1726 ('string', 'e')))))
1727 $ cat log.nodes
1727 $ cat log.nodes
1728 nodetag 4
1728 nodetag 4
1729 nodetag 3
1729 nodetag 3
1730 nodetag 2
1730 nodetag 2
1731 nodetag 1
1731 nodetag 1
1732 nodetag 0
1732 nodetag 0
1733
1733
1734 Test --follow-first
1734 Test --follow-first
1735
1735
1736 $ hg up -q 3
1736 $ hg up -q 3
1737 $ echo ee > e
1737 $ echo ee > e
1738 $ hg ci -Am "add another e" e
1738 $ hg ci -Am "add another e" e
1739 created new head
1739 created new head
1740 $ hg merge --tool internal:other 4
1740 $ hg merge --tool internal:other 4
1741 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1741 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1742 (branch merge, don't forget to commit)
1742 (branch merge, don't forget to commit)
1743 $ echo merge > e
1743 $ echo merge > e
1744 $ hg ci -m "merge 5 and 4"
1744 $ hg ci -m "merge 5 and 4"
1745 $ testlog --follow-first
1745 $ testlog --follow-first
1746 []
1746 []
1747 (group
1747 (group
1748 (func
1748 (func
1749 ('symbol', '_followfirst')
1749 ('symbol', '_firstancestors')
1750 None))
1750 ('symbol', '6')))
1751
1751
1752 Cannot compare with log --follow-first FILE as it never worked
1752 Cannot compare with log --follow-first FILE as it never worked
1753
1753
1754 $ hg log -G --print-revset --follow-first e
1754 $ hg log -G --print-revset --follow-first e
1755 []
1755 []
1756 (group
1756 (group
1757 (group
1757 (group
1758 (func
1758 (func
1759 ('symbol', '_followfirst')
1759 ('symbol', '_followfirst')
1760 ('string', 'e'))))
1760 ('string', 'e'))))
1761 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1761 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1762 @ 6 merge 5 and 4
1762 @ 6 merge 5 and 4
1763 |\
1763 |\
1764 o | 5 add another e
1764 o | 5 add another e
1765 | |
1765 | |
1766
1766
1767 Test --copies
1767 Test --copies
1768
1768
1769 $ hg log -G --copies --template "{rev} {desc|firstline} \
1769 $ hg log -G --copies --template "{rev} {desc|firstline} \
1770 > copies: {file_copies_switch}\n"
1770 > copies: {file_copies_switch}\n"
1771 @ 6 merge 5 and 4 copies:
1771 @ 6 merge 5 and 4 copies:
1772 |\
1772 |\
1773 | o 5 add another e copies:
1773 | o 5 add another e copies:
1774 | |
1774 | |
1775 o | 4 mv dir/b e copies: e (dir/b)
1775 o | 4 mv dir/b e copies: e (dir/b)
1776 |/
1776 |/
1777 o 3 mv a b; add d copies: b (a)g (f)
1777 o 3 mv a b; add d copies: b (a)g (f)
1778 |
1778 |
1779 o 2 mv b dir/b copies: dir/b (b)
1779 o 2 mv b dir/b copies: dir/b (b)
1780 |
1780 |
1781 o 1 copy a b copies: b (a)g (f)
1781 o 1 copy a b copies: b (a)g (f)
1782 |
1782 |
1783 o 0 add a copies:
1783 o 0 add a copies:
1784
1784
1785 Test "set:..." and parent revision
1785 Test "set:..." and parent revision
1786
1786
1787 $ hg up -q 4
1787 $ hg up -q 4
1788 $ testlog "set:copied()"
1788 $ testlog "set:copied()"
1789 []
1789 []
1790 (group
1790 (group
1791 (func
1791 (func
1792 ('symbol', '_matchfiles')
1792 ('symbol', '_matchfiles')
1793 (list
1793 (list
1794 ('string', 'r:')
1794 ('string', 'r:')
1795 ('string', 'p:set:copied()'))))
1795 ('string', 'p:set:copied()'))))
1796 $ testlog --include "set:copied()"
1796 $ testlog --include "set:copied()"
1797 []
1797 []
1798 (group
1798 (group
1799 (func
1799 (func
1800 ('symbol', '_matchfiles')
1800 ('symbol', '_matchfiles')
1801 (list
1801 (list
1802 ('string', 'r:')
1802 ('string', 'r:')
1803 ('string', 'i:set:copied()'))))
1803 ('string', 'i:set:copied()'))))
1804 $ testlog -r "sort(file('set:copied()'), -rev)"
1804 $ testlog -r "sort(file('set:copied()'), -rev)"
1805 ["sort(file('set:copied()'), -rev)"]
1805 ["sort(file('set:copied()'), -rev)"]
1806 []
1806 []
1807
1807
1808 Test --removed
1808 Test --removed
1809
1809
1810 $ testlog --removed
1810 $ testlog --removed
1811 []
1811 []
1812 []
1812 []
1813 $ testlog --removed a
1813 $ testlog --removed a
1814 []
1814 []
1815 (group
1815 (group
1816 (func
1816 (func
1817 ('symbol', '_matchfiles')
1817 ('symbol', '_matchfiles')
1818 (list
1818 (list
1819 ('string', 'r:')
1819 ('string', 'r:')
1820 ('string', 'p:a'))))
1820 ('string', 'p:a'))))
1821 $ testlog --removed --follow a
1821 $ testlog --removed --follow a
1822 abort: can only follow copies/renames for explicit filenames
1822 abort: can only follow copies/renames for explicit filenames
1823 abort: can only follow copies/renames for explicit filenames
1823 abort: can only follow copies/renames for explicit filenames
1824 abort: can only follow copies/renames for explicit filenames
1824 abort: can only follow copies/renames for explicit filenames
1825
1825
1826 Test --patch and --stat with --follow and --follow-first
1826 Test --patch and --stat with --follow and --follow-first
1827
1827
1828 $ hg up -q 3
1828 $ hg up -q 3
1829 $ hg log -G --git --patch b
1829 $ hg log -G --git --patch b
1830 o changeset: 1:216d4c92cf98
1830 o changeset: 1:216d4c92cf98
1831 | user: test
1831 | user: test
1832 | date: Thu Jan 01 00:00:00 1970 +0000
1832 | date: Thu Jan 01 00:00:00 1970 +0000
1833 | summary: copy a b
1833 | summary: copy a b
1834 |
1834 |
1835 | diff --git a/a b/b
1835 | diff --git a/a b/b
1836 | copy from a
1836 | copy from a
1837 | copy to b
1837 | copy to b
1838 |
1838 |
1839
1839
1840 $ hg log -G --git --stat b
1840 $ hg log -G --git --stat b
1841 o changeset: 1:216d4c92cf98
1841 o changeset: 1:216d4c92cf98
1842 | user: test
1842 | user: test
1843 | date: Thu Jan 01 00:00:00 1970 +0000
1843 | date: Thu Jan 01 00:00:00 1970 +0000
1844 | summary: copy a b
1844 | summary: copy a b
1845 |
1845 |
1846 | a | 0
1846 | a | 0
1847 | 1 files changed, 0 insertions(+), 0 deletions(-)
1847 | 1 files changed, 0 insertions(+), 0 deletions(-)
1848 |
1848 |
1849
1849
1850 $ hg log -G --git --patch --follow b
1850 $ hg log -G --git --patch --follow b
1851 o changeset: 1:216d4c92cf98
1851 o changeset: 1:216d4c92cf98
1852 | user: test
1852 | user: test
1853 | date: Thu Jan 01 00:00:00 1970 +0000
1853 | date: Thu Jan 01 00:00:00 1970 +0000
1854 | summary: copy a b
1854 | summary: copy a b
1855 |
1855 |
1856 | diff --git a/a b/b
1856 | diff --git a/a b/b
1857 | copy from a
1857 | copy from a
1858 | copy to b
1858 | copy to b
1859 |
1859 |
1860 o changeset: 0:f8035bb17114
1860 o changeset: 0:f8035bb17114
1861 user: test
1861 user: test
1862 date: Thu Jan 01 00:00:00 1970 +0000
1862 date: Thu Jan 01 00:00:00 1970 +0000
1863 summary: add a
1863 summary: add a
1864
1864
1865 diff --git a/a b/a
1865 diff --git a/a b/a
1866 new file mode 100644
1866 new file mode 100644
1867 --- /dev/null
1867 --- /dev/null
1868 +++ b/a
1868 +++ b/a
1869 @@ -0,0 +1,1 @@
1869 @@ -0,0 +1,1 @@
1870 +a
1870 +a
1871
1871
1872
1872
1873 $ hg log -G --git --stat --follow b
1873 $ hg log -G --git --stat --follow b
1874 o changeset: 1:216d4c92cf98
1874 o changeset: 1:216d4c92cf98
1875 | user: test
1875 | user: test
1876 | date: Thu Jan 01 00:00:00 1970 +0000
1876 | date: Thu Jan 01 00:00:00 1970 +0000
1877 | summary: copy a b
1877 | summary: copy a b
1878 |
1878 |
1879 | a | 0
1879 | a | 0
1880 | 1 files changed, 0 insertions(+), 0 deletions(-)
1880 | 1 files changed, 0 insertions(+), 0 deletions(-)
1881 |
1881 |
1882 o changeset: 0:f8035bb17114
1882 o changeset: 0:f8035bb17114
1883 user: test
1883 user: test
1884 date: Thu Jan 01 00:00:00 1970 +0000
1884 date: Thu Jan 01 00:00:00 1970 +0000
1885 summary: add a
1885 summary: add a
1886
1886
1887 a | 1 +
1887 a | 1 +
1888 1 files changed, 1 insertions(+), 0 deletions(-)
1888 1 files changed, 1 insertions(+), 0 deletions(-)
1889
1889
1890
1890
1891 $ hg up -q 6
1891 $ hg up -q 6
1892 $ hg log -G --git --patch --follow-first e
1892 $ hg log -G --git --patch --follow-first e
1893 @ changeset: 6:fc281d8ff18d
1893 @ changeset: 6:fc281d8ff18d
1894 |\ tag: tip
1894 |\ tag: tip
1895 | | parent: 5:99b31f1c2782
1895 | | parent: 5:99b31f1c2782
1896 | | parent: 4:17d952250a9d
1896 | | parent: 4:17d952250a9d
1897 | | user: test
1897 | | user: test
1898 | | date: Thu Jan 01 00:00:00 1970 +0000
1898 | | date: Thu Jan 01 00:00:00 1970 +0000
1899 | | summary: merge 5 and 4
1899 | | summary: merge 5 and 4
1900 | |
1900 | |
1901 | | diff --git a/e b/e
1901 | | diff --git a/e b/e
1902 | | --- a/e
1902 | | --- a/e
1903 | | +++ b/e
1903 | | +++ b/e
1904 | | @@ -1,1 +1,1 @@
1904 | | @@ -1,1 +1,1 @@
1905 | | -ee
1905 | | -ee
1906 | | +merge
1906 | | +merge
1907 | |
1907 | |
1908 o | changeset: 5:99b31f1c2782
1908 o | changeset: 5:99b31f1c2782
1909 | | parent: 3:5918b8d165d1
1909 | | parent: 3:5918b8d165d1
1910 | | user: test
1910 | | user: test
1911 | | date: Thu Jan 01 00:00:00 1970 +0000
1911 | | date: Thu Jan 01 00:00:00 1970 +0000
1912 | | summary: add another e
1912 | | summary: add another e
1913 | |
1913 | |
1914 | | diff --git a/e b/e
1914 | | diff --git a/e b/e
1915 | | new file mode 100644
1915 | | new file mode 100644
1916 | | --- /dev/null
1916 | | --- /dev/null
1917 | | +++ b/e
1917 | | +++ b/e
1918 | | @@ -0,0 +1,1 @@
1918 | | @@ -0,0 +1,1 @@
1919 | | +ee
1919 | | +ee
1920 | |
1920 | |
1921
1921
1922 Test old-style --rev
1922 Test old-style --rev
1923
1923
1924 $ hg tag 'foo-bar'
1924 $ hg tag 'foo-bar'
1925 $ testlog -r 'foo-bar'
1925 $ testlog -r 'foo-bar'
1926 ['foo-bar']
1926 ['foo-bar']
1927 []
1927 []
1928
1928
1929 Test --follow and forward --rev
1929 Test --follow and forward --rev
1930
1930
1931 $ hg up -q 6
1931 $ hg up -q 6
1932 $ echo g > g
1932 $ echo g > g
1933 $ hg ci -Am 'add g' g
1933 $ hg ci -Am 'add g' g
1934 created new head
1934 created new head
1935 $ hg up -q 2
1935 $ hg up -q 2
1936 $ hg log -G --template "{rev} {desc|firstline}\n"
1936 $ hg log -G --template "{rev} {desc|firstline}\n"
1937 o 8 add g
1937 o 8 add g
1938 |
1938 |
1939 | o 7 Added tag foo-bar for changeset fc281d8ff18d
1939 | o 7 Added tag foo-bar for changeset fc281d8ff18d
1940 |/
1940 |/
1941 o 6 merge 5 and 4
1941 o 6 merge 5 and 4
1942 |\
1942 |\
1943 | o 5 add another e
1943 | o 5 add another e
1944 | |
1944 | |
1945 o | 4 mv dir/b e
1945 o | 4 mv dir/b e
1946 |/
1946 |/
1947 o 3 mv a b; add d
1947 o 3 mv a b; add d
1948 |
1948 |
1949 @ 2 mv b dir/b
1949 @ 2 mv b dir/b
1950 |
1950 |
1951 o 1 copy a b
1951 o 1 copy a b
1952 |
1952 |
1953 o 0 add a
1953 o 0 add a
1954
1954
1955 $ testlog --follow -r6 -r8 -r5 -r7 -r4
1955 $ testlog --follow -r6 -r8 -r5 -r7 -r4
1956 ['6', '8', '5', '7', '4']
1956 ['6', '8', '5', '7', '4']
1957 (group
1957 (group
1958 (func
1958 (func
1959 ('symbol', 'descendants')
1959 ('symbol', 'descendants')
1960 ('symbol', '6')))
1960 ('symbol', '6')))
1961 --- log.nodes * (glob)
1961 --- log.nodes * (glob)
1962 +++ glog.nodes * (glob)
1962 +++ glog.nodes * (glob)
1963 @@ -1,3 +1,3 @@
1963 @@ -1,3 +1,3 @@
1964 -nodetag 6
1964 -nodetag 6
1965 nodetag 8
1965 nodetag 8
1966 nodetag 7
1966 nodetag 7
1967 +nodetag 6
1967 +nodetag 6
1968 [1]
1968 [1]
1969
1969
1970 Test --follow-first and forward --rev
1971
1972 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
1973 ['6', '8', '5', '7', '4']
1974 (group
1975 (func
1976 ('symbol', '_firstdescendants')
1977 ('symbol', '6')))
1978 --- log.nodes * (glob)
1979 +++ glog.nodes * (glob)
1980 @@ -1,3 +1,3 @@
1981 -nodetag 6
1982 nodetag 8
1983 nodetag 7
1984 +nodetag 6
1985 [1]
1986
1970 Test --follow and backward --rev
1987 Test --follow and backward --rev
1971
1988
1972 $ testlog --follow -r6 -r5 -r7 -r8 -r4
1989 $ testlog --follow -r6 -r5 -r7 -r8 -r4
1973 ['6', '5', '7', '8', '4']
1990 ['6', '5', '7', '8', '4']
1974 (group
1991 (group
1975 (func
1992 (func
1976 ('symbol', 'ancestors')
1993 ('symbol', 'ancestors')
1977 ('symbol', '6')))
1994 ('symbol', '6')))
1978
1995
1996 Test --follow-first and backward --rev
1997
1998 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
1999 ['6', '5', '7', '8', '4']
2000 (group
2001 (func
2002 ('symbol', '_firstancestors')
2003 ('symbol', '6')))
General Comments 0
You need to be logged in to leave comments. Login now