##// END OF EJS Templates
stringutil: promote smartset.prettyformat() to utility function...
Yuya Nishihara -
r38280:f3033692 default
parent child Browse files
Show More
@@ -1,3138 +1,3137 b''
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2016 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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import difflib
12 import difflib
13 import errno
13 import errno
14 import operator
14 import operator
15 import os
15 import os
16 import random
16 import random
17 import re
17 import re
18 import socket
18 import socket
19 import ssl
19 import ssl
20 import stat
20 import stat
21 import string
21 import string
22 import subprocess
22 import subprocess
23 import sys
23 import sys
24 import time
24 import time
25
25
26 from .i18n import _
26 from .i18n import _
27 from .node import (
27 from .node import (
28 bin,
28 bin,
29 hex,
29 hex,
30 nullhex,
30 nullhex,
31 nullid,
31 nullid,
32 nullrev,
32 nullrev,
33 short,
33 short,
34 )
34 )
35 from .thirdparty import (
35 from .thirdparty import (
36 cbor,
36 cbor,
37 )
37 )
38 from . import (
38 from . import (
39 bundle2,
39 bundle2,
40 changegroup,
40 changegroup,
41 cmdutil,
41 cmdutil,
42 color,
42 color,
43 context,
43 context,
44 dagparser,
44 dagparser,
45 dagutil,
45 dagutil,
46 encoding,
46 encoding,
47 error,
47 error,
48 exchange,
48 exchange,
49 extensions,
49 extensions,
50 filemerge,
50 filemerge,
51 fileset,
51 fileset,
52 formatter,
52 formatter,
53 hg,
53 hg,
54 httppeer,
54 httppeer,
55 localrepo,
55 localrepo,
56 lock as lockmod,
56 lock as lockmod,
57 logcmdutil,
57 logcmdutil,
58 merge as mergemod,
58 merge as mergemod,
59 obsolete,
59 obsolete,
60 obsutil,
60 obsutil,
61 phases,
61 phases,
62 policy,
62 policy,
63 pvec,
63 pvec,
64 pycompat,
64 pycompat,
65 registrar,
65 registrar,
66 repair,
66 repair,
67 revlog,
67 revlog,
68 revset,
68 revset,
69 revsetlang,
69 revsetlang,
70 scmutil,
70 scmutil,
71 setdiscovery,
71 setdiscovery,
72 simplemerge,
72 simplemerge,
73 smartset,
74 sshpeer,
73 sshpeer,
75 sslutil,
74 sslutil,
76 streamclone,
75 streamclone,
77 templater,
76 templater,
78 treediscovery,
77 treediscovery,
79 upgrade,
78 upgrade,
80 url as urlmod,
79 url as urlmod,
81 util,
80 util,
82 vfs as vfsmod,
81 vfs as vfsmod,
83 wireprotoframing,
82 wireprotoframing,
84 wireprotoserver,
83 wireprotoserver,
85 wireprotov2peer,
84 wireprotov2peer,
86 )
85 )
87 from .utils import (
86 from .utils import (
88 dateutil,
87 dateutil,
89 procutil,
88 procutil,
90 stringutil,
89 stringutil,
91 )
90 )
92
91
93 release = lockmod.release
92 release = lockmod.release
94
93
95 command = registrar.command()
94 command = registrar.command()
96
95
97 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
96 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
98 def debugancestor(ui, repo, *args):
97 def debugancestor(ui, repo, *args):
99 """find the ancestor revision of two revisions in a given index"""
98 """find the ancestor revision of two revisions in a given index"""
100 if len(args) == 3:
99 if len(args) == 3:
101 index, rev1, rev2 = args
100 index, rev1, rev2 = args
102 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
101 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
103 lookup = r.lookup
102 lookup = r.lookup
104 elif len(args) == 2:
103 elif len(args) == 2:
105 if not repo:
104 if not repo:
106 raise error.Abort(_('there is no Mercurial repository here '
105 raise error.Abort(_('there is no Mercurial repository here '
107 '(.hg not found)'))
106 '(.hg not found)'))
108 rev1, rev2 = args
107 rev1, rev2 = args
109 r = repo.changelog
108 r = repo.changelog
110 lookup = repo.lookup
109 lookup = repo.lookup
111 else:
110 else:
112 raise error.Abort(_('either two or three arguments required'))
111 raise error.Abort(_('either two or three arguments required'))
113 a = r.ancestor(lookup(rev1), lookup(rev2))
112 a = r.ancestor(lookup(rev1), lookup(rev2))
114 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
113 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
115
114
116 @command('debugapplystreamclonebundle', [], 'FILE')
115 @command('debugapplystreamclonebundle', [], 'FILE')
117 def debugapplystreamclonebundle(ui, repo, fname):
116 def debugapplystreamclonebundle(ui, repo, fname):
118 """apply a stream clone bundle file"""
117 """apply a stream clone bundle file"""
119 f = hg.openpath(ui, fname)
118 f = hg.openpath(ui, fname)
120 gen = exchange.readbundle(ui, f, fname)
119 gen = exchange.readbundle(ui, f, fname)
121 gen.apply(repo)
120 gen.apply(repo)
122
121
123 @command('debugbuilddag',
122 @command('debugbuilddag',
124 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
123 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
125 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
124 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
126 ('n', 'new-file', None, _('add new file at each rev'))],
125 ('n', 'new-file', None, _('add new file at each rev'))],
127 _('[OPTION]... [TEXT]'))
126 _('[OPTION]... [TEXT]'))
128 def debugbuilddag(ui, repo, text=None,
127 def debugbuilddag(ui, repo, text=None,
129 mergeable_file=False,
128 mergeable_file=False,
130 overwritten_file=False,
129 overwritten_file=False,
131 new_file=False):
130 new_file=False):
132 """builds a repo with a given DAG from scratch in the current empty repo
131 """builds a repo with a given DAG from scratch in the current empty repo
133
132
134 The description of the DAG is read from stdin if not given on the
133 The description of the DAG is read from stdin if not given on the
135 command line.
134 command line.
136
135
137 Elements:
136 Elements:
138
137
139 - "+n" is a linear run of n nodes based on the current default parent
138 - "+n" is a linear run of n nodes based on the current default parent
140 - "." is a single node based on the current default parent
139 - "." is a single node based on the current default parent
141 - "$" resets the default parent to null (implied at the start);
140 - "$" resets the default parent to null (implied at the start);
142 otherwise the default parent is always the last node created
141 otherwise the default parent is always the last node created
143 - "<p" sets the default parent to the backref p
142 - "<p" sets the default parent to the backref p
144 - "*p" is a fork at parent p, which is a backref
143 - "*p" is a fork at parent p, which is a backref
145 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
144 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
146 - "/p2" is a merge of the preceding node and p2
145 - "/p2" is a merge of the preceding node and p2
147 - ":tag" defines a local tag for the preceding node
146 - ":tag" defines a local tag for the preceding node
148 - "@branch" sets the named branch for subsequent nodes
147 - "@branch" sets the named branch for subsequent nodes
149 - "#...\\n" is a comment up to the end of the line
148 - "#...\\n" is a comment up to the end of the line
150
149
151 Whitespace between the above elements is ignored.
150 Whitespace between the above elements is ignored.
152
151
153 A backref is either
152 A backref is either
154
153
155 - a number n, which references the node curr-n, where curr is the current
154 - a number n, which references the node curr-n, where curr is the current
156 node, or
155 node, or
157 - the name of a local tag you placed earlier using ":tag", or
156 - the name of a local tag you placed earlier using ":tag", or
158 - empty to denote the default parent.
157 - empty to denote the default parent.
159
158
160 All string valued-elements are either strictly alphanumeric, or must
159 All string valued-elements are either strictly alphanumeric, or must
161 be enclosed in double quotes ("..."), with "\\" as escape character.
160 be enclosed in double quotes ("..."), with "\\" as escape character.
162 """
161 """
163
162
164 if text is None:
163 if text is None:
165 ui.status(_("reading DAG from stdin\n"))
164 ui.status(_("reading DAG from stdin\n"))
166 text = ui.fin.read()
165 text = ui.fin.read()
167
166
168 cl = repo.changelog
167 cl = repo.changelog
169 if len(cl) > 0:
168 if len(cl) > 0:
170 raise error.Abort(_('repository is not empty'))
169 raise error.Abort(_('repository is not empty'))
171
170
172 # determine number of revs in DAG
171 # determine number of revs in DAG
173 total = 0
172 total = 0
174 for type, data in dagparser.parsedag(text):
173 for type, data in dagparser.parsedag(text):
175 if type == 'n':
174 if type == 'n':
176 total += 1
175 total += 1
177
176
178 if mergeable_file:
177 if mergeable_file:
179 linesperrev = 2
178 linesperrev = 2
180 # make a file with k lines per rev
179 # make a file with k lines per rev
181 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
180 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
182 initialmergedlines.append("")
181 initialmergedlines.append("")
183
182
184 tags = []
183 tags = []
185
184
186 wlock = lock = tr = None
185 wlock = lock = tr = None
187 try:
186 try:
188 wlock = repo.wlock()
187 wlock = repo.wlock()
189 lock = repo.lock()
188 lock = repo.lock()
190 tr = repo.transaction("builddag")
189 tr = repo.transaction("builddag")
191
190
192 at = -1
191 at = -1
193 atbranch = 'default'
192 atbranch = 'default'
194 nodeids = []
193 nodeids = []
195 id = 0
194 id = 0
196 ui.progress(_('building'), id, unit=_('revisions'), total=total)
195 ui.progress(_('building'), id, unit=_('revisions'), total=total)
197 for type, data in dagparser.parsedag(text):
196 for type, data in dagparser.parsedag(text):
198 if type == 'n':
197 if type == 'n':
199 ui.note(('node %s\n' % pycompat.bytestr(data)))
198 ui.note(('node %s\n' % pycompat.bytestr(data)))
200 id, ps = data
199 id, ps = data
201
200
202 files = []
201 files = []
203 filecontent = {}
202 filecontent = {}
204
203
205 p2 = None
204 p2 = None
206 if mergeable_file:
205 if mergeable_file:
207 fn = "mf"
206 fn = "mf"
208 p1 = repo[ps[0]]
207 p1 = repo[ps[0]]
209 if len(ps) > 1:
208 if len(ps) > 1:
210 p2 = repo[ps[1]]
209 p2 = repo[ps[1]]
211 pa = p1.ancestor(p2)
210 pa = p1.ancestor(p2)
212 base, local, other = [x[fn].data() for x in (pa, p1,
211 base, local, other = [x[fn].data() for x in (pa, p1,
213 p2)]
212 p2)]
214 m3 = simplemerge.Merge3Text(base, local, other)
213 m3 = simplemerge.Merge3Text(base, local, other)
215 ml = [l.strip() for l in m3.merge_lines()]
214 ml = [l.strip() for l in m3.merge_lines()]
216 ml.append("")
215 ml.append("")
217 elif at > 0:
216 elif at > 0:
218 ml = p1[fn].data().split("\n")
217 ml = p1[fn].data().split("\n")
219 else:
218 else:
220 ml = initialmergedlines
219 ml = initialmergedlines
221 ml[id * linesperrev] += " r%i" % id
220 ml[id * linesperrev] += " r%i" % id
222 mergedtext = "\n".join(ml)
221 mergedtext = "\n".join(ml)
223 files.append(fn)
222 files.append(fn)
224 filecontent[fn] = mergedtext
223 filecontent[fn] = mergedtext
225
224
226 if overwritten_file:
225 if overwritten_file:
227 fn = "of"
226 fn = "of"
228 files.append(fn)
227 files.append(fn)
229 filecontent[fn] = "r%i\n" % id
228 filecontent[fn] = "r%i\n" % id
230
229
231 if new_file:
230 if new_file:
232 fn = "nf%i" % id
231 fn = "nf%i" % id
233 files.append(fn)
232 files.append(fn)
234 filecontent[fn] = "r%i\n" % id
233 filecontent[fn] = "r%i\n" % id
235 if len(ps) > 1:
234 if len(ps) > 1:
236 if not p2:
235 if not p2:
237 p2 = repo[ps[1]]
236 p2 = repo[ps[1]]
238 for fn in p2:
237 for fn in p2:
239 if fn.startswith("nf"):
238 if fn.startswith("nf"):
240 files.append(fn)
239 files.append(fn)
241 filecontent[fn] = p2[fn].data()
240 filecontent[fn] = p2[fn].data()
242
241
243 def fctxfn(repo, cx, path):
242 def fctxfn(repo, cx, path):
244 if path in filecontent:
243 if path in filecontent:
245 return context.memfilectx(repo, cx, path,
244 return context.memfilectx(repo, cx, path,
246 filecontent[path])
245 filecontent[path])
247 return None
246 return None
248
247
249 if len(ps) == 0 or ps[0] < 0:
248 if len(ps) == 0 or ps[0] < 0:
250 pars = [None, None]
249 pars = [None, None]
251 elif len(ps) == 1:
250 elif len(ps) == 1:
252 pars = [nodeids[ps[0]], None]
251 pars = [nodeids[ps[0]], None]
253 else:
252 else:
254 pars = [nodeids[p] for p in ps]
253 pars = [nodeids[p] for p in ps]
255 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
254 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
256 date=(id, 0),
255 date=(id, 0),
257 user="debugbuilddag",
256 user="debugbuilddag",
258 extra={'branch': atbranch})
257 extra={'branch': atbranch})
259 nodeid = repo.commitctx(cx)
258 nodeid = repo.commitctx(cx)
260 nodeids.append(nodeid)
259 nodeids.append(nodeid)
261 at = id
260 at = id
262 elif type == 'l':
261 elif type == 'l':
263 id, name = data
262 id, name = data
264 ui.note(('tag %s\n' % name))
263 ui.note(('tag %s\n' % name))
265 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
264 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
266 elif type == 'a':
265 elif type == 'a':
267 ui.note(('branch %s\n' % data))
266 ui.note(('branch %s\n' % data))
268 atbranch = data
267 atbranch = data
269 ui.progress(_('building'), id, unit=_('revisions'), total=total)
268 ui.progress(_('building'), id, unit=_('revisions'), total=total)
270 tr.close()
269 tr.close()
271
270
272 if tags:
271 if tags:
273 repo.vfs.write("localtags", "".join(tags))
272 repo.vfs.write("localtags", "".join(tags))
274 finally:
273 finally:
275 ui.progress(_('building'), None)
274 ui.progress(_('building'), None)
276 release(tr, lock, wlock)
275 release(tr, lock, wlock)
277
276
278 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
277 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
279 indent_string = ' ' * indent
278 indent_string = ' ' * indent
280 if all:
279 if all:
281 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
280 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
282 % indent_string)
281 % indent_string)
283
282
284 def showchunks(named):
283 def showchunks(named):
285 ui.write("\n%s%s\n" % (indent_string, named))
284 ui.write("\n%s%s\n" % (indent_string, named))
286 for deltadata in gen.deltaiter():
285 for deltadata in gen.deltaiter():
287 node, p1, p2, cs, deltabase, delta, flags = deltadata
286 node, p1, p2, cs, deltabase, delta, flags = deltadata
288 ui.write("%s%s %s %s %s %s %d\n" %
287 ui.write("%s%s %s %s %s %s %d\n" %
289 (indent_string, hex(node), hex(p1), hex(p2),
288 (indent_string, hex(node), hex(p1), hex(p2),
290 hex(cs), hex(deltabase), len(delta)))
289 hex(cs), hex(deltabase), len(delta)))
291
290
292 chunkdata = gen.changelogheader()
291 chunkdata = gen.changelogheader()
293 showchunks("changelog")
292 showchunks("changelog")
294 chunkdata = gen.manifestheader()
293 chunkdata = gen.manifestheader()
295 showchunks("manifest")
294 showchunks("manifest")
296 for chunkdata in iter(gen.filelogheader, {}):
295 for chunkdata in iter(gen.filelogheader, {}):
297 fname = chunkdata['filename']
296 fname = chunkdata['filename']
298 showchunks(fname)
297 showchunks(fname)
299 else:
298 else:
300 if isinstance(gen, bundle2.unbundle20):
299 if isinstance(gen, bundle2.unbundle20):
301 raise error.Abort(_('use debugbundle2 for this file'))
300 raise error.Abort(_('use debugbundle2 for this file'))
302 chunkdata = gen.changelogheader()
301 chunkdata = gen.changelogheader()
303 for deltadata in gen.deltaiter():
302 for deltadata in gen.deltaiter():
304 node, p1, p2, cs, deltabase, delta, flags = deltadata
303 node, p1, p2, cs, deltabase, delta, flags = deltadata
305 ui.write("%s%s\n" % (indent_string, hex(node)))
304 ui.write("%s%s\n" % (indent_string, hex(node)))
306
305
307 def _debugobsmarkers(ui, part, indent=0, **opts):
306 def _debugobsmarkers(ui, part, indent=0, **opts):
308 """display version and markers contained in 'data'"""
307 """display version and markers contained in 'data'"""
309 opts = pycompat.byteskwargs(opts)
308 opts = pycompat.byteskwargs(opts)
310 data = part.read()
309 data = part.read()
311 indent_string = ' ' * indent
310 indent_string = ' ' * indent
312 try:
311 try:
313 version, markers = obsolete._readmarkers(data)
312 version, markers = obsolete._readmarkers(data)
314 except error.UnknownVersion as exc:
313 except error.UnknownVersion as exc:
315 msg = "%sunsupported version: %s (%d bytes)\n"
314 msg = "%sunsupported version: %s (%d bytes)\n"
316 msg %= indent_string, exc.version, len(data)
315 msg %= indent_string, exc.version, len(data)
317 ui.write(msg)
316 ui.write(msg)
318 else:
317 else:
319 msg = "%sversion: %d (%d bytes)\n"
318 msg = "%sversion: %d (%d bytes)\n"
320 msg %= indent_string, version, len(data)
319 msg %= indent_string, version, len(data)
321 ui.write(msg)
320 ui.write(msg)
322 fm = ui.formatter('debugobsolete', opts)
321 fm = ui.formatter('debugobsolete', opts)
323 for rawmarker in sorted(markers):
322 for rawmarker in sorted(markers):
324 m = obsutil.marker(None, rawmarker)
323 m = obsutil.marker(None, rawmarker)
325 fm.startitem()
324 fm.startitem()
326 fm.plain(indent_string)
325 fm.plain(indent_string)
327 cmdutil.showmarker(fm, m)
326 cmdutil.showmarker(fm, m)
328 fm.end()
327 fm.end()
329
328
330 def _debugphaseheads(ui, data, indent=0):
329 def _debugphaseheads(ui, data, indent=0):
331 """display version and markers contained in 'data'"""
330 """display version and markers contained in 'data'"""
332 indent_string = ' ' * indent
331 indent_string = ' ' * indent
333 headsbyphase = phases.binarydecode(data)
332 headsbyphase = phases.binarydecode(data)
334 for phase in phases.allphases:
333 for phase in phases.allphases:
335 for head in headsbyphase[phase]:
334 for head in headsbyphase[phase]:
336 ui.write(indent_string)
335 ui.write(indent_string)
337 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
336 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
338
337
339 def _quasirepr(thing):
338 def _quasirepr(thing):
340 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
339 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
341 return '{%s}' % (
340 return '{%s}' % (
342 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
341 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
343 return pycompat.bytestr(repr(thing))
342 return pycompat.bytestr(repr(thing))
344
343
345 def _debugbundle2(ui, gen, all=None, **opts):
344 def _debugbundle2(ui, gen, all=None, **opts):
346 """lists the contents of a bundle2"""
345 """lists the contents of a bundle2"""
347 if not isinstance(gen, bundle2.unbundle20):
346 if not isinstance(gen, bundle2.unbundle20):
348 raise error.Abort(_('not a bundle2 file'))
347 raise error.Abort(_('not a bundle2 file'))
349 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
348 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
350 parttypes = opts.get(r'part_type', [])
349 parttypes = opts.get(r'part_type', [])
351 for part in gen.iterparts():
350 for part in gen.iterparts():
352 if parttypes and part.type not in parttypes:
351 if parttypes and part.type not in parttypes:
353 continue
352 continue
354 msg = '%s -- %s (mandatory: %r)\n'
353 msg = '%s -- %s (mandatory: %r)\n'
355 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
354 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
356 if part.type == 'changegroup':
355 if part.type == 'changegroup':
357 version = part.params.get('version', '01')
356 version = part.params.get('version', '01')
358 cg = changegroup.getunbundler(version, part, 'UN')
357 cg = changegroup.getunbundler(version, part, 'UN')
359 if not ui.quiet:
358 if not ui.quiet:
360 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
359 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
361 if part.type == 'obsmarkers':
360 if part.type == 'obsmarkers':
362 if not ui.quiet:
361 if not ui.quiet:
363 _debugobsmarkers(ui, part, indent=4, **opts)
362 _debugobsmarkers(ui, part, indent=4, **opts)
364 if part.type == 'phase-heads':
363 if part.type == 'phase-heads':
365 if not ui.quiet:
364 if not ui.quiet:
366 _debugphaseheads(ui, part, indent=4)
365 _debugphaseheads(ui, part, indent=4)
367
366
368 @command('debugbundle',
367 @command('debugbundle',
369 [('a', 'all', None, _('show all details')),
368 [('a', 'all', None, _('show all details')),
370 ('', 'part-type', [], _('show only the named part type')),
369 ('', 'part-type', [], _('show only the named part type')),
371 ('', 'spec', None, _('print the bundlespec of the bundle'))],
370 ('', 'spec', None, _('print the bundlespec of the bundle'))],
372 _('FILE'),
371 _('FILE'),
373 norepo=True)
372 norepo=True)
374 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
373 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
375 """lists the contents of a bundle"""
374 """lists the contents of a bundle"""
376 with hg.openpath(ui, bundlepath) as f:
375 with hg.openpath(ui, bundlepath) as f:
377 if spec:
376 if spec:
378 spec = exchange.getbundlespec(ui, f)
377 spec = exchange.getbundlespec(ui, f)
379 ui.write('%s\n' % spec)
378 ui.write('%s\n' % spec)
380 return
379 return
381
380
382 gen = exchange.readbundle(ui, f, bundlepath)
381 gen = exchange.readbundle(ui, f, bundlepath)
383 if isinstance(gen, bundle2.unbundle20):
382 if isinstance(gen, bundle2.unbundle20):
384 return _debugbundle2(ui, gen, all=all, **opts)
383 return _debugbundle2(ui, gen, all=all, **opts)
385 _debugchangegroup(ui, gen, all=all, **opts)
384 _debugchangegroup(ui, gen, all=all, **opts)
386
385
387 @command('debugcapabilities',
386 @command('debugcapabilities',
388 [], _('PATH'),
387 [], _('PATH'),
389 norepo=True)
388 norepo=True)
390 def debugcapabilities(ui, path, **opts):
389 def debugcapabilities(ui, path, **opts):
391 """lists the capabilities of a remote peer"""
390 """lists the capabilities of a remote peer"""
392 opts = pycompat.byteskwargs(opts)
391 opts = pycompat.byteskwargs(opts)
393 peer = hg.peer(ui, opts, path)
392 peer = hg.peer(ui, opts, path)
394 caps = peer.capabilities()
393 caps = peer.capabilities()
395 ui.write(('Main capabilities:\n'))
394 ui.write(('Main capabilities:\n'))
396 for c in sorted(caps):
395 for c in sorted(caps):
397 ui.write((' %s\n') % c)
396 ui.write((' %s\n') % c)
398 b2caps = bundle2.bundle2caps(peer)
397 b2caps = bundle2.bundle2caps(peer)
399 if b2caps:
398 if b2caps:
400 ui.write(('Bundle2 capabilities:\n'))
399 ui.write(('Bundle2 capabilities:\n'))
401 for key, values in sorted(b2caps.iteritems()):
400 for key, values in sorted(b2caps.iteritems()):
402 ui.write((' %s\n') % key)
401 ui.write((' %s\n') % key)
403 for v in values:
402 for v in values:
404 ui.write((' %s\n') % v)
403 ui.write((' %s\n') % v)
405
404
406 @command('debugcheckstate', [], '')
405 @command('debugcheckstate', [], '')
407 def debugcheckstate(ui, repo):
406 def debugcheckstate(ui, repo):
408 """validate the correctness of the current dirstate"""
407 """validate the correctness of the current dirstate"""
409 parent1, parent2 = repo.dirstate.parents()
408 parent1, parent2 = repo.dirstate.parents()
410 m1 = repo[parent1].manifest()
409 m1 = repo[parent1].manifest()
411 m2 = repo[parent2].manifest()
410 m2 = repo[parent2].manifest()
412 errors = 0
411 errors = 0
413 for f in repo.dirstate:
412 for f in repo.dirstate:
414 state = repo.dirstate[f]
413 state = repo.dirstate[f]
415 if state in "nr" and f not in m1:
414 if state in "nr" and f not in m1:
416 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
417 errors += 1
416 errors += 1
418 if state in "a" and f in m1:
417 if state in "a" and f in m1:
419 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
420 errors += 1
419 errors += 1
421 if state in "m" and f not in m1 and f not in m2:
420 if state in "m" and f not in m1 and f not in m2:
422 ui.warn(_("%s in state %s, but not in either manifest\n") %
421 ui.warn(_("%s in state %s, but not in either manifest\n") %
423 (f, state))
422 (f, state))
424 errors += 1
423 errors += 1
425 for f in m1:
424 for f in m1:
426 state = repo.dirstate[f]
425 state = repo.dirstate[f]
427 if state not in "nrm":
426 if state not in "nrm":
428 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
429 errors += 1
428 errors += 1
430 if errors:
429 if errors:
431 error = _(".hg/dirstate inconsistent with current parent's manifest")
430 error = _(".hg/dirstate inconsistent with current parent's manifest")
432 raise error.Abort(error)
431 raise error.Abort(error)
433
432
434 @command('debugcolor',
433 @command('debugcolor',
435 [('', 'style', None, _('show all configured styles'))],
434 [('', 'style', None, _('show all configured styles'))],
436 'hg debugcolor')
435 'hg debugcolor')
437 def debugcolor(ui, repo, **opts):
436 def debugcolor(ui, repo, **opts):
438 """show available color, effects or style"""
437 """show available color, effects or style"""
439 ui.write(('color mode: %s\n') % ui._colormode)
438 ui.write(('color mode: %s\n') % ui._colormode)
440 if opts.get(r'style'):
439 if opts.get(r'style'):
441 return _debugdisplaystyle(ui)
440 return _debugdisplaystyle(ui)
442 else:
441 else:
443 return _debugdisplaycolor(ui)
442 return _debugdisplaycolor(ui)
444
443
445 def _debugdisplaycolor(ui):
444 def _debugdisplaycolor(ui):
446 ui = ui.copy()
445 ui = ui.copy()
447 ui._styles.clear()
446 ui._styles.clear()
448 for effect in color._activeeffects(ui).keys():
447 for effect in color._activeeffects(ui).keys():
449 ui._styles[effect] = effect
448 ui._styles[effect] = effect
450 if ui._terminfoparams:
449 if ui._terminfoparams:
451 for k, v in ui.configitems('color'):
450 for k, v in ui.configitems('color'):
452 if k.startswith('color.'):
451 if k.startswith('color.'):
453 ui._styles[k] = k[6:]
452 ui._styles[k] = k[6:]
454 elif k.startswith('terminfo.'):
453 elif k.startswith('terminfo.'):
455 ui._styles[k] = k[9:]
454 ui._styles[k] = k[9:]
456 ui.write(_('available colors:\n'))
455 ui.write(_('available colors:\n'))
457 # sort label with a '_' after the other to group '_background' entry.
456 # sort label with a '_' after the other to group '_background' entry.
458 items = sorted(ui._styles.items(),
457 items = sorted(ui._styles.items(),
459 key=lambda i: ('_' in i[0], i[0], i[1]))
458 key=lambda i: ('_' in i[0], i[0], i[1]))
460 for colorname, label in items:
459 for colorname, label in items:
461 ui.write(('%s\n') % colorname, label=label)
460 ui.write(('%s\n') % colorname, label=label)
462
461
463 def _debugdisplaystyle(ui):
462 def _debugdisplaystyle(ui):
464 ui.write(_('available style:\n'))
463 ui.write(_('available style:\n'))
465 if not ui._styles:
464 if not ui._styles:
466 return
465 return
467 width = max(len(s) for s in ui._styles)
466 width = max(len(s) for s in ui._styles)
468 for label, effects in sorted(ui._styles.items()):
467 for label, effects in sorted(ui._styles.items()):
469 ui.write('%s' % label, label=label)
468 ui.write('%s' % label, label=label)
470 if effects:
469 if effects:
471 # 50
470 # 50
472 ui.write(': ')
471 ui.write(': ')
473 ui.write(' ' * (max(0, width - len(label))))
472 ui.write(' ' * (max(0, width - len(label))))
474 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
473 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
475 ui.write('\n')
474 ui.write('\n')
476
475
477 @command('debugcreatestreamclonebundle', [], 'FILE')
476 @command('debugcreatestreamclonebundle', [], 'FILE')
478 def debugcreatestreamclonebundle(ui, repo, fname):
477 def debugcreatestreamclonebundle(ui, repo, fname):
479 """create a stream clone bundle file
478 """create a stream clone bundle file
480
479
481 Stream bundles are special bundles that are essentially archives of
480 Stream bundles are special bundles that are essentially archives of
482 revlog files. They are commonly used for cloning very quickly.
481 revlog files. They are commonly used for cloning very quickly.
483 """
482 """
484 # TODO we may want to turn this into an abort when this functionality
483 # TODO we may want to turn this into an abort when this functionality
485 # is moved into `hg bundle`.
484 # is moved into `hg bundle`.
486 if phases.hassecret(repo):
485 if phases.hassecret(repo):
487 ui.warn(_('(warning: stream clone bundle will contain secret '
486 ui.warn(_('(warning: stream clone bundle will contain secret '
488 'revisions)\n'))
487 'revisions)\n'))
489
488
490 requirements, gen = streamclone.generatebundlev1(repo)
489 requirements, gen = streamclone.generatebundlev1(repo)
491 changegroup.writechunks(ui, gen, fname)
490 changegroup.writechunks(ui, gen, fname)
492
491
493 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
492 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
494
493
495 @command('debugdag',
494 @command('debugdag',
496 [('t', 'tags', None, _('use tags as labels')),
495 [('t', 'tags', None, _('use tags as labels')),
497 ('b', 'branches', None, _('annotate with branch names')),
496 ('b', 'branches', None, _('annotate with branch names')),
498 ('', 'dots', None, _('use dots for runs')),
497 ('', 'dots', None, _('use dots for runs')),
499 ('s', 'spaces', None, _('separate elements by spaces'))],
498 ('s', 'spaces', None, _('separate elements by spaces'))],
500 _('[OPTION]... [FILE [REV]...]'),
499 _('[OPTION]... [FILE [REV]...]'),
501 optionalrepo=True)
500 optionalrepo=True)
502 def debugdag(ui, repo, file_=None, *revs, **opts):
501 def debugdag(ui, repo, file_=None, *revs, **opts):
503 """format the changelog or an index DAG as a concise textual description
502 """format the changelog or an index DAG as a concise textual description
504
503
505 If you pass a revlog index, the revlog's DAG is emitted. If you list
504 If you pass a revlog index, the revlog's DAG is emitted. If you list
506 revision numbers, they get labeled in the output as rN.
505 revision numbers, they get labeled in the output as rN.
507
506
508 Otherwise, the changelog DAG of the current repo is emitted.
507 Otherwise, the changelog DAG of the current repo is emitted.
509 """
508 """
510 spaces = opts.get(r'spaces')
509 spaces = opts.get(r'spaces')
511 dots = opts.get(r'dots')
510 dots = opts.get(r'dots')
512 if file_:
511 if file_:
513 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
512 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
514 file_)
513 file_)
515 revs = set((int(r) for r in revs))
514 revs = set((int(r) for r in revs))
516 def events():
515 def events():
517 for r in rlog:
516 for r in rlog:
518 yield 'n', (r, list(p for p in rlog.parentrevs(r)
517 yield 'n', (r, list(p for p in rlog.parentrevs(r)
519 if p != -1))
518 if p != -1))
520 if r in revs:
519 if r in revs:
521 yield 'l', (r, "r%i" % r)
520 yield 'l', (r, "r%i" % r)
522 elif repo:
521 elif repo:
523 cl = repo.changelog
522 cl = repo.changelog
524 tags = opts.get(r'tags')
523 tags = opts.get(r'tags')
525 branches = opts.get(r'branches')
524 branches = opts.get(r'branches')
526 if tags:
525 if tags:
527 labels = {}
526 labels = {}
528 for l, n in repo.tags().items():
527 for l, n in repo.tags().items():
529 labels.setdefault(cl.rev(n), []).append(l)
528 labels.setdefault(cl.rev(n), []).append(l)
530 def events():
529 def events():
531 b = "default"
530 b = "default"
532 for r in cl:
531 for r in cl:
533 if branches:
532 if branches:
534 newb = cl.read(cl.node(r))[5]['branch']
533 newb = cl.read(cl.node(r))[5]['branch']
535 if newb != b:
534 if newb != b:
536 yield 'a', newb
535 yield 'a', newb
537 b = newb
536 b = newb
538 yield 'n', (r, list(p for p in cl.parentrevs(r)
537 yield 'n', (r, list(p for p in cl.parentrevs(r)
539 if p != -1))
538 if p != -1))
540 if tags:
539 if tags:
541 ls = labels.get(r)
540 ls = labels.get(r)
542 if ls:
541 if ls:
543 for l in ls:
542 for l in ls:
544 yield 'l', (r, l)
543 yield 'l', (r, l)
545 else:
544 else:
546 raise error.Abort(_('need repo for changelog dag'))
545 raise error.Abort(_('need repo for changelog dag'))
547
546
548 for line in dagparser.dagtextlines(events(),
547 for line in dagparser.dagtextlines(events(),
549 addspaces=spaces,
548 addspaces=spaces,
550 wraplabels=True,
549 wraplabels=True,
551 wrapannotations=True,
550 wrapannotations=True,
552 wrapnonlinear=dots,
551 wrapnonlinear=dots,
553 usedots=dots,
552 usedots=dots,
554 maxlinewidth=70):
553 maxlinewidth=70):
555 ui.write(line)
554 ui.write(line)
556 ui.write("\n")
555 ui.write("\n")
557
556
558 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
557 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
559 def debugdata(ui, repo, file_, rev=None, **opts):
558 def debugdata(ui, repo, file_, rev=None, **opts):
560 """dump the contents of a data file revision"""
559 """dump the contents of a data file revision"""
561 opts = pycompat.byteskwargs(opts)
560 opts = pycompat.byteskwargs(opts)
562 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
561 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
563 if rev is not None:
562 if rev is not None:
564 raise error.CommandError('debugdata', _('invalid arguments'))
563 raise error.CommandError('debugdata', _('invalid arguments'))
565 file_, rev = None, file_
564 file_, rev = None, file_
566 elif rev is None:
565 elif rev is None:
567 raise error.CommandError('debugdata', _('invalid arguments'))
566 raise error.CommandError('debugdata', _('invalid arguments'))
568 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
567 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
569 try:
568 try:
570 ui.write(r.revision(r.lookup(rev), raw=True))
569 ui.write(r.revision(r.lookup(rev), raw=True))
571 except KeyError:
570 except KeyError:
572 raise error.Abort(_('invalid revision identifier %s') % rev)
571 raise error.Abort(_('invalid revision identifier %s') % rev)
573
572
574 @command('debugdate',
573 @command('debugdate',
575 [('e', 'extended', None, _('try extended date formats'))],
574 [('e', 'extended', None, _('try extended date formats'))],
576 _('[-e] DATE [RANGE]'),
575 _('[-e] DATE [RANGE]'),
577 norepo=True, optionalrepo=True)
576 norepo=True, optionalrepo=True)
578 def debugdate(ui, date, range=None, **opts):
577 def debugdate(ui, date, range=None, **opts):
579 """parse and display a date"""
578 """parse and display a date"""
580 if opts[r"extended"]:
579 if opts[r"extended"]:
581 d = dateutil.parsedate(date, util.extendeddateformats)
580 d = dateutil.parsedate(date, util.extendeddateformats)
582 else:
581 else:
583 d = dateutil.parsedate(date)
582 d = dateutil.parsedate(date)
584 ui.write(("internal: %d %d\n") % d)
583 ui.write(("internal: %d %d\n") % d)
585 ui.write(("standard: %s\n") % dateutil.datestr(d))
584 ui.write(("standard: %s\n") % dateutil.datestr(d))
586 if range:
585 if range:
587 m = dateutil.matchdate(range)
586 m = dateutil.matchdate(range)
588 ui.write(("match: %s\n") % m(d[0]))
587 ui.write(("match: %s\n") % m(d[0]))
589
588
590 @command('debugdeltachain',
589 @command('debugdeltachain',
591 cmdutil.debugrevlogopts + cmdutil.formatteropts,
590 cmdutil.debugrevlogopts + cmdutil.formatteropts,
592 _('-c|-m|FILE'),
591 _('-c|-m|FILE'),
593 optionalrepo=True)
592 optionalrepo=True)
594 def debugdeltachain(ui, repo, file_=None, **opts):
593 def debugdeltachain(ui, repo, file_=None, **opts):
595 """dump information about delta chains in a revlog
594 """dump information about delta chains in a revlog
596
595
597 Output can be templatized. Available template keywords are:
596 Output can be templatized. Available template keywords are:
598
597
599 :``rev``: revision number
598 :``rev``: revision number
600 :``chainid``: delta chain identifier (numbered by unique base)
599 :``chainid``: delta chain identifier (numbered by unique base)
601 :``chainlen``: delta chain length to this revision
600 :``chainlen``: delta chain length to this revision
602 :``prevrev``: previous revision in delta chain
601 :``prevrev``: previous revision in delta chain
603 :``deltatype``: role of delta / how it was computed
602 :``deltatype``: role of delta / how it was computed
604 :``compsize``: compressed size of revision
603 :``compsize``: compressed size of revision
605 :``uncompsize``: uncompressed size of revision
604 :``uncompsize``: uncompressed size of revision
606 :``chainsize``: total size of compressed revisions in chain
605 :``chainsize``: total size of compressed revisions in chain
607 :``chainratio``: total chain size divided by uncompressed revision size
606 :``chainratio``: total chain size divided by uncompressed revision size
608 (new delta chains typically start at ratio 2.00)
607 (new delta chains typically start at ratio 2.00)
609 :``lindist``: linear distance from base revision in delta chain to end
608 :``lindist``: linear distance from base revision in delta chain to end
610 of this revision
609 of this revision
611 :``extradist``: total size of revisions not part of this delta chain from
610 :``extradist``: total size of revisions not part of this delta chain from
612 base of delta chain to end of this revision; a measurement
611 base of delta chain to end of this revision; a measurement
613 of how much extra data we need to read/seek across to read
612 of how much extra data we need to read/seek across to read
614 the delta chain for this revision
613 the delta chain for this revision
615 :``extraratio``: extradist divided by chainsize; another representation of
614 :``extraratio``: extradist divided by chainsize; another representation of
616 how much unrelated data is needed to load this delta chain
615 how much unrelated data is needed to load this delta chain
617
616
618 If the repository is configured to use the sparse read, additional keywords
617 If the repository is configured to use the sparse read, additional keywords
619 are available:
618 are available:
620
619
621 :``readsize``: total size of data read from the disk for a revision
620 :``readsize``: total size of data read from the disk for a revision
622 (sum of the sizes of all the blocks)
621 (sum of the sizes of all the blocks)
623 :``largestblock``: size of the largest block of data read from the disk
622 :``largestblock``: size of the largest block of data read from the disk
624 :``readdensity``: density of useful bytes in the data read from the disk
623 :``readdensity``: density of useful bytes in the data read from the disk
625 :``srchunks``: in how many data hunks the whole revision would be read
624 :``srchunks``: in how many data hunks the whole revision would be read
626
625
627 The sparse read can be enabled with experimental.sparse-read = True
626 The sparse read can be enabled with experimental.sparse-read = True
628 """
627 """
629 opts = pycompat.byteskwargs(opts)
628 opts = pycompat.byteskwargs(opts)
630 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
629 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
631 index = r.index
630 index = r.index
632 start = r.start
631 start = r.start
633 length = r.length
632 length = r.length
634 generaldelta = r.version & revlog.FLAG_GENERALDELTA
633 generaldelta = r.version & revlog.FLAG_GENERALDELTA
635 withsparseread = getattr(r, '_withsparseread', False)
634 withsparseread = getattr(r, '_withsparseread', False)
636
635
637 def revinfo(rev):
636 def revinfo(rev):
638 e = index[rev]
637 e = index[rev]
639 compsize = e[1]
638 compsize = e[1]
640 uncompsize = e[2]
639 uncompsize = e[2]
641 chainsize = 0
640 chainsize = 0
642
641
643 if generaldelta:
642 if generaldelta:
644 if e[3] == e[5]:
643 if e[3] == e[5]:
645 deltatype = 'p1'
644 deltatype = 'p1'
646 elif e[3] == e[6]:
645 elif e[3] == e[6]:
647 deltatype = 'p2'
646 deltatype = 'p2'
648 elif e[3] == rev - 1:
647 elif e[3] == rev - 1:
649 deltatype = 'prev'
648 deltatype = 'prev'
650 elif e[3] == rev:
649 elif e[3] == rev:
651 deltatype = 'base'
650 deltatype = 'base'
652 else:
651 else:
653 deltatype = 'other'
652 deltatype = 'other'
654 else:
653 else:
655 if e[3] == rev:
654 if e[3] == rev:
656 deltatype = 'base'
655 deltatype = 'base'
657 else:
656 else:
658 deltatype = 'prev'
657 deltatype = 'prev'
659
658
660 chain = r._deltachain(rev)[0]
659 chain = r._deltachain(rev)[0]
661 for iterrev in chain:
660 for iterrev in chain:
662 e = index[iterrev]
661 e = index[iterrev]
663 chainsize += e[1]
662 chainsize += e[1]
664
663
665 return compsize, uncompsize, deltatype, chain, chainsize
664 return compsize, uncompsize, deltatype, chain, chainsize
666
665
667 fm = ui.formatter('debugdeltachain', opts)
666 fm = ui.formatter('debugdeltachain', opts)
668
667
669 fm.plain(' rev chain# chainlen prev delta '
668 fm.plain(' rev chain# chainlen prev delta '
670 'size rawsize chainsize ratio lindist extradist '
669 'size rawsize chainsize ratio lindist extradist '
671 'extraratio')
670 'extraratio')
672 if withsparseread:
671 if withsparseread:
673 fm.plain(' readsize largestblk rddensity srchunks')
672 fm.plain(' readsize largestblk rddensity srchunks')
674 fm.plain('\n')
673 fm.plain('\n')
675
674
676 chainbases = {}
675 chainbases = {}
677 for rev in r:
676 for rev in r:
678 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
677 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
679 chainbase = chain[0]
678 chainbase = chain[0]
680 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
679 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
681 basestart = start(chainbase)
680 basestart = start(chainbase)
682 revstart = start(rev)
681 revstart = start(rev)
683 lineardist = revstart + comp - basestart
682 lineardist = revstart + comp - basestart
684 extradist = lineardist - chainsize
683 extradist = lineardist - chainsize
685 try:
684 try:
686 prevrev = chain[-2]
685 prevrev = chain[-2]
687 except IndexError:
686 except IndexError:
688 prevrev = -1
687 prevrev = -1
689
688
690 chainratio = float(chainsize) / float(uncomp)
689 chainratio = float(chainsize) / float(uncomp)
691 extraratio = float(extradist) / float(chainsize)
690 extraratio = float(extradist) / float(chainsize)
692
691
693 fm.startitem()
692 fm.startitem()
694 fm.write('rev chainid chainlen prevrev deltatype compsize '
693 fm.write('rev chainid chainlen prevrev deltatype compsize '
695 'uncompsize chainsize chainratio lindist extradist '
694 'uncompsize chainsize chainratio lindist extradist '
696 'extraratio',
695 'extraratio',
697 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
696 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
698 rev, chainid, len(chain), prevrev, deltatype, comp,
697 rev, chainid, len(chain), prevrev, deltatype, comp,
699 uncomp, chainsize, chainratio, lineardist, extradist,
698 uncomp, chainsize, chainratio, lineardist, extradist,
700 extraratio,
699 extraratio,
701 rev=rev, chainid=chainid, chainlen=len(chain),
700 rev=rev, chainid=chainid, chainlen=len(chain),
702 prevrev=prevrev, deltatype=deltatype, compsize=comp,
701 prevrev=prevrev, deltatype=deltatype, compsize=comp,
703 uncompsize=uncomp, chainsize=chainsize,
702 uncompsize=uncomp, chainsize=chainsize,
704 chainratio=chainratio, lindist=lineardist,
703 chainratio=chainratio, lindist=lineardist,
705 extradist=extradist, extraratio=extraratio)
704 extradist=extradist, extraratio=extraratio)
706 if withsparseread:
705 if withsparseread:
707 readsize = 0
706 readsize = 0
708 largestblock = 0
707 largestblock = 0
709 srchunks = 0
708 srchunks = 0
710
709
711 for revschunk in revlog._slicechunk(r, chain):
710 for revschunk in revlog._slicechunk(r, chain):
712 srchunks += 1
711 srchunks += 1
713 blkend = start(revschunk[-1]) + length(revschunk[-1])
712 blkend = start(revschunk[-1]) + length(revschunk[-1])
714 blksize = blkend - start(revschunk[0])
713 blksize = blkend - start(revschunk[0])
715
714
716 readsize += blksize
715 readsize += blksize
717 if largestblock < blksize:
716 if largestblock < blksize:
718 largestblock = blksize
717 largestblock = blksize
719
718
720 readdensity = float(chainsize) / float(readsize)
719 readdensity = float(chainsize) / float(readsize)
721
720
722 fm.write('readsize largestblock readdensity srchunks',
721 fm.write('readsize largestblock readdensity srchunks',
723 ' %10d %10d %9.5f %8d',
722 ' %10d %10d %9.5f %8d',
724 readsize, largestblock, readdensity, srchunks,
723 readsize, largestblock, readdensity, srchunks,
725 readsize=readsize, largestblock=largestblock,
724 readsize=readsize, largestblock=largestblock,
726 readdensity=readdensity, srchunks=srchunks)
725 readdensity=readdensity, srchunks=srchunks)
727
726
728 fm.plain('\n')
727 fm.plain('\n')
729
728
730 fm.end()
729 fm.end()
731
730
732 @command('debugdirstate|debugstate',
731 @command('debugdirstate|debugstate',
733 [('', 'nodates', None, _('do not display the saved mtime')),
732 [('', 'nodates', None, _('do not display the saved mtime')),
734 ('', 'datesort', None, _('sort by saved mtime'))],
733 ('', 'datesort', None, _('sort by saved mtime'))],
735 _('[OPTION]...'))
734 _('[OPTION]...'))
736 def debugstate(ui, repo, **opts):
735 def debugstate(ui, repo, **opts):
737 """show the contents of the current dirstate"""
736 """show the contents of the current dirstate"""
738
737
739 nodates = opts.get(r'nodates')
738 nodates = opts.get(r'nodates')
740 datesort = opts.get(r'datesort')
739 datesort = opts.get(r'datesort')
741
740
742 timestr = ""
741 timestr = ""
743 if datesort:
742 if datesort:
744 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
743 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
745 else:
744 else:
746 keyfunc = None # sort by filename
745 keyfunc = None # sort by filename
747 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
746 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
748 if ent[3] == -1:
747 if ent[3] == -1:
749 timestr = 'unset '
748 timestr = 'unset '
750 elif nodates:
749 elif nodates:
751 timestr = 'set '
750 timestr = 'set '
752 else:
751 else:
753 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
752 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
754 time.localtime(ent[3]))
753 time.localtime(ent[3]))
755 timestr = encoding.strtolocal(timestr)
754 timestr = encoding.strtolocal(timestr)
756 if ent[1] & 0o20000:
755 if ent[1] & 0o20000:
757 mode = 'lnk'
756 mode = 'lnk'
758 else:
757 else:
759 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
758 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
760 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
759 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
761 for f in repo.dirstate.copies():
760 for f in repo.dirstate.copies():
762 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
761 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
763
762
764 @command('debugdiscovery',
763 @command('debugdiscovery',
765 [('', 'old', None, _('use old-style discovery')),
764 [('', 'old', None, _('use old-style discovery')),
766 ('', 'nonheads', None,
765 ('', 'nonheads', None,
767 _('use old-style discovery with non-heads included')),
766 _('use old-style discovery with non-heads included')),
768 ('', 'rev', [], 'restrict discovery to this set of revs'),
767 ('', 'rev', [], 'restrict discovery to this set of revs'),
769 ] + cmdutil.remoteopts,
768 ] + cmdutil.remoteopts,
770 _('[--rev REV] [OTHER]'))
769 _('[--rev REV] [OTHER]'))
771 def debugdiscovery(ui, repo, remoteurl="default", **opts):
770 def debugdiscovery(ui, repo, remoteurl="default", **opts):
772 """runs the changeset discovery protocol in isolation"""
771 """runs the changeset discovery protocol in isolation"""
773 opts = pycompat.byteskwargs(opts)
772 opts = pycompat.byteskwargs(opts)
774 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
773 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
775 remote = hg.peer(repo, opts, remoteurl)
774 remote = hg.peer(repo, opts, remoteurl)
776 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
775 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
777
776
778 # make sure tests are repeatable
777 # make sure tests are repeatable
779 random.seed(12323)
778 random.seed(12323)
780
779
781 def doit(pushedrevs, remoteheads, remote=remote):
780 def doit(pushedrevs, remoteheads, remote=remote):
782 if opts.get('old'):
781 if opts.get('old'):
783 if not util.safehasattr(remote, 'branches'):
782 if not util.safehasattr(remote, 'branches'):
784 # enable in-client legacy support
783 # enable in-client legacy support
785 remote = localrepo.locallegacypeer(remote.local())
784 remote = localrepo.locallegacypeer(remote.local())
786 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
785 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
787 force=True)
786 force=True)
788 common = set(common)
787 common = set(common)
789 if not opts.get('nonheads'):
788 if not opts.get('nonheads'):
790 ui.write(("unpruned common: %s\n") %
789 ui.write(("unpruned common: %s\n") %
791 " ".join(sorted(short(n) for n in common)))
790 " ".join(sorted(short(n) for n in common)))
792 dag = dagutil.revlogdag(repo.changelog)
791 dag = dagutil.revlogdag(repo.changelog)
793 all = dag.ancestorset(dag.internalizeall(common))
792 all = dag.ancestorset(dag.internalizeall(common))
794 common = dag.externalizeall(dag.headsetofconnecteds(all))
793 common = dag.externalizeall(dag.headsetofconnecteds(all))
795 else:
794 else:
796 nodes = None
795 nodes = None
797 if pushedrevs:
796 if pushedrevs:
798 revs = scmutil.revrange(repo, pushedrevs)
797 revs = scmutil.revrange(repo, pushedrevs)
799 nodes = [repo[r].node() for r in revs]
798 nodes = [repo[r].node() for r in revs]
800 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
799 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
801 ancestorsof=nodes)
800 ancestorsof=nodes)
802 common = set(common)
801 common = set(common)
803 rheads = set(hds)
802 rheads = set(hds)
804 lheads = set(repo.heads())
803 lheads = set(repo.heads())
805 ui.write(("common heads: %s\n") %
804 ui.write(("common heads: %s\n") %
806 " ".join(sorted(short(n) for n in common)))
805 " ".join(sorted(short(n) for n in common)))
807 if lheads <= common:
806 if lheads <= common:
808 ui.write(("local is subset\n"))
807 ui.write(("local is subset\n"))
809 elif rheads <= common:
808 elif rheads <= common:
810 ui.write(("remote is subset\n"))
809 ui.write(("remote is subset\n"))
811
810
812 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
811 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
813 localrevs = opts['rev']
812 localrevs = opts['rev']
814 doit(localrevs, remoterevs)
813 doit(localrevs, remoterevs)
815
814
816 _chunksize = 4 << 10
815 _chunksize = 4 << 10
817
816
818 @command('debugdownload',
817 @command('debugdownload',
819 [
818 [
820 ('o', 'output', '', _('path')),
819 ('o', 'output', '', _('path')),
821 ],
820 ],
822 optionalrepo=True)
821 optionalrepo=True)
823 def debugdownload(ui, repo, url, output=None, **opts):
822 def debugdownload(ui, repo, url, output=None, **opts):
824 """download a resource using Mercurial logic and config
823 """download a resource using Mercurial logic and config
825 """
824 """
826 fh = urlmod.open(ui, url, output)
825 fh = urlmod.open(ui, url, output)
827
826
828 dest = ui
827 dest = ui
829 if output:
828 if output:
830 dest = open(output, "wb", _chunksize)
829 dest = open(output, "wb", _chunksize)
831 try:
830 try:
832 data = fh.read(_chunksize)
831 data = fh.read(_chunksize)
833 while data:
832 while data:
834 dest.write(data)
833 dest.write(data)
835 data = fh.read(_chunksize)
834 data = fh.read(_chunksize)
836 finally:
835 finally:
837 if output:
836 if output:
838 dest.close()
837 dest.close()
839
838
840 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
839 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
841 def debugextensions(ui, repo, **opts):
840 def debugextensions(ui, repo, **opts):
842 '''show information about active extensions'''
841 '''show information about active extensions'''
843 opts = pycompat.byteskwargs(opts)
842 opts = pycompat.byteskwargs(opts)
844 exts = extensions.extensions(ui)
843 exts = extensions.extensions(ui)
845 hgver = util.version()
844 hgver = util.version()
846 fm = ui.formatter('debugextensions', opts)
845 fm = ui.formatter('debugextensions', opts)
847 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
846 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
848 isinternal = extensions.ismoduleinternal(extmod)
847 isinternal = extensions.ismoduleinternal(extmod)
849 extsource = pycompat.fsencode(extmod.__file__)
848 extsource = pycompat.fsencode(extmod.__file__)
850 if isinternal:
849 if isinternal:
851 exttestedwith = [] # never expose magic string to users
850 exttestedwith = [] # never expose magic string to users
852 else:
851 else:
853 exttestedwith = getattr(extmod, 'testedwith', '').split()
852 exttestedwith = getattr(extmod, 'testedwith', '').split()
854 extbuglink = getattr(extmod, 'buglink', None)
853 extbuglink = getattr(extmod, 'buglink', None)
855
854
856 fm.startitem()
855 fm.startitem()
857
856
858 if ui.quiet or ui.verbose:
857 if ui.quiet or ui.verbose:
859 fm.write('name', '%s\n', extname)
858 fm.write('name', '%s\n', extname)
860 else:
859 else:
861 fm.write('name', '%s', extname)
860 fm.write('name', '%s', extname)
862 if isinternal or hgver in exttestedwith:
861 if isinternal or hgver in exttestedwith:
863 fm.plain('\n')
862 fm.plain('\n')
864 elif not exttestedwith:
863 elif not exttestedwith:
865 fm.plain(_(' (untested!)\n'))
864 fm.plain(_(' (untested!)\n'))
866 else:
865 else:
867 lasttestedversion = exttestedwith[-1]
866 lasttestedversion = exttestedwith[-1]
868 fm.plain(' (%s!)\n' % lasttestedversion)
867 fm.plain(' (%s!)\n' % lasttestedversion)
869
868
870 fm.condwrite(ui.verbose and extsource, 'source',
869 fm.condwrite(ui.verbose and extsource, 'source',
871 _(' location: %s\n'), extsource or "")
870 _(' location: %s\n'), extsource or "")
872
871
873 if ui.verbose:
872 if ui.verbose:
874 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
873 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
875 fm.data(bundled=isinternal)
874 fm.data(bundled=isinternal)
876
875
877 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
876 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
878 _(' tested with: %s\n'),
877 _(' tested with: %s\n'),
879 fm.formatlist(exttestedwith, name='ver'))
878 fm.formatlist(exttestedwith, name='ver'))
880
879
881 fm.condwrite(ui.verbose and extbuglink, 'buglink',
880 fm.condwrite(ui.verbose and extbuglink, 'buglink',
882 _(' bug reporting: %s\n'), extbuglink or "")
881 _(' bug reporting: %s\n'), extbuglink or "")
883
882
884 fm.end()
883 fm.end()
885
884
886 @command('debugfileset',
885 @command('debugfileset',
887 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
886 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
888 _('[-r REV] FILESPEC'))
887 _('[-r REV] FILESPEC'))
889 def debugfileset(ui, repo, expr, **opts):
888 def debugfileset(ui, repo, expr, **opts):
890 '''parse and apply a fileset specification'''
889 '''parse and apply a fileset specification'''
891 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
890 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
892 if ui.verbose:
891 if ui.verbose:
893 tree = fileset.parse(expr)
892 tree = fileset.parse(expr)
894 ui.note(fileset.prettyformat(tree), "\n")
893 ui.note(fileset.prettyformat(tree), "\n")
895
894
896 for f in ctx.getfileset(expr):
895 for f in ctx.getfileset(expr):
897 ui.write("%s\n" % f)
896 ui.write("%s\n" % f)
898
897
899 @command('debugformat',
898 @command('debugformat',
900 [] + cmdutil.formatteropts,
899 [] + cmdutil.formatteropts,
901 _(''))
900 _(''))
902 def debugformat(ui, repo, **opts):
901 def debugformat(ui, repo, **opts):
903 """display format information about the current repository
902 """display format information about the current repository
904
903
905 Use --verbose to get extra information about current config value and
904 Use --verbose to get extra information about current config value and
906 Mercurial default."""
905 Mercurial default."""
907 opts = pycompat.byteskwargs(opts)
906 opts = pycompat.byteskwargs(opts)
908 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
907 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
909 maxvariantlength = max(len('format-variant'), maxvariantlength)
908 maxvariantlength = max(len('format-variant'), maxvariantlength)
910
909
911 def makeformatname(name):
910 def makeformatname(name):
912 return '%s:' + (' ' * (maxvariantlength - len(name)))
911 return '%s:' + (' ' * (maxvariantlength - len(name)))
913
912
914 fm = ui.formatter('debugformat', opts)
913 fm = ui.formatter('debugformat', opts)
915 if fm.isplain():
914 if fm.isplain():
916 def formatvalue(value):
915 def formatvalue(value):
917 if util.safehasattr(value, 'startswith'):
916 if util.safehasattr(value, 'startswith'):
918 return value
917 return value
919 if value:
918 if value:
920 return 'yes'
919 return 'yes'
921 else:
920 else:
922 return 'no'
921 return 'no'
923 else:
922 else:
924 formatvalue = pycompat.identity
923 formatvalue = pycompat.identity
925
924
926 fm.plain('format-variant')
925 fm.plain('format-variant')
927 fm.plain(' ' * (maxvariantlength - len('format-variant')))
926 fm.plain(' ' * (maxvariantlength - len('format-variant')))
928 fm.plain(' repo')
927 fm.plain(' repo')
929 if ui.verbose:
928 if ui.verbose:
930 fm.plain(' config default')
929 fm.plain(' config default')
931 fm.plain('\n')
930 fm.plain('\n')
932 for fv in upgrade.allformatvariant:
931 for fv in upgrade.allformatvariant:
933 fm.startitem()
932 fm.startitem()
934 repovalue = fv.fromrepo(repo)
933 repovalue = fv.fromrepo(repo)
935 configvalue = fv.fromconfig(repo)
934 configvalue = fv.fromconfig(repo)
936
935
937 if repovalue != configvalue:
936 if repovalue != configvalue:
938 namelabel = 'formatvariant.name.mismatchconfig'
937 namelabel = 'formatvariant.name.mismatchconfig'
939 repolabel = 'formatvariant.repo.mismatchconfig'
938 repolabel = 'formatvariant.repo.mismatchconfig'
940 elif repovalue != fv.default:
939 elif repovalue != fv.default:
941 namelabel = 'formatvariant.name.mismatchdefault'
940 namelabel = 'formatvariant.name.mismatchdefault'
942 repolabel = 'formatvariant.repo.mismatchdefault'
941 repolabel = 'formatvariant.repo.mismatchdefault'
943 else:
942 else:
944 namelabel = 'formatvariant.name.uptodate'
943 namelabel = 'formatvariant.name.uptodate'
945 repolabel = 'formatvariant.repo.uptodate'
944 repolabel = 'formatvariant.repo.uptodate'
946
945
947 fm.write('name', makeformatname(fv.name), fv.name,
946 fm.write('name', makeformatname(fv.name), fv.name,
948 label=namelabel)
947 label=namelabel)
949 fm.write('repo', ' %3s', formatvalue(repovalue),
948 fm.write('repo', ' %3s', formatvalue(repovalue),
950 label=repolabel)
949 label=repolabel)
951 if fv.default != configvalue:
950 if fv.default != configvalue:
952 configlabel = 'formatvariant.config.special'
951 configlabel = 'formatvariant.config.special'
953 else:
952 else:
954 configlabel = 'formatvariant.config.default'
953 configlabel = 'formatvariant.config.default'
955 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
954 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
956 label=configlabel)
955 label=configlabel)
957 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
956 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
958 label='formatvariant.default')
957 label='formatvariant.default')
959 fm.plain('\n')
958 fm.plain('\n')
960 fm.end()
959 fm.end()
961
960
962 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
961 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
963 def debugfsinfo(ui, path="."):
962 def debugfsinfo(ui, path="."):
964 """show information detected about current filesystem"""
963 """show information detected about current filesystem"""
965 ui.write(('path: %s\n') % path)
964 ui.write(('path: %s\n') % path)
966 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
965 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
967 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
966 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
968 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
967 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
969 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
968 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
970 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
969 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
971 casesensitive = '(unknown)'
970 casesensitive = '(unknown)'
972 try:
971 try:
973 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
972 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
974 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
973 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
975 except OSError:
974 except OSError:
976 pass
975 pass
977 ui.write(('case-sensitive: %s\n') % casesensitive)
976 ui.write(('case-sensitive: %s\n') % casesensitive)
978
977
979 @command('debuggetbundle',
978 @command('debuggetbundle',
980 [('H', 'head', [], _('id of head node'), _('ID')),
979 [('H', 'head', [], _('id of head node'), _('ID')),
981 ('C', 'common', [], _('id of common node'), _('ID')),
980 ('C', 'common', [], _('id of common node'), _('ID')),
982 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
981 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
983 _('REPO FILE [-H|-C ID]...'),
982 _('REPO FILE [-H|-C ID]...'),
984 norepo=True)
983 norepo=True)
985 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
984 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
986 """retrieves a bundle from a repo
985 """retrieves a bundle from a repo
987
986
988 Every ID must be a full-length hex node id string. Saves the bundle to the
987 Every ID must be a full-length hex node id string. Saves the bundle to the
989 given file.
988 given file.
990 """
989 """
991 opts = pycompat.byteskwargs(opts)
990 opts = pycompat.byteskwargs(opts)
992 repo = hg.peer(ui, opts, repopath)
991 repo = hg.peer(ui, opts, repopath)
993 if not repo.capable('getbundle'):
992 if not repo.capable('getbundle'):
994 raise error.Abort("getbundle() not supported by target repository")
993 raise error.Abort("getbundle() not supported by target repository")
995 args = {}
994 args = {}
996 if common:
995 if common:
997 args[r'common'] = [bin(s) for s in common]
996 args[r'common'] = [bin(s) for s in common]
998 if head:
997 if head:
999 args[r'heads'] = [bin(s) for s in head]
998 args[r'heads'] = [bin(s) for s in head]
1000 # TODO: get desired bundlecaps from command line.
999 # TODO: get desired bundlecaps from command line.
1001 args[r'bundlecaps'] = None
1000 args[r'bundlecaps'] = None
1002 bundle = repo.getbundle('debug', **args)
1001 bundle = repo.getbundle('debug', **args)
1003
1002
1004 bundletype = opts.get('type', 'bzip2').lower()
1003 bundletype = opts.get('type', 'bzip2').lower()
1005 btypes = {'none': 'HG10UN',
1004 btypes = {'none': 'HG10UN',
1006 'bzip2': 'HG10BZ',
1005 'bzip2': 'HG10BZ',
1007 'gzip': 'HG10GZ',
1006 'gzip': 'HG10GZ',
1008 'bundle2': 'HG20'}
1007 'bundle2': 'HG20'}
1009 bundletype = btypes.get(bundletype)
1008 bundletype = btypes.get(bundletype)
1010 if bundletype not in bundle2.bundletypes:
1009 if bundletype not in bundle2.bundletypes:
1011 raise error.Abort(_('unknown bundle type specified with --type'))
1010 raise error.Abort(_('unknown bundle type specified with --type'))
1012 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1011 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1013
1012
1014 @command('debugignore', [], '[FILE]')
1013 @command('debugignore', [], '[FILE]')
1015 def debugignore(ui, repo, *files, **opts):
1014 def debugignore(ui, repo, *files, **opts):
1016 """display the combined ignore pattern and information about ignored files
1015 """display the combined ignore pattern and information about ignored files
1017
1016
1018 With no argument display the combined ignore pattern.
1017 With no argument display the combined ignore pattern.
1019
1018
1020 Given space separated file names, shows if the given file is ignored and
1019 Given space separated file names, shows if the given file is ignored and
1021 if so, show the ignore rule (file and line number) that matched it.
1020 if so, show the ignore rule (file and line number) that matched it.
1022 """
1021 """
1023 ignore = repo.dirstate._ignore
1022 ignore = repo.dirstate._ignore
1024 if not files:
1023 if not files:
1025 # Show all the patterns
1024 # Show all the patterns
1026 ui.write("%s\n" % pycompat.byterepr(ignore))
1025 ui.write("%s\n" % pycompat.byterepr(ignore))
1027 else:
1026 else:
1028 m = scmutil.match(repo[None], pats=files)
1027 m = scmutil.match(repo[None], pats=files)
1029 for f in m.files():
1028 for f in m.files():
1030 nf = util.normpath(f)
1029 nf = util.normpath(f)
1031 ignored = None
1030 ignored = None
1032 ignoredata = None
1031 ignoredata = None
1033 if nf != '.':
1032 if nf != '.':
1034 if ignore(nf):
1033 if ignore(nf):
1035 ignored = nf
1034 ignored = nf
1036 ignoredata = repo.dirstate._ignorefileandline(nf)
1035 ignoredata = repo.dirstate._ignorefileandline(nf)
1037 else:
1036 else:
1038 for p in util.finddirs(nf):
1037 for p in util.finddirs(nf):
1039 if ignore(p):
1038 if ignore(p):
1040 ignored = p
1039 ignored = p
1041 ignoredata = repo.dirstate._ignorefileandline(p)
1040 ignoredata = repo.dirstate._ignorefileandline(p)
1042 break
1041 break
1043 if ignored:
1042 if ignored:
1044 if ignored == nf:
1043 if ignored == nf:
1045 ui.write(_("%s is ignored\n") % m.uipath(f))
1044 ui.write(_("%s is ignored\n") % m.uipath(f))
1046 else:
1045 else:
1047 ui.write(_("%s is ignored because of "
1046 ui.write(_("%s is ignored because of "
1048 "containing folder %s\n")
1047 "containing folder %s\n")
1049 % (m.uipath(f), ignored))
1048 % (m.uipath(f), ignored))
1050 ignorefile, lineno, line = ignoredata
1049 ignorefile, lineno, line = ignoredata
1051 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1050 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1052 % (ignorefile, lineno, line))
1051 % (ignorefile, lineno, line))
1053 else:
1052 else:
1054 ui.write(_("%s is not ignored\n") % m.uipath(f))
1053 ui.write(_("%s is not ignored\n") % m.uipath(f))
1055
1054
1056 @command('debugindex', cmdutil.debugrevlogopts +
1055 @command('debugindex', cmdutil.debugrevlogopts +
1057 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1056 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1058 _('[-f FORMAT] -c|-m|FILE'),
1057 _('[-f FORMAT] -c|-m|FILE'),
1059 optionalrepo=True)
1058 optionalrepo=True)
1060 def debugindex(ui, repo, file_=None, **opts):
1059 def debugindex(ui, repo, file_=None, **opts):
1061 """dump the contents of an index file"""
1060 """dump the contents of an index file"""
1062 opts = pycompat.byteskwargs(opts)
1061 opts = pycompat.byteskwargs(opts)
1063 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1062 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1064 format = opts.get('format', 0)
1063 format = opts.get('format', 0)
1065 if format not in (0, 1):
1064 if format not in (0, 1):
1066 raise error.Abort(_("unknown format %d") % format)
1065 raise error.Abort(_("unknown format %d") % format)
1067
1066
1068 if ui.debugflag:
1067 if ui.debugflag:
1069 shortfn = hex
1068 shortfn = hex
1070 else:
1069 else:
1071 shortfn = short
1070 shortfn = short
1072
1071
1073 # There might not be anything in r, so have a sane default
1072 # There might not be anything in r, so have a sane default
1074 idlen = 12
1073 idlen = 12
1075 for i in r:
1074 for i in r:
1076 idlen = len(shortfn(r.node(i)))
1075 idlen = len(shortfn(r.node(i)))
1077 break
1076 break
1078
1077
1079 if format == 0:
1078 if format == 0:
1080 if ui.verbose:
1079 if ui.verbose:
1081 ui.write((" rev offset length linkrev"
1080 ui.write((" rev offset length linkrev"
1082 " %s %s p2\n") % ("nodeid".ljust(idlen),
1081 " %s %s p2\n") % ("nodeid".ljust(idlen),
1083 "p1".ljust(idlen)))
1082 "p1".ljust(idlen)))
1084 else:
1083 else:
1085 ui.write((" rev linkrev %s %s p2\n") % (
1084 ui.write((" rev linkrev %s %s p2\n") % (
1086 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1085 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1087 elif format == 1:
1086 elif format == 1:
1088 if ui.verbose:
1087 if ui.verbose:
1089 ui.write((" rev flag offset length size link p1"
1088 ui.write((" rev flag offset length size link p1"
1090 " p2 %s\n") % "nodeid".rjust(idlen))
1089 " p2 %s\n") % "nodeid".rjust(idlen))
1091 else:
1090 else:
1092 ui.write((" rev flag size link p1 p2 %s\n") %
1091 ui.write((" rev flag size link p1 p2 %s\n") %
1093 "nodeid".rjust(idlen))
1092 "nodeid".rjust(idlen))
1094
1093
1095 for i in r:
1094 for i in r:
1096 node = r.node(i)
1095 node = r.node(i)
1097 if format == 0:
1096 if format == 0:
1098 try:
1097 try:
1099 pp = r.parents(node)
1098 pp = r.parents(node)
1100 except Exception:
1099 except Exception:
1101 pp = [nullid, nullid]
1100 pp = [nullid, nullid]
1102 if ui.verbose:
1101 if ui.verbose:
1103 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1102 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1104 i, r.start(i), r.length(i), r.linkrev(i),
1103 i, r.start(i), r.length(i), r.linkrev(i),
1105 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1104 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1106 else:
1105 else:
1107 ui.write("% 6d % 7d %s %s %s\n" % (
1106 ui.write("% 6d % 7d %s %s %s\n" % (
1108 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1107 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1109 shortfn(pp[1])))
1108 shortfn(pp[1])))
1110 elif format == 1:
1109 elif format == 1:
1111 pr = r.parentrevs(i)
1110 pr = r.parentrevs(i)
1112 if ui.verbose:
1111 if ui.verbose:
1113 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1112 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1114 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1113 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1115 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1114 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1116 else:
1115 else:
1117 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1116 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1118 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1117 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1119 shortfn(node)))
1118 shortfn(node)))
1120
1119
1121 @command('debugindexdot', cmdutil.debugrevlogopts,
1120 @command('debugindexdot', cmdutil.debugrevlogopts,
1122 _('-c|-m|FILE'), optionalrepo=True)
1121 _('-c|-m|FILE'), optionalrepo=True)
1123 def debugindexdot(ui, repo, file_=None, **opts):
1122 def debugindexdot(ui, repo, file_=None, **opts):
1124 """dump an index DAG as a graphviz dot file"""
1123 """dump an index DAG as a graphviz dot file"""
1125 opts = pycompat.byteskwargs(opts)
1124 opts = pycompat.byteskwargs(opts)
1126 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1125 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1127 ui.write(("digraph G {\n"))
1126 ui.write(("digraph G {\n"))
1128 for i in r:
1127 for i in r:
1129 node = r.node(i)
1128 node = r.node(i)
1130 pp = r.parents(node)
1129 pp = r.parents(node)
1131 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1130 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1132 if pp[1] != nullid:
1131 if pp[1] != nullid:
1133 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1132 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1134 ui.write("}\n")
1133 ui.write("}\n")
1135
1134
1136 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1135 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1137 def debuginstall(ui, **opts):
1136 def debuginstall(ui, **opts):
1138 '''test Mercurial installation
1137 '''test Mercurial installation
1139
1138
1140 Returns 0 on success.
1139 Returns 0 on success.
1141 '''
1140 '''
1142 opts = pycompat.byteskwargs(opts)
1141 opts = pycompat.byteskwargs(opts)
1143
1142
1144 def writetemp(contents):
1143 def writetemp(contents):
1145 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
1144 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
1146 f = os.fdopen(fd, r"wb")
1145 f = os.fdopen(fd, r"wb")
1147 f.write(contents)
1146 f.write(contents)
1148 f.close()
1147 f.close()
1149 return name
1148 return name
1150
1149
1151 problems = 0
1150 problems = 0
1152
1151
1153 fm = ui.formatter('debuginstall', opts)
1152 fm = ui.formatter('debuginstall', opts)
1154 fm.startitem()
1153 fm.startitem()
1155
1154
1156 # encoding
1155 # encoding
1157 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1156 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1158 err = None
1157 err = None
1159 try:
1158 try:
1160 codecs.lookup(pycompat.sysstr(encoding.encoding))
1159 codecs.lookup(pycompat.sysstr(encoding.encoding))
1161 except LookupError as inst:
1160 except LookupError as inst:
1162 err = stringutil.forcebytestr(inst)
1161 err = stringutil.forcebytestr(inst)
1163 problems += 1
1162 problems += 1
1164 fm.condwrite(err, 'encodingerror', _(" %s\n"
1163 fm.condwrite(err, 'encodingerror', _(" %s\n"
1165 " (check that your locale is properly set)\n"), err)
1164 " (check that your locale is properly set)\n"), err)
1166
1165
1167 # Python
1166 # Python
1168 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1167 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1169 pycompat.sysexecutable)
1168 pycompat.sysexecutable)
1170 fm.write('pythonver', _("checking Python version (%s)\n"),
1169 fm.write('pythonver', _("checking Python version (%s)\n"),
1171 ("%d.%d.%d" % sys.version_info[:3]))
1170 ("%d.%d.%d" % sys.version_info[:3]))
1172 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1171 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1173 os.path.dirname(pycompat.fsencode(os.__file__)))
1172 os.path.dirname(pycompat.fsencode(os.__file__)))
1174
1173
1175 security = set(sslutil.supportedprotocols)
1174 security = set(sslutil.supportedprotocols)
1176 if sslutil.hassni:
1175 if sslutil.hassni:
1177 security.add('sni')
1176 security.add('sni')
1178
1177
1179 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1178 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1180 fm.formatlist(sorted(security), name='protocol',
1179 fm.formatlist(sorted(security), name='protocol',
1181 fmt='%s', sep=','))
1180 fmt='%s', sep=','))
1182
1181
1183 # These are warnings, not errors. So don't increment problem count. This
1182 # These are warnings, not errors. So don't increment problem count. This
1184 # may change in the future.
1183 # may change in the future.
1185 if 'tls1.2' not in security:
1184 if 'tls1.2' not in security:
1186 fm.plain(_(' TLS 1.2 not supported by Python install; '
1185 fm.plain(_(' TLS 1.2 not supported by Python install; '
1187 'network connections lack modern security\n'))
1186 'network connections lack modern security\n'))
1188 if 'sni' not in security:
1187 if 'sni' not in security:
1189 fm.plain(_(' SNI not supported by Python install; may have '
1188 fm.plain(_(' SNI not supported by Python install; may have '
1190 'connectivity issues with some servers\n'))
1189 'connectivity issues with some servers\n'))
1191
1190
1192 # TODO print CA cert info
1191 # TODO print CA cert info
1193
1192
1194 # hg version
1193 # hg version
1195 hgver = util.version()
1194 hgver = util.version()
1196 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1195 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1197 hgver.split('+')[0])
1196 hgver.split('+')[0])
1198 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1197 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1199 '+'.join(hgver.split('+')[1:]))
1198 '+'.join(hgver.split('+')[1:]))
1200
1199
1201 # compiled modules
1200 # compiled modules
1202 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1201 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1203 policy.policy)
1202 policy.policy)
1204 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1203 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1205 os.path.dirname(pycompat.fsencode(__file__)))
1204 os.path.dirname(pycompat.fsencode(__file__)))
1206
1205
1207 if policy.policy in ('c', 'allow'):
1206 if policy.policy in ('c', 'allow'):
1208 err = None
1207 err = None
1209 try:
1208 try:
1210 from .cext import (
1209 from .cext import (
1211 base85,
1210 base85,
1212 bdiff,
1211 bdiff,
1213 mpatch,
1212 mpatch,
1214 osutil,
1213 osutil,
1215 )
1214 )
1216 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1215 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1217 except Exception as inst:
1216 except Exception as inst:
1218 err = stringutil.forcebytestr(inst)
1217 err = stringutil.forcebytestr(inst)
1219 problems += 1
1218 problems += 1
1220 fm.condwrite(err, 'extensionserror', " %s\n", err)
1219 fm.condwrite(err, 'extensionserror', " %s\n", err)
1221
1220
1222 compengines = util.compengines._engines.values()
1221 compengines = util.compengines._engines.values()
1223 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1222 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1224 fm.formatlist(sorted(e.name() for e in compengines),
1223 fm.formatlist(sorted(e.name() for e in compengines),
1225 name='compengine', fmt='%s', sep=', '))
1224 name='compengine', fmt='%s', sep=', '))
1226 fm.write('compenginesavail', _('checking available compression engines '
1225 fm.write('compenginesavail', _('checking available compression engines '
1227 '(%s)\n'),
1226 '(%s)\n'),
1228 fm.formatlist(sorted(e.name() for e in compengines
1227 fm.formatlist(sorted(e.name() for e in compengines
1229 if e.available()),
1228 if e.available()),
1230 name='compengine', fmt='%s', sep=', '))
1229 name='compengine', fmt='%s', sep=', '))
1231 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1230 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1232 fm.write('compenginesserver', _('checking available compression engines '
1231 fm.write('compenginesserver', _('checking available compression engines '
1233 'for wire protocol (%s)\n'),
1232 'for wire protocol (%s)\n'),
1234 fm.formatlist([e.name() for e in wirecompengines
1233 fm.formatlist([e.name() for e in wirecompengines
1235 if e.wireprotosupport()],
1234 if e.wireprotosupport()],
1236 name='compengine', fmt='%s', sep=', '))
1235 name='compengine', fmt='%s', sep=', '))
1237 re2 = 'missing'
1236 re2 = 'missing'
1238 if util._re2:
1237 if util._re2:
1239 re2 = 'available'
1238 re2 = 'available'
1240 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1239 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1241 fm.data(re2=bool(util._re2))
1240 fm.data(re2=bool(util._re2))
1242
1241
1243 # templates
1242 # templates
1244 p = templater.templatepaths()
1243 p = templater.templatepaths()
1245 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1244 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1246 fm.condwrite(not p, '', _(" no template directories found\n"))
1245 fm.condwrite(not p, '', _(" no template directories found\n"))
1247 if p:
1246 if p:
1248 m = templater.templatepath("map-cmdline.default")
1247 m = templater.templatepath("map-cmdline.default")
1249 if m:
1248 if m:
1250 # template found, check if it is working
1249 # template found, check if it is working
1251 err = None
1250 err = None
1252 try:
1251 try:
1253 templater.templater.frommapfile(m)
1252 templater.templater.frommapfile(m)
1254 except Exception as inst:
1253 except Exception as inst:
1255 err = stringutil.forcebytestr(inst)
1254 err = stringutil.forcebytestr(inst)
1256 p = None
1255 p = None
1257 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1256 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1258 else:
1257 else:
1259 p = None
1258 p = None
1260 fm.condwrite(p, 'defaulttemplate',
1259 fm.condwrite(p, 'defaulttemplate',
1261 _("checking default template (%s)\n"), m)
1260 _("checking default template (%s)\n"), m)
1262 fm.condwrite(not m, 'defaulttemplatenotfound',
1261 fm.condwrite(not m, 'defaulttemplatenotfound',
1263 _(" template '%s' not found\n"), "default")
1262 _(" template '%s' not found\n"), "default")
1264 if not p:
1263 if not p:
1265 problems += 1
1264 problems += 1
1266 fm.condwrite(not p, '',
1265 fm.condwrite(not p, '',
1267 _(" (templates seem to have been installed incorrectly)\n"))
1266 _(" (templates seem to have been installed incorrectly)\n"))
1268
1267
1269 # editor
1268 # editor
1270 editor = ui.geteditor()
1269 editor = ui.geteditor()
1271 editor = util.expandpath(editor)
1270 editor = util.expandpath(editor)
1272 editorbin = procutil.shellsplit(editor)[0]
1271 editorbin = procutil.shellsplit(editor)[0]
1273 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1272 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1274 cmdpath = procutil.findexe(editorbin)
1273 cmdpath = procutil.findexe(editorbin)
1275 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1274 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1276 _(" No commit editor set and can't find %s in PATH\n"
1275 _(" No commit editor set and can't find %s in PATH\n"
1277 " (specify a commit editor in your configuration"
1276 " (specify a commit editor in your configuration"
1278 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1277 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1279 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1278 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1280 _(" Can't find editor '%s' in PATH\n"
1279 _(" Can't find editor '%s' in PATH\n"
1281 " (specify a commit editor in your configuration"
1280 " (specify a commit editor in your configuration"
1282 " file)\n"), not cmdpath and editorbin)
1281 " file)\n"), not cmdpath and editorbin)
1283 if not cmdpath and editor != 'vi':
1282 if not cmdpath and editor != 'vi':
1284 problems += 1
1283 problems += 1
1285
1284
1286 # check username
1285 # check username
1287 username = None
1286 username = None
1288 err = None
1287 err = None
1289 try:
1288 try:
1290 username = ui.username()
1289 username = ui.username()
1291 except error.Abort as e:
1290 except error.Abort as e:
1292 err = stringutil.forcebytestr(e)
1291 err = stringutil.forcebytestr(e)
1293 problems += 1
1292 problems += 1
1294
1293
1295 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1294 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1296 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1295 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1297 " (specify a username in your configuration file)\n"), err)
1296 " (specify a username in your configuration file)\n"), err)
1298
1297
1299 fm.condwrite(not problems, '',
1298 fm.condwrite(not problems, '',
1300 _("no problems detected\n"))
1299 _("no problems detected\n"))
1301 if not problems:
1300 if not problems:
1302 fm.data(problems=problems)
1301 fm.data(problems=problems)
1303 fm.condwrite(problems, 'problems',
1302 fm.condwrite(problems, 'problems',
1304 _("%d problems detected,"
1303 _("%d problems detected,"
1305 " please check your install!\n"), problems)
1304 " please check your install!\n"), problems)
1306 fm.end()
1305 fm.end()
1307
1306
1308 return problems
1307 return problems
1309
1308
1310 @command('debugknown', [], _('REPO ID...'), norepo=True)
1309 @command('debugknown', [], _('REPO ID...'), norepo=True)
1311 def debugknown(ui, repopath, *ids, **opts):
1310 def debugknown(ui, repopath, *ids, **opts):
1312 """test whether node ids are known to a repo
1311 """test whether node ids are known to a repo
1313
1312
1314 Every ID must be a full-length hex node id string. Returns a list of 0s
1313 Every ID must be a full-length hex node id string. Returns a list of 0s
1315 and 1s indicating unknown/known.
1314 and 1s indicating unknown/known.
1316 """
1315 """
1317 opts = pycompat.byteskwargs(opts)
1316 opts = pycompat.byteskwargs(opts)
1318 repo = hg.peer(ui, opts, repopath)
1317 repo = hg.peer(ui, opts, repopath)
1319 if not repo.capable('known'):
1318 if not repo.capable('known'):
1320 raise error.Abort("known() not supported by target repository")
1319 raise error.Abort("known() not supported by target repository")
1321 flags = repo.known([bin(s) for s in ids])
1320 flags = repo.known([bin(s) for s in ids])
1322 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1321 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1323
1322
1324 @command('debuglabelcomplete', [], _('LABEL...'))
1323 @command('debuglabelcomplete', [], _('LABEL...'))
1325 def debuglabelcomplete(ui, repo, *args):
1324 def debuglabelcomplete(ui, repo, *args):
1326 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1325 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1327 debugnamecomplete(ui, repo, *args)
1326 debugnamecomplete(ui, repo, *args)
1328
1327
1329 @command('debuglocks',
1328 @command('debuglocks',
1330 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1329 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1331 ('W', 'force-wlock', None,
1330 ('W', 'force-wlock', None,
1332 _('free the working state lock (DANGEROUS)')),
1331 _('free the working state lock (DANGEROUS)')),
1333 ('s', 'set-lock', None, _('set the store lock until stopped')),
1332 ('s', 'set-lock', None, _('set the store lock until stopped')),
1334 ('S', 'set-wlock', None,
1333 ('S', 'set-wlock', None,
1335 _('set the working state lock until stopped'))],
1334 _('set the working state lock until stopped'))],
1336 _('[OPTION]...'))
1335 _('[OPTION]...'))
1337 def debuglocks(ui, repo, **opts):
1336 def debuglocks(ui, repo, **opts):
1338 """show or modify state of locks
1337 """show or modify state of locks
1339
1338
1340 By default, this command will show which locks are held. This
1339 By default, this command will show which locks are held. This
1341 includes the user and process holding the lock, the amount of time
1340 includes the user and process holding the lock, the amount of time
1342 the lock has been held, and the machine name where the process is
1341 the lock has been held, and the machine name where the process is
1343 running if it's not local.
1342 running if it's not local.
1344
1343
1345 Locks protect the integrity of Mercurial's data, so should be
1344 Locks protect the integrity of Mercurial's data, so should be
1346 treated with care. System crashes or other interruptions may cause
1345 treated with care. System crashes or other interruptions may cause
1347 locks to not be properly released, though Mercurial will usually
1346 locks to not be properly released, though Mercurial will usually
1348 detect and remove such stale locks automatically.
1347 detect and remove such stale locks automatically.
1349
1348
1350 However, detecting stale locks may not always be possible (for
1349 However, detecting stale locks may not always be possible (for
1351 instance, on a shared filesystem). Removing locks may also be
1350 instance, on a shared filesystem). Removing locks may also be
1352 blocked by filesystem permissions.
1351 blocked by filesystem permissions.
1353
1352
1354 Setting a lock will prevent other commands from changing the data.
1353 Setting a lock will prevent other commands from changing the data.
1355 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1354 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1356 The set locks are removed when the command exits.
1355 The set locks are removed when the command exits.
1357
1356
1358 Returns 0 if no locks are held.
1357 Returns 0 if no locks are held.
1359
1358
1360 """
1359 """
1361
1360
1362 if opts.get(r'force_lock'):
1361 if opts.get(r'force_lock'):
1363 repo.svfs.unlink('lock')
1362 repo.svfs.unlink('lock')
1364 if opts.get(r'force_wlock'):
1363 if opts.get(r'force_wlock'):
1365 repo.vfs.unlink('wlock')
1364 repo.vfs.unlink('wlock')
1366 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1365 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1367 return 0
1366 return 0
1368
1367
1369 locks = []
1368 locks = []
1370 try:
1369 try:
1371 if opts.get(r'set_wlock'):
1370 if opts.get(r'set_wlock'):
1372 try:
1371 try:
1373 locks.append(repo.wlock(False))
1372 locks.append(repo.wlock(False))
1374 except error.LockHeld:
1373 except error.LockHeld:
1375 raise error.Abort(_('wlock is already held'))
1374 raise error.Abort(_('wlock is already held'))
1376 if opts.get(r'set_lock'):
1375 if opts.get(r'set_lock'):
1377 try:
1376 try:
1378 locks.append(repo.lock(False))
1377 locks.append(repo.lock(False))
1379 except error.LockHeld:
1378 except error.LockHeld:
1380 raise error.Abort(_('lock is already held'))
1379 raise error.Abort(_('lock is already held'))
1381 if len(locks):
1380 if len(locks):
1382 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1381 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1383 return 0
1382 return 0
1384 finally:
1383 finally:
1385 release(*locks)
1384 release(*locks)
1386
1385
1387 now = time.time()
1386 now = time.time()
1388 held = 0
1387 held = 0
1389
1388
1390 def report(vfs, name, method):
1389 def report(vfs, name, method):
1391 # this causes stale locks to get reaped for more accurate reporting
1390 # this causes stale locks to get reaped for more accurate reporting
1392 try:
1391 try:
1393 l = method(False)
1392 l = method(False)
1394 except error.LockHeld:
1393 except error.LockHeld:
1395 l = None
1394 l = None
1396
1395
1397 if l:
1396 if l:
1398 l.release()
1397 l.release()
1399 else:
1398 else:
1400 try:
1399 try:
1401 st = vfs.lstat(name)
1400 st = vfs.lstat(name)
1402 age = now - st[stat.ST_MTIME]
1401 age = now - st[stat.ST_MTIME]
1403 user = util.username(st.st_uid)
1402 user = util.username(st.st_uid)
1404 locker = vfs.readlock(name)
1403 locker = vfs.readlock(name)
1405 if ":" in locker:
1404 if ":" in locker:
1406 host, pid = locker.split(':')
1405 host, pid = locker.split(':')
1407 if host == socket.gethostname():
1406 if host == socket.gethostname():
1408 locker = 'user %s, process %s' % (user, pid)
1407 locker = 'user %s, process %s' % (user, pid)
1409 else:
1408 else:
1410 locker = 'user %s, process %s, host %s' \
1409 locker = 'user %s, process %s, host %s' \
1411 % (user, pid, host)
1410 % (user, pid, host)
1412 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1411 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1413 return 1
1412 return 1
1414 except OSError as e:
1413 except OSError as e:
1415 if e.errno != errno.ENOENT:
1414 if e.errno != errno.ENOENT:
1416 raise
1415 raise
1417
1416
1418 ui.write(("%-6s free\n") % (name + ":"))
1417 ui.write(("%-6s free\n") % (name + ":"))
1419 return 0
1418 return 0
1420
1419
1421 held += report(repo.svfs, "lock", repo.lock)
1420 held += report(repo.svfs, "lock", repo.lock)
1422 held += report(repo.vfs, "wlock", repo.wlock)
1421 held += report(repo.vfs, "wlock", repo.wlock)
1423
1422
1424 return held
1423 return held
1425
1424
1426 @command('debugmergestate', [], '')
1425 @command('debugmergestate', [], '')
1427 def debugmergestate(ui, repo, *args):
1426 def debugmergestate(ui, repo, *args):
1428 """print merge state
1427 """print merge state
1429
1428
1430 Use --verbose to print out information about whether v1 or v2 merge state
1429 Use --verbose to print out information about whether v1 or v2 merge state
1431 was chosen."""
1430 was chosen."""
1432 def _hashornull(h):
1431 def _hashornull(h):
1433 if h == nullhex:
1432 if h == nullhex:
1434 return 'null'
1433 return 'null'
1435 else:
1434 else:
1436 return h
1435 return h
1437
1436
1438 def printrecords(version):
1437 def printrecords(version):
1439 ui.write(('* version %d records\n') % version)
1438 ui.write(('* version %d records\n') % version)
1440 if version == 1:
1439 if version == 1:
1441 records = v1records
1440 records = v1records
1442 else:
1441 else:
1443 records = v2records
1442 records = v2records
1444
1443
1445 for rtype, record in records:
1444 for rtype, record in records:
1446 # pretty print some record types
1445 # pretty print some record types
1447 if rtype == 'L':
1446 if rtype == 'L':
1448 ui.write(('local: %s\n') % record)
1447 ui.write(('local: %s\n') % record)
1449 elif rtype == 'O':
1448 elif rtype == 'O':
1450 ui.write(('other: %s\n') % record)
1449 ui.write(('other: %s\n') % record)
1451 elif rtype == 'm':
1450 elif rtype == 'm':
1452 driver, mdstate = record.split('\0', 1)
1451 driver, mdstate = record.split('\0', 1)
1453 ui.write(('merge driver: %s (state "%s")\n')
1452 ui.write(('merge driver: %s (state "%s")\n')
1454 % (driver, mdstate))
1453 % (driver, mdstate))
1455 elif rtype in 'FDC':
1454 elif rtype in 'FDC':
1456 r = record.split('\0')
1455 r = record.split('\0')
1457 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1456 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1458 if version == 1:
1457 if version == 1:
1459 onode = 'not stored in v1 format'
1458 onode = 'not stored in v1 format'
1460 flags = r[7]
1459 flags = r[7]
1461 else:
1460 else:
1462 onode, flags = r[7:9]
1461 onode, flags = r[7:9]
1463 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1462 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1464 % (f, rtype, state, _hashornull(hash)))
1463 % (f, rtype, state, _hashornull(hash)))
1465 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1464 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1466 ui.write((' ancestor path: %s (node %s)\n')
1465 ui.write((' ancestor path: %s (node %s)\n')
1467 % (afile, _hashornull(anode)))
1466 % (afile, _hashornull(anode)))
1468 ui.write((' other path: %s (node %s)\n')
1467 ui.write((' other path: %s (node %s)\n')
1469 % (ofile, _hashornull(onode)))
1468 % (ofile, _hashornull(onode)))
1470 elif rtype == 'f':
1469 elif rtype == 'f':
1471 filename, rawextras = record.split('\0', 1)
1470 filename, rawextras = record.split('\0', 1)
1472 extras = rawextras.split('\0')
1471 extras = rawextras.split('\0')
1473 i = 0
1472 i = 0
1474 extrastrings = []
1473 extrastrings = []
1475 while i < len(extras):
1474 while i < len(extras):
1476 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1475 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1477 i += 2
1476 i += 2
1478
1477
1479 ui.write(('file extras: %s (%s)\n')
1478 ui.write(('file extras: %s (%s)\n')
1480 % (filename, ', '.join(extrastrings)))
1479 % (filename, ', '.join(extrastrings)))
1481 elif rtype == 'l':
1480 elif rtype == 'l':
1482 labels = record.split('\0', 2)
1481 labels = record.split('\0', 2)
1483 labels = [l for l in labels if len(l) > 0]
1482 labels = [l for l in labels if len(l) > 0]
1484 ui.write(('labels:\n'))
1483 ui.write(('labels:\n'))
1485 ui.write((' local: %s\n' % labels[0]))
1484 ui.write((' local: %s\n' % labels[0]))
1486 ui.write((' other: %s\n' % labels[1]))
1485 ui.write((' other: %s\n' % labels[1]))
1487 if len(labels) > 2:
1486 if len(labels) > 2:
1488 ui.write((' base: %s\n' % labels[2]))
1487 ui.write((' base: %s\n' % labels[2]))
1489 else:
1488 else:
1490 ui.write(('unrecognized entry: %s\t%s\n')
1489 ui.write(('unrecognized entry: %s\t%s\n')
1491 % (rtype, record.replace('\0', '\t')))
1490 % (rtype, record.replace('\0', '\t')))
1492
1491
1493 # Avoid mergestate.read() since it may raise an exception for unsupported
1492 # Avoid mergestate.read() since it may raise an exception for unsupported
1494 # merge state records. We shouldn't be doing this, but this is OK since this
1493 # merge state records. We shouldn't be doing this, but this is OK since this
1495 # command is pretty low-level.
1494 # command is pretty low-level.
1496 ms = mergemod.mergestate(repo)
1495 ms = mergemod.mergestate(repo)
1497
1496
1498 # sort so that reasonable information is on top
1497 # sort so that reasonable information is on top
1499 v1records = ms._readrecordsv1()
1498 v1records = ms._readrecordsv1()
1500 v2records = ms._readrecordsv2()
1499 v2records = ms._readrecordsv2()
1501 order = 'LOml'
1500 order = 'LOml'
1502 def key(r):
1501 def key(r):
1503 idx = order.find(r[0])
1502 idx = order.find(r[0])
1504 if idx == -1:
1503 if idx == -1:
1505 return (1, r[1])
1504 return (1, r[1])
1506 else:
1505 else:
1507 return (0, idx)
1506 return (0, idx)
1508 v1records.sort(key=key)
1507 v1records.sort(key=key)
1509 v2records.sort(key=key)
1508 v2records.sort(key=key)
1510
1509
1511 if not v1records and not v2records:
1510 if not v1records and not v2records:
1512 ui.write(('no merge state found\n'))
1511 ui.write(('no merge state found\n'))
1513 elif not v2records:
1512 elif not v2records:
1514 ui.note(('no version 2 merge state\n'))
1513 ui.note(('no version 2 merge state\n'))
1515 printrecords(1)
1514 printrecords(1)
1516 elif ms._v1v2match(v1records, v2records):
1515 elif ms._v1v2match(v1records, v2records):
1517 ui.note(('v1 and v2 states match: using v2\n'))
1516 ui.note(('v1 and v2 states match: using v2\n'))
1518 printrecords(2)
1517 printrecords(2)
1519 else:
1518 else:
1520 ui.note(('v1 and v2 states mismatch: using v1\n'))
1519 ui.note(('v1 and v2 states mismatch: using v1\n'))
1521 printrecords(1)
1520 printrecords(1)
1522 if ui.verbose:
1521 if ui.verbose:
1523 printrecords(2)
1522 printrecords(2)
1524
1523
1525 @command('debugnamecomplete', [], _('NAME...'))
1524 @command('debugnamecomplete', [], _('NAME...'))
1526 def debugnamecomplete(ui, repo, *args):
1525 def debugnamecomplete(ui, repo, *args):
1527 '''complete "names" - tags, open branch names, bookmark names'''
1526 '''complete "names" - tags, open branch names, bookmark names'''
1528
1527
1529 names = set()
1528 names = set()
1530 # since we previously only listed open branches, we will handle that
1529 # since we previously only listed open branches, we will handle that
1531 # specially (after this for loop)
1530 # specially (after this for loop)
1532 for name, ns in repo.names.iteritems():
1531 for name, ns in repo.names.iteritems():
1533 if name != 'branches':
1532 if name != 'branches':
1534 names.update(ns.listnames(repo))
1533 names.update(ns.listnames(repo))
1535 names.update(tag for (tag, heads, tip, closed)
1534 names.update(tag for (tag, heads, tip, closed)
1536 in repo.branchmap().iterbranches() if not closed)
1535 in repo.branchmap().iterbranches() if not closed)
1537 completions = set()
1536 completions = set()
1538 if not args:
1537 if not args:
1539 args = ['']
1538 args = ['']
1540 for a in args:
1539 for a in args:
1541 completions.update(n for n in names if n.startswith(a))
1540 completions.update(n for n in names if n.startswith(a))
1542 ui.write('\n'.join(sorted(completions)))
1541 ui.write('\n'.join(sorted(completions)))
1543 ui.write('\n')
1542 ui.write('\n')
1544
1543
1545 @command('debugobsolete',
1544 @command('debugobsolete',
1546 [('', 'flags', 0, _('markers flag')),
1545 [('', 'flags', 0, _('markers flag')),
1547 ('', 'record-parents', False,
1546 ('', 'record-parents', False,
1548 _('record parent information for the precursor')),
1547 _('record parent information for the precursor')),
1549 ('r', 'rev', [], _('display markers relevant to REV')),
1548 ('r', 'rev', [], _('display markers relevant to REV')),
1550 ('', 'exclusive', False, _('restrict display to markers only '
1549 ('', 'exclusive', False, _('restrict display to markers only '
1551 'relevant to REV')),
1550 'relevant to REV')),
1552 ('', 'index', False, _('display index of the marker')),
1551 ('', 'index', False, _('display index of the marker')),
1553 ('', 'delete', [], _('delete markers specified by indices')),
1552 ('', 'delete', [], _('delete markers specified by indices')),
1554 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1553 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1555 _('[OBSOLETED [REPLACEMENT ...]]'))
1554 _('[OBSOLETED [REPLACEMENT ...]]'))
1556 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1555 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1557 """create arbitrary obsolete marker
1556 """create arbitrary obsolete marker
1558
1557
1559 With no arguments, displays the list of obsolescence markers."""
1558 With no arguments, displays the list of obsolescence markers."""
1560
1559
1561 opts = pycompat.byteskwargs(opts)
1560 opts = pycompat.byteskwargs(opts)
1562
1561
1563 def parsenodeid(s):
1562 def parsenodeid(s):
1564 try:
1563 try:
1565 # We do not use revsingle/revrange functions here to accept
1564 # We do not use revsingle/revrange functions here to accept
1566 # arbitrary node identifiers, possibly not present in the
1565 # arbitrary node identifiers, possibly not present in the
1567 # local repository.
1566 # local repository.
1568 n = bin(s)
1567 n = bin(s)
1569 if len(n) != len(nullid):
1568 if len(n) != len(nullid):
1570 raise TypeError()
1569 raise TypeError()
1571 return n
1570 return n
1572 except TypeError:
1571 except TypeError:
1573 raise error.Abort('changeset references must be full hexadecimal '
1572 raise error.Abort('changeset references must be full hexadecimal '
1574 'node identifiers')
1573 'node identifiers')
1575
1574
1576 if opts.get('delete'):
1575 if opts.get('delete'):
1577 indices = []
1576 indices = []
1578 for v in opts.get('delete'):
1577 for v in opts.get('delete'):
1579 try:
1578 try:
1580 indices.append(int(v))
1579 indices.append(int(v))
1581 except ValueError:
1580 except ValueError:
1582 raise error.Abort(_('invalid index value: %r') % v,
1581 raise error.Abort(_('invalid index value: %r') % v,
1583 hint=_('use integers for indices'))
1582 hint=_('use integers for indices'))
1584
1583
1585 if repo.currenttransaction():
1584 if repo.currenttransaction():
1586 raise error.Abort(_('cannot delete obsmarkers in the middle '
1585 raise error.Abort(_('cannot delete obsmarkers in the middle '
1587 'of transaction.'))
1586 'of transaction.'))
1588
1587
1589 with repo.lock():
1588 with repo.lock():
1590 n = repair.deleteobsmarkers(repo.obsstore, indices)
1589 n = repair.deleteobsmarkers(repo.obsstore, indices)
1591 ui.write(_('deleted %i obsolescence markers\n') % n)
1590 ui.write(_('deleted %i obsolescence markers\n') % n)
1592
1591
1593 return
1592 return
1594
1593
1595 if precursor is not None:
1594 if precursor is not None:
1596 if opts['rev']:
1595 if opts['rev']:
1597 raise error.Abort('cannot select revision when creating marker')
1596 raise error.Abort('cannot select revision when creating marker')
1598 metadata = {}
1597 metadata = {}
1599 metadata['user'] = opts['user'] or ui.username()
1598 metadata['user'] = opts['user'] or ui.username()
1600 succs = tuple(parsenodeid(succ) for succ in successors)
1599 succs = tuple(parsenodeid(succ) for succ in successors)
1601 l = repo.lock()
1600 l = repo.lock()
1602 try:
1601 try:
1603 tr = repo.transaction('debugobsolete')
1602 tr = repo.transaction('debugobsolete')
1604 try:
1603 try:
1605 date = opts.get('date')
1604 date = opts.get('date')
1606 if date:
1605 if date:
1607 date = dateutil.parsedate(date)
1606 date = dateutil.parsedate(date)
1608 else:
1607 else:
1609 date = None
1608 date = None
1610 prec = parsenodeid(precursor)
1609 prec = parsenodeid(precursor)
1611 parents = None
1610 parents = None
1612 if opts['record_parents']:
1611 if opts['record_parents']:
1613 if prec not in repo.unfiltered():
1612 if prec not in repo.unfiltered():
1614 raise error.Abort('cannot used --record-parents on '
1613 raise error.Abort('cannot used --record-parents on '
1615 'unknown changesets')
1614 'unknown changesets')
1616 parents = repo.unfiltered()[prec].parents()
1615 parents = repo.unfiltered()[prec].parents()
1617 parents = tuple(p.node() for p in parents)
1616 parents = tuple(p.node() for p in parents)
1618 repo.obsstore.create(tr, prec, succs, opts['flags'],
1617 repo.obsstore.create(tr, prec, succs, opts['flags'],
1619 parents=parents, date=date,
1618 parents=parents, date=date,
1620 metadata=metadata, ui=ui)
1619 metadata=metadata, ui=ui)
1621 tr.close()
1620 tr.close()
1622 except ValueError as exc:
1621 except ValueError as exc:
1623 raise error.Abort(_('bad obsmarker input: %s') %
1622 raise error.Abort(_('bad obsmarker input: %s') %
1624 pycompat.bytestr(exc))
1623 pycompat.bytestr(exc))
1625 finally:
1624 finally:
1626 tr.release()
1625 tr.release()
1627 finally:
1626 finally:
1628 l.release()
1627 l.release()
1629 else:
1628 else:
1630 if opts['rev']:
1629 if opts['rev']:
1631 revs = scmutil.revrange(repo, opts['rev'])
1630 revs = scmutil.revrange(repo, opts['rev'])
1632 nodes = [repo[r].node() for r in revs]
1631 nodes = [repo[r].node() for r in revs]
1633 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1632 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1634 exclusive=opts['exclusive']))
1633 exclusive=opts['exclusive']))
1635 markers.sort(key=lambda x: x._data)
1634 markers.sort(key=lambda x: x._data)
1636 else:
1635 else:
1637 markers = obsutil.getmarkers(repo)
1636 markers = obsutil.getmarkers(repo)
1638
1637
1639 markerstoiter = markers
1638 markerstoiter = markers
1640 isrelevant = lambda m: True
1639 isrelevant = lambda m: True
1641 if opts.get('rev') and opts.get('index'):
1640 if opts.get('rev') and opts.get('index'):
1642 markerstoiter = obsutil.getmarkers(repo)
1641 markerstoiter = obsutil.getmarkers(repo)
1643 markerset = set(markers)
1642 markerset = set(markers)
1644 isrelevant = lambda m: m in markerset
1643 isrelevant = lambda m: m in markerset
1645
1644
1646 fm = ui.formatter('debugobsolete', opts)
1645 fm = ui.formatter('debugobsolete', opts)
1647 for i, m in enumerate(markerstoiter):
1646 for i, m in enumerate(markerstoiter):
1648 if not isrelevant(m):
1647 if not isrelevant(m):
1649 # marker can be irrelevant when we're iterating over a set
1648 # marker can be irrelevant when we're iterating over a set
1650 # of markers (markerstoiter) which is bigger than the set
1649 # of markers (markerstoiter) which is bigger than the set
1651 # of markers we want to display (markers)
1650 # of markers we want to display (markers)
1652 # this can happen if both --index and --rev options are
1651 # this can happen if both --index and --rev options are
1653 # provided and thus we need to iterate over all of the markers
1652 # provided and thus we need to iterate over all of the markers
1654 # to get the correct indices, but only display the ones that
1653 # to get the correct indices, but only display the ones that
1655 # are relevant to --rev value
1654 # are relevant to --rev value
1656 continue
1655 continue
1657 fm.startitem()
1656 fm.startitem()
1658 ind = i if opts.get('index') else None
1657 ind = i if opts.get('index') else None
1659 cmdutil.showmarker(fm, m, index=ind)
1658 cmdutil.showmarker(fm, m, index=ind)
1660 fm.end()
1659 fm.end()
1661
1660
1662 @command('debugpathcomplete',
1661 @command('debugpathcomplete',
1663 [('f', 'full', None, _('complete an entire path')),
1662 [('f', 'full', None, _('complete an entire path')),
1664 ('n', 'normal', None, _('show only normal files')),
1663 ('n', 'normal', None, _('show only normal files')),
1665 ('a', 'added', None, _('show only added files')),
1664 ('a', 'added', None, _('show only added files')),
1666 ('r', 'removed', None, _('show only removed files'))],
1665 ('r', 'removed', None, _('show only removed files'))],
1667 _('FILESPEC...'))
1666 _('FILESPEC...'))
1668 def debugpathcomplete(ui, repo, *specs, **opts):
1667 def debugpathcomplete(ui, repo, *specs, **opts):
1669 '''complete part or all of a tracked path
1668 '''complete part or all of a tracked path
1670
1669
1671 This command supports shells that offer path name completion. It
1670 This command supports shells that offer path name completion. It
1672 currently completes only files already known to the dirstate.
1671 currently completes only files already known to the dirstate.
1673
1672
1674 Completion extends only to the next path segment unless
1673 Completion extends only to the next path segment unless
1675 --full is specified, in which case entire paths are used.'''
1674 --full is specified, in which case entire paths are used.'''
1676
1675
1677 def complete(path, acceptable):
1676 def complete(path, acceptable):
1678 dirstate = repo.dirstate
1677 dirstate = repo.dirstate
1679 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1678 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1680 rootdir = repo.root + pycompat.ossep
1679 rootdir = repo.root + pycompat.ossep
1681 if spec != repo.root and not spec.startswith(rootdir):
1680 if spec != repo.root and not spec.startswith(rootdir):
1682 return [], []
1681 return [], []
1683 if os.path.isdir(spec):
1682 if os.path.isdir(spec):
1684 spec += '/'
1683 spec += '/'
1685 spec = spec[len(rootdir):]
1684 spec = spec[len(rootdir):]
1686 fixpaths = pycompat.ossep != '/'
1685 fixpaths = pycompat.ossep != '/'
1687 if fixpaths:
1686 if fixpaths:
1688 spec = spec.replace(pycompat.ossep, '/')
1687 spec = spec.replace(pycompat.ossep, '/')
1689 speclen = len(spec)
1688 speclen = len(spec)
1690 fullpaths = opts[r'full']
1689 fullpaths = opts[r'full']
1691 files, dirs = set(), set()
1690 files, dirs = set(), set()
1692 adddir, addfile = dirs.add, files.add
1691 adddir, addfile = dirs.add, files.add
1693 for f, st in dirstate.iteritems():
1692 for f, st in dirstate.iteritems():
1694 if f.startswith(spec) and st[0] in acceptable:
1693 if f.startswith(spec) and st[0] in acceptable:
1695 if fixpaths:
1694 if fixpaths:
1696 f = f.replace('/', pycompat.ossep)
1695 f = f.replace('/', pycompat.ossep)
1697 if fullpaths:
1696 if fullpaths:
1698 addfile(f)
1697 addfile(f)
1699 continue
1698 continue
1700 s = f.find(pycompat.ossep, speclen)
1699 s = f.find(pycompat.ossep, speclen)
1701 if s >= 0:
1700 if s >= 0:
1702 adddir(f[:s])
1701 adddir(f[:s])
1703 else:
1702 else:
1704 addfile(f)
1703 addfile(f)
1705 return files, dirs
1704 return files, dirs
1706
1705
1707 acceptable = ''
1706 acceptable = ''
1708 if opts[r'normal']:
1707 if opts[r'normal']:
1709 acceptable += 'nm'
1708 acceptable += 'nm'
1710 if opts[r'added']:
1709 if opts[r'added']:
1711 acceptable += 'a'
1710 acceptable += 'a'
1712 if opts[r'removed']:
1711 if opts[r'removed']:
1713 acceptable += 'r'
1712 acceptable += 'r'
1714 cwd = repo.getcwd()
1713 cwd = repo.getcwd()
1715 if not specs:
1714 if not specs:
1716 specs = ['.']
1715 specs = ['.']
1717
1716
1718 files, dirs = set(), set()
1717 files, dirs = set(), set()
1719 for spec in specs:
1718 for spec in specs:
1720 f, d = complete(spec, acceptable or 'nmar')
1719 f, d = complete(spec, acceptable or 'nmar')
1721 files.update(f)
1720 files.update(f)
1722 dirs.update(d)
1721 dirs.update(d)
1723 files.update(dirs)
1722 files.update(dirs)
1724 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1723 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1725 ui.write('\n')
1724 ui.write('\n')
1726
1725
1727 @command('debugpeer', [], _('PATH'), norepo=True)
1726 @command('debugpeer', [], _('PATH'), norepo=True)
1728 def debugpeer(ui, path):
1727 def debugpeer(ui, path):
1729 """establish a connection to a peer repository"""
1728 """establish a connection to a peer repository"""
1730 # Always enable peer request logging. Requires --debug to display
1729 # Always enable peer request logging. Requires --debug to display
1731 # though.
1730 # though.
1732 overrides = {
1731 overrides = {
1733 ('devel', 'debug.peer-request'): True,
1732 ('devel', 'debug.peer-request'): True,
1734 }
1733 }
1735
1734
1736 with ui.configoverride(overrides):
1735 with ui.configoverride(overrides):
1737 peer = hg.peer(ui, {}, path)
1736 peer = hg.peer(ui, {}, path)
1738
1737
1739 local = peer.local() is not None
1738 local = peer.local() is not None
1740 canpush = peer.canpush()
1739 canpush = peer.canpush()
1741
1740
1742 ui.write(_('url: %s\n') % peer.url())
1741 ui.write(_('url: %s\n') % peer.url())
1743 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1742 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1744 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1743 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1745
1744
1746 @command('debugpickmergetool',
1745 @command('debugpickmergetool',
1747 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1746 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1748 ('', 'changedelete', None, _('emulate merging change and delete')),
1747 ('', 'changedelete', None, _('emulate merging change and delete')),
1749 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1748 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1750 _('[PATTERN]...'),
1749 _('[PATTERN]...'),
1751 inferrepo=True)
1750 inferrepo=True)
1752 def debugpickmergetool(ui, repo, *pats, **opts):
1751 def debugpickmergetool(ui, repo, *pats, **opts):
1753 """examine which merge tool is chosen for specified file
1752 """examine which merge tool is chosen for specified file
1754
1753
1755 As described in :hg:`help merge-tools`, Mercurial examines
1754 As described in :hg:`help merge-tools`, Mercurial examines
1756 configurations below in this order to decide which merge tool is
1755 configurations below in this order to decide which merge tool is
1757 chosen for specified file.
1756 chosen for specified file.
1758
1757
1759 1. ``--tool`` option
1758 1. ``--tool`` option
1760 2. ``HGMERGE`` environment variable
1759 2. ``HGMERGE`` environment variable
1761 3. configurations in ``merge-patterns`` section
1760 3. configurations in ``merge-patterns`` section
1762 4. configuration of ``ui.merge``
1761 4. configuration of ``ui.merge``
1763 5. configurations in ``merge-tools`` section
1762 5. configurations in ``merge-tools`` section
1764 6. ``hgmerge`` tool (for historical reason only)
1763 6. ``hgmerge`` tool (for historical reason only)
1765 7. default tool for fallback (``:merge`` or ``:prompt``)
1764 7. default tool for fallback (``:merge`` or ``:prompt``)
1766
1765
1767 This command writes out examination result in the style below::
1766 This command writes out examination result in the style below::
1768
1767
1769 FILE = MERGETOOL
1768 FILE = MERGETOOL
1770
1769
1771 By default, all files known in the first parent context of the
1770 By default, all files known in the first parent context of the
1772 working directory are examined. Use file patterns and/or -I/-X
1771 working directory are examined. Use file patterns and/or -I/-X
1773 options to limit target files. -r/--rev is also useful to examine
1772 options to limit target files. -r/--rev is also useful to examine
1774 files in another context without actual updating to it.
1773 files in another context without actual updating to it.
1775
1774
1776 With --debug, this command shows warning messages while matching
1775 With --debug, this command shows warning messages while matching
1777 against ``merge-patterns`` and so on, too. It is recommended to
1776 against ``merge-patterns`` and so on, too. It is recommended to
1778 use this option with explicit file patterns and/or -I/-X options,
1777 use this option with explicit file patterns and/or -I/-X options,
1779 because this option increases amount of output per file according
1778 because this option increases amount of output per file according
1780 to configurations in hgrc.
1779 to configurations in hgrc.
1781
1780
1782 With -v/--verbose, this command shows configurations below at
1781 With -v/--verbose, this command shows configurations below at
1783 first (only if specified).
1782 first (only if specified).
1784
1783
1785 - ``--tool`` option
1784 - ``--tool`` option
1786 - ``HGMERGE`` environment variable
1785 - ``HGMERGE`` environment variable
1787 - configuration of ``ui.merge``
1786 - configuration of ``ui.merge``
1788
1787
1789 If merge tool is chosen before matching against
1788 If merge tool is chosen before matching against
1790 ``merge-patterns``, this command can't show any helpful
1789 ``merge-patterns``, this command can't show any helpful
1791 information, even with --debug. In such case, information above is
1790 information, even with --debug. In such case, information above is
1792 useful to know why a merge tool is chosen.
1791 useful to know why a merge tool is chosen.
1793 """
1792 """
1794 opts = pycompat.byteskwargs(opts)
1793 opts = pycompat.byteskwargs(opts)
1795 overrides = {}
1794 overrides = {}
1796 if opts['tool']:
1795 if opts['tool']:
1797 overrides[('ui', 'forcemerge')] = opts['tool']
1796 overrides[('ui', 'forcemerge')] = opts['tool']
1798 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1797 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1799
1798
1800 with ui.configoverride(overrides, 'debugmergepatterns'):
1799 with ui.configoverride(overrides, 'debugmergepatterns'):
1801 hgmerge = encoding.environ.get("HGMERGE")
1800 hgmerge = encoding.environ.get("HGMERGE")
1802 if hgmerge is not None:
1801 if hgmerge is not None:
1803 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1802 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1804 uimerge = ui.config("ui", "merge")
1803 uimerge = ui.config("ui", "merge")
1805 if uimerge:
1804 if uimerge:
1806 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1805 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1807
1806
1808 ctx = scmutil.revsingle(repo, opts.get('rev'))
1807 ctx = scmutil.revsingle(repo, opts.get('rev'))
1809 m = scmutil.match(ctx, pats, opts)
1808 m = scmutil.match(ctx, pats, opts)
1810 changedelete = opts['changedelete']
1809 changedelete = opts['changedelete']
1811 for path in ctx.walk(m):
1810 for path in ctx.walk(m):
1812 fctx = ctx[path]
1811 fctx = ctx[path]
1813 try:
1812 try:
1814 if not ui.debugflag:
1813 if not ui.debugflag:
1815 ui.pushbuffer(error=True)
1814 ui.pushbuffer(error=True)
1816 tool, toolpath = filemerge._picktool(repo, ui, path,
1815 tool, toolpath = filemerge._picktool(repo, ui, path,
1817 fctx.isbinary(),
1816 fctx.isbinary(),
1818 'l' in fctx.flags(),
1817 'l' in fctx.flags(),
1819 changedelete)
1818 changedelete)
1820 finally:
1819 finally:
1821 if not ui.debugflag:
1820 if not ui.debugflag:
1822 ui.popbuffer()
1821 ui.popbuffer()
1823 ui.write(('%s = %s\n') % (path, tool))
1822 ui.write(('%s = %s\n') % (path, tool))
1824
1823
1825 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1824 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1826 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1825 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1827 '''access the pushkey key/value protocol
1826 '''access the pushkey key/value protocol
1828
1827
1829 With two args, list the keys in the given namespace.
1828 With two args, list the keys in the given namespace.
1830
1829
1831 With five args, set a key to new if it currently is set to old.
1830 With five args, set a key to new if it currently is set to old.
1832 Reports success or failure.
1831 Reports success or failure.
1833 '''
1832 '''
1834
1833
1835 target = hg.peer(ui, {}, repopath)
1834 target = hg.peer(ui, {}, repopath)
1836 if keyinfo:
1835 if keyinfo:
1837 key, old, new = keyinfo
1836 key, old, new = keyinfo
1838 with target.commandexecutor() as e:
1837 with target.commandexecutor() as e:
1839 r = e.callcommand('pushkey', {
1838 r = e.callcommand('pushkey', {
1840 'namespace': namespace,
1839 'namespace': namespace,
1841 'key': key,
1840 'key': key,
1842 'old': old,
1841 'old': old,
1843 'new': new,
1842 'new': new,
1844 }).result()
1843 }).result()
1845
1844
1846 ui.status(pycompat.bytestr(r) + '\n')
1845 ui.status(pycompat.bytestr(r) + '\n')
1847 return not r
1846 return not r
1848 else:
1847 else:
1849 for k, v in sorted(target.listkeys(namespace).iteritems()):
1848 for k, v in sorted(target.listkeys(namespace).iteritems()):
1850 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1849 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1851 stringutil.escapestr(v)))
1850 stringutil.escapestr(v)))
1852
1851
1853 @command('debugpvec', [], _('A B'))
1852 @command('debugpvec', [], _('A B'))
1854 def debugpvec(ui, repo, a, b=None):
1853 def debugpvec(ui, repo, a, b=None):
1855 ca = scmutil.revsingle(repo, a)
1854 ca = scmutil.revsingle(repo, a)
1856 cb = scmutil.revsingle(repo, b)
1855 cb = scmutil.revsingle(repo, b)
1857 pa = pvec.ctxpvec(ca)
1856 pa = pvec.ctxpvec(ca)
1858 pb = pvec.ctxpvec(cb)
1857 pb = pvec.ctxpvec(cb)
1859 if pa == pb:
1858 if pa == pb:
1860 rel = "="
1859 rel = "="
1861 elif pa > pb:
1860 elif pa > pb:
1862 rel = ">"
1861 rel = ">"
1863 elif pa < pb:
1862 elif pa < pb:
1864 rel = "<"
1863 rel = "<"
1865 elif pa | pb:
1864 elif pa | pb:
1866 rel = "|"
1865 rel = "|"
1867 ui.write(_("a: %s\n") % pa)
1866 ui.write(_("a: %s\n") % pa)
1868 ui.write(_("b: %s\n") % pb)
1867 ui.write(_("b: %s\n") % pb)
1869 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1868 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1870 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1869 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1871 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1870 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1872 pa.distance(pb), rel))
1871 pa.distance(pb), rel))
1873
1872
1874 @command('debugrebuilddirstate|debugrebuildstate',
1873 @command('debugrebuilddirstate|debugrebuildstate',
1875 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1874 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1876 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1875 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1877 'the working copy parent')),
1876 'the working copy parent')),
1878 ],
1877 ],
1879 _('[-r REV]'))
1878 _('[-r REV]'))
1880 def debugrebuilddirstate(ui, repo, rev, **opts):
1879 def debugrebuilddirstate(ui, repo, rev, **opts):
1881 """rebuild the dirstate as it would look like for the given revision
1880 """rebuild the dirstate as it would look like for the given revision
1882
1881
1883 If no revision is specified the first current parent will be used.
1882 If no revision is specified the first current parent will be used.
1884
1883
1885 The dirstate will be set to the files of the given revision.
1884 The dirstate will be set to the files of the given revision.
1886 The actual working directory content or existing dirstate
1885 The actual working directory content or existing dirstate
1887 information such as adds or removes is not considered.
1886 information such as adds or removes is not considered.
1888
1887
1889 ``minimal`` will only rebuild the dirstate status for files that claim to be
1888 ``minimal`` will only rebuild the dirstate status for files that claim to be
1890 tracked but are not in the parent manifest, or that exist in the parent
1889 tracked but are not in the parent manifest, or that exist in the parent
1891 manifest but are not in the dirstate. It will not change adds, removes, or
1890 manifest but are not in the dirstate. It will not change adds, removes, or
1892 modified files that are in the working copy parent.
1891 modified files that are in the working copy parent.
1893
1892
1894 One use of this command is to make the next :hg:`status` invocation
1893 One use of this command is to make the next :hg:`status` invocation
1895 check the actual file content.
1894 check the actual file content.
1896 """
1895 """
1897 ctx = scmutil.revsingle(repo, rev)
1896 ctx = scmutil.revsingle(repo, rev)
1898 with repo.wlock():
1897 with repo.wlock():
1899 dirstate = repo.dirstate
1898 dirstate = repo.dirstate
1900 changedfiles = None
1899 changedfiles = None
1901 # See command doc for what minimal does.
1900 # See command doc for what minimal does.
1902 if opts.get(r'minimal'):
1901 if opts.get(r'minimal'):
1903 manifestfiles = set(ctx.manifest().keys())
1902 manifestfiles = set(ctx.manifest().keys())
1904 dirstatefiles = set(dirstate)
1903 dirstatefiles = set(dirstate)
1905 manifestonly = manifestfiles - dirstatefiles
1904 manifestonly = manifestfiles - dirstatefiles
1906 dsonly = dirstatefiles - manifestfiles
1905 dsonly = dirstatefiles - manifestfiles
1907 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1906 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1908 changedfiles = manifestonly | dsnotadded
1907 changedfiles = manifestonly | dsnotadded
1909
1908
1910 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1909 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1911
1910
1912 @command('debugrebuildfncache', [], '')
1911 @command('debugrebuildfncache', [], '')
1913 def debugrebuildfncache(ui, repo):
1912 def debugrebuildfncache(ui, repo):
1914 """rebuild the fncache file"""
1913 """rebuild the fncache file"""
1915 repair.rebuildfncache(ui, repo)
1914 repair.rebuildfncache(ui, repo)
1916
1915
1917 @command('debugrename',
1916 @command('debugrename',
1918 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1917 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1919 _('[-r REV] FILE'))
1918 _('[-r REV] FILE'))
1920 def debugrename(ui, repo, file1, *pats, **opts):
1919 def debugrename(ui, repo, file1, *pats, **opts):
1921 """dump rename information"""
1920 """dump rename information"""
1922
1921
1923 opts = pycompat.byteskwargs(opts)
1922 opts = pycompat.byteskwargs(opts)
1924 ctx = scmutil.revsingle(repo, opts.get('rev'))
1923 ctx = scmutil.revsingle(repo, opts.get('rev'))
1925 m = scmutil.match(ctx, (file1,) + pats, opts)
1924 m = scmutil.match(ctx, (file1,) + pats, opts)
1926 for abs in ctx.walk(m):
1925 for abs in ctx.walk(m):
1927 fctx = ctx[abs]
1926 fctx = ctx[abs]
1928 o = fctx.filelog().renamed(fctx.filenode())
1927 o = fctx.filelog().renamed(fctx.filenode())
1929 rel = m.rel(abs)
1928 rel = m.rel(abs)
1930 if o:
1929 if o:
1931 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1930 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1932 else:
1931 else:
1933 ui.write(_("%s not renamed\n") % rel)
1932 ui.write(_("%s not renamed\n") % rel)
1934
1933
1935 @command('debugrevlog', cmdutil.debugrevlogopts +
1934 @command('debugrevlog', cmdutil.debugrevlogopts +
1936 [('d', 'dump', False, _('dump index data'))],
1935 [('d', 'dump', False, _('dump index data'))],
1937 _('-c|-m|FILE'),
1936 _('-c|-m|FILE'),
1938 optionalrepo=True)
1937 optionalrepo=True)
1939 def debugrevlog(ui, repo, file_=None, **opts):
1938 def debugrevlog(ui, repo, file_=None, **opts):
1940 """show data and statistics about a revlog"""
1939 """show data and statistics about a revlog"""
1941 opts = pycompat.byteskwargs(opts)
1940 opts = pycompat.byteskwargs(opts)
1942 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1941 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1943
1942
1944 if opts.get("dump"):
1943 if opts.get("dump"):
1945 numrevs = len(r)
1944 numrevs = len(r)
1946 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1945 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1947 " rawsize totalsize compression heads chainlen\n"))
1946 " rawsize totalsize compression heads chainlen\n"))
1948 ts = 0
1947 ts = 0
1949 heads = set()
1948 heads = set()
1950
1949
1951 for rev in xrange(numrevs):
1950 for rev in xrange(numrevs):
1952 dbase = r.deltaparent(rev)
1951 dbase = r.deltaparent(rev)
1953 if dbase == -1:
1952 if dbase == -1:
1954 dbase = rev
1953 dbase = rev
1955 cbase = r.chainbase(rev)
1954 cbase = r.chainbase(rev)
1956 clen = r.chainlen(rev)
1955 clen = r.chainlen(rev)
1957 p1, p2 = r.parentrevs(rev)
1956 p1, p2 = r.parentrevs(rev)
1958 rs = r.rawsize(rev)
1957 rs = r.rawsize(rev)
1959 ts = ts + rs
1958 ts = ts + rs
1960 heads -= set(r.parentrevs(rev))
1959 heads -= set(r.parentrevs(rev))
1961 heads.add(rev)
1960 heads.add(rev)
1962 try:
1961 try:
1963 compression = ts / r.end(rev)
1962 compression = ts / r.end(rev)
1964 except ZeroDivisionError:
1963 except ZeroDivisionError:
1965 compression = 0
1964 compression = 0
1966 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1965 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1967 "%11d %5d %8d\n" %
1966 "%11d %5d %8d\n" %
1968 (rev, p1, p2, r.start(rev), r.end(rev),
1967 (rev, p1, p2, r.start(rev), r.end(rev),
1969 r.start(dbase), r.start(cbase),
1968 r.start(dbase), r.start(cbase),
1970 r.start(p1), r.start(p2),
1969 r.start(p1), r.start(p2),
1971 rs, ts, compression, len(heads), clen))
1970 rs, ts, compression, len(heads), clen))
1972 return 0
1971 return 0
1973
1972
1974 v = r.version
1973 v = r.version
1975 format = v & 0xFFFF
1974 format = v & 0xFFFF
1976 flags = []
1975 flags = []
1977 gdelta = False
1976 gdelta = False
1978 if v & revlog.FLAG_INLINE_DATA:
1977 if v & revlog.FLAG_INLINE_DATA:
1979 flags.append('inline')
1978 flags.append('inline')
1980 if v & revlog.FLAG_GENERALDELTA:
1979 if v & revlog.FLAG_GENERALDELTA:
1981 gdelta = True
1980 gdelta = True
1982 flags.append('generaldelta')
1981 flags.append('generaldelta')
1983 if not flags:
1982 if not flags:
1984 flags = ['(none)']
1983 flags = ['(none)']
1985
1984
1986 nummerges = 0
1985 nummerges = 0
1987 numfull = 0
1986 numfull = 0
1988 numprev = 0
1987 numprev = 0
1989 nump1 = 0
1988 nump1 = 0
1990 nump2 = 0
1989 nump2 = 0
1991 numother = 0
1990 numother = 0
1992 nump1prev = 0
1991 nump1prev = 0
1993 nump2prev = 0
1992 nump2prev = 0
1994 chainlengths = []
1993 chainlengths = []
1995 chainbases = []
1994 chainbases = []
1996 chainspans = []
1995 chainspans = []
1997
1996
1998 datasize = [None, 0, 0]
1997 datasize = [None, 0, 0]
1999 fullsize = [None, 0, 0]
1998 fullsize = [None, 0, 0]
2000 deltasize = [None, 0, 0]
1999 deltasize = [None, 0, 0]
2001 chunktypecounts = {}
2000 chunktypecounts = {}
2002 chunktypesizes = {}
2001 chunktypesizes = {}
2003
2002
2004 def addsize(size, l):
2003 def addsize(size, l):
2005 if l[0] is None or size < l[0]:
2004 if l[0] is None or size < l[0]:
2006 l[0] = size
2005 l[0] = size
2007 if size > l[1]:
2006 if size > l[1]:
2008 l[1] = size
2007 l[1] = size
2009 l[2] += size
2008 l[2] += size
2010
2009
2011 numrevs = len(r)
2010 numrevs = len(r)
2012 for rev in xrange(numrevs):
2011 for rev in xrange(numrevs):
2013 p1, p2 = r.parentrevs(rev)
2012 p1, p2 = r.parentrevs(rev)
2014 delta = r.deltaparent(rev)
2013 delta = r.deltaparent(rev)
2015 if format > 0:
2014 if format > 0:
2016 addsize(r.rawsize(rev), datasize)
2015 addsize(r.rawsize(rev), datasize)
2017 if p2 != nullrev:
2016 if p2 != nullrev:
2018 nummerges += 1
2017 nummerges += 1
2019 size = r.length(rev)
2018 size = r.length(rev)
2020 if delta == nullrev:
2019 if delta == nullrev:
2021 chainlengths.append(0)
2020 chainlengths.append(0)
2022 chainbases.append(r.start(rev))
2021 chainbases.append(r.start(rev))
2023 chainspans.append(size)
2022 chainspans.append(size)
2024 numfull += 1
2023 numfull += 1
2025 addsize(size, fullsize)
2024 addsize(size, fullsize)
2026 else:
2025 else:
2027 chainlengths.append(chainlengths[delta] + 1)
2026 chainlengths.append(chainlengths[delta] + 1)
2028 baseaddr = chainbases[delta]
2027 baseaddr = chainbases[delta]
2029 revaddr = r.start(rev)
2028 revaddr = r.start(rev)
2030 chainbases.append(baseaddr)
2029 chainbases.append(baseaddr)
2031 chainspans.append((revaddr - baseaddr) + size)
2030 chainspans.append((revaddr - baseaddr) + size)
2032 addsize(size, deltasize)
2031 addsize(size, deltasize)
2033 if delta == rev - 1:
2032 if delta == rev - 1:
2034 numprev += 1
2033 numprev += 1
2035 if delta == p1:
2034 if delta == p1:
2036 nump1prev += 1
2035 nump1prev += 1
2037 elif delta == p2:
2036 elif delta == p2:
2038 nump2prev += 1
2037 nump2prev += 1
2039 elif delta == p1:
2038 elif delta == p1:
2040 nump1 += 1
2039 nump1 += 1
2041 elif delta == p2:
2040 elif delta == p2:
2042 nump2 += 1
2041 nump2 += 1
2043 elif delta != nullrev:
2042 elif delta != nullrev:
2044 numother += 1
2043 numother += 1
2045
2044
2046 # Obtain data on the raw chunks in the revlog.
2045 # Obtain data on the raw chunks in the revlog.
2047 segment = r._getsegmentforrevs(rev, rev)[1]
2046 segment = r._getsegmentforrevs(rev, rev)[1]
2048 if segment:
2047 if segment:
2049 chunktype = bytes(segment[0:1])
2048 chunktype = bytes(segment[0:1])
2050 else:
2049 else:
2051 chunktype = 'empty'
2050 chunktype = 'empty'
2052
2051
2053 if chunktype not in chunktypecounts:
2052 if chunktype not in chunktypecounts:
2054 chunktypecounts[chunktype] = 0
2053 chunktypecounts[chunktype] = 0
2055 chunktypesizes[chunktype] = 0
2054 chunktypesizes[chunktype] = 0
2056
2055
2057 chunktypecounts[chunktype] += 1
2056 chunktypecounts[chunktype] += 1
2058 chunktypesizes[chunktype] += size
2057 chunktypesizes[chunktype] += size
2059
2058
2060 # Adjust size min value for empty cases
2059 # Adjust size min value for empty cases
2061 for size in (datasize, fullsize, deltasize):
2060 for size in (datasize, fullsize, deltasize):
2062 if size[0] is None:
2061 if size[0] is None:
2063 size[0] = 0
2062 size[0] = 0
2064
2063
2065 numdeltas = numrevs - numfull
2064 numdeltas = numrevs - numfull
2066 numoprev = numprev - nump1prev - nump2prev
2065 numoprev = numprev - nump1prev - nump2prev
2067 totalrawsize = datasize[2]
2066 totalrawsize = datasize[2]
2068 datasize[2] /= numrevs
2067 datasize[2] /= numrevs
2069 fulltotal = fullsize[2]
2068 fulltotal = fullsize[2]
2070 fullsize[2] /= numfull
2069 fullsize[2] /= numfull
2071 deltatotal = deltasize[2]
2070 deltatotal = deltasize[2]
2072 if numrevs - numfull > 0:
2071 if numrevs - numfull > 0:
2073 deltasize[2] /= numrevs - numfull
2072 deltasize[2] /= numrevs - numfull
2074 totalsize = fulltotal + deltatotal
2073 totalsize = fulltotal + deltatotal
2075 avgchainlen = sum(chainlengths) / numrevs
2074 avgchainlen = sum(chainlengths) / numrevs
2076 maxchainlen = max(chainlengths)
2075 maxchainlen = max(chainlengths)
2077 maxchainspan = max(chainspans)
2076 maxchainspan = max(chainspans)
2078 compratio = 1
2077 compratio = 1
2079 if totalsize:
2078 if totalsize:
2080 compratio = totalrawsize / totalsize
2079 compratio = totalrawsize / totalsize
2081
2080
2082 basedfmtstr = '%%%dd\n'
2081 basedfmtstr = '%%%dd\n'
2083 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2082 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2084
2083
2085 def dfmtstr(max):
2084 def dfmtstr(max):
2086 return basedfmtstr % len(str(max))
2085 return basedfmtstr % len(str(max))
2087 def pcfmtstr(max, padding=0):
2086 def pcfmtstr(max, padding=0):
2088 return basepcfmtstr % (len(str(max)), ' ' * padding)
2087 return basepcfmtstr % (len(str(max)), ' ' * padding)
2089
2088
2090 def pcfmt(value, total):
2089 def pcfmt(value, total):
2091 if total:
2090 if total:
2092 return (value, 100 * float(value) / total)
2091 return (value, 100 * float(value) / total)
2093 else:
2092 else:
2094 return value, 100.0
2093 return value, 100.0
2095
2094
2096 ui.write(('format : %d\n') % format)
2095 ui.write(('format : %d\n') % format)
2097 ui.write(('flags : %s\n') % ', '.join(flags))
2096 ui.write(('flags : %s\n') % ', '.join(flags))
2098
2097
2099 ui.write('\n')
2098 ui.write('\n')
2100 fmt = pcfmtstr(totalsize)
2099 fmt = pcfmtstr(totalsize)
2101 fmt2 = dfmtstr(totalsize)
2100 fmt2 = dfmtstr(totalsize)
2102 ui.write(('revisions : ') + fmt2 % numrevs)
2101 ui.write(('revisions : ') + fmt2 % numrevs)
2103 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2102 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2104 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2103 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2105 ui.write(('revisions : ') + fmt2 % numrevs)
2104 ui.write(('revisions : ') + fmt2 % numrevs)
2106 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2105 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2107 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2106 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2108 ui.write(('revision size : ') + fmt2 % totalsize)
2107 ui.write(('revision size : ') + fmt2 % totalsize)
2109 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2108 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2110 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2109 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2111
2110
2112 def fmtchunktype(chunktype):
2111 def fmtchunktype(chunktype):
2113 if chunktype == 'empty':
2112 if chunktype == 'empty':
2114 return ' %s : ' % chunktype
2113 return ' %s : ' % chunktype
2115 elif chunktype in pycompat.bytestr(string.ascii_letters):
2114 elif chunktype in pycompat.bytestr(string.ascii_letters):
2116 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2115 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2117 else:
2116 else:
2118 return ' 0x%s : ' % hex(chunktype)
2117 return ' 0x%s : ' % hex(chunktype)
2119
2118
2120 ui.write('\n')
2119 ui.write('\n')
2121 ui.write(('chunks : ') + fmt2 % numrevs)
2120 ui.write(('chunks : ') + fmt2 % numrevs)
2122 for chunktype in sorted(chunktypecounts):
2121 for chunktype in sorted(chunktypecounts):
2123 ui.write(fmtchunktype(chunktype))
2122 ui.write(fmtchunktype(chunktype))
2124 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2123 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2125 ui.write(('chunks size : ') + fmt2 % totalsize)
2124 ui.write(('chunks size : ') + fmt2 % totalsize)
2126 for chunktype in sorted(chunktypecounts):
2125 for chunktype in sorted(chunktypecounts):
2127 ui.write(fmtchunktype(chunktype))
2126 ui.write(fmtchunktype(chunktype))
2128 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2127 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2129
2128
2130 ui.write('\n')
2129 ui.write('\n')
2131 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2130 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2132 ui.write(('avg chain length : ') + fmt % avgchainlen)
2131 ui.write(('avg chain length : ') + fmt % avgchainlen)
2133 ui.write(('max chain length : ') + fmt % maxchainlen)
2132 ui.write(('max chain length : ') + fmt % maxchainlen)
2134 ui.write(('max chain reach : ') + fmt % maxchainspan)
2133 ui.write(('max chain reach : ') + fmt % maxchainspan)
2135 ui.write(('compression ratio : ') + fmt % compratio)
2134 ui.write(('compression ratio : ') + fmt % compratio)
2136
2135
2137 if format > 0:
2136 if format > 0:
2138 ui.write('\n')
2137 ui.write('\n')
2139 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2138 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2140 % tuple(datasize))
2139 % tuple(datasize))
2141 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2140 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2142 % tuple(fullsize))
2141 % tuple(fullsize))
2143 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2142 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2144 % tuple(deltasize))
2143 % tuple(deltasize))
2145
2144
2146 if numdeltas > 0:
2145 if numdeltas > 0:
2147 ui.write('\n')
2146 ui.write('\n')
2148 fmt = pcfmtstr(numdeltas)
2147 fmt = pcfmtstr(numdeltas)
2149 fmt2 = pcfmtstr(numdeltas, 4)
2148 fmt2 = pcfmtstr(numdeltas, 4)
2150 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2149 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2151 if numprev > 0:
2150 if numprev > 0:
2152 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2151 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2153 numprev))
2152 numprev))
2154 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2153 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2155 numprev))
2154 numprev))
2156 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2155 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2157 numprev))
2156 numprev))
2158 if gdelta:
2157 if gdelta:
2159 ui.write(('deltas against p1 : ')
2158 ui.write(('deltas against p1 : ')
2160 + fmt % pcfmt(nump1, numdeltas))
2159 + fmt % pcfmt(nump1, numdeltas))
2161 ui.write(('deltas against p2 : ')
2160 ui.write(('deltas against p2 : ')
2162 + fmt % pcfmt(nump2, numdeltas))
2161 + fmt % pcfmt(nump2, numdeltas))
2163 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2162 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2164 numdeltas))
2163 numdeltas))
2165
2164
2166 @command('debugrevspec',
2165 @command('debugrevspec',
2167 [('', 'optimize', None,
2166 [('', 'optimize', None,
2168 _('print parsed tree after optimizing (DEPRECATED)')),
2167 _('print parsed tree after optimizing (DEPRECATED)')),
2169 ('', 'show-revs', True, _('print list of result revisions (default)')),
2168 ('', 'show-revs', True, _('print list of result revisions (default)')),
2170 ('s', 'show-set', None, _('print internal representation of result set')),
2169 ('s', 'show-set', None, _('print internal representation of result set')),
2171 ('p', 'show-stage', [],
2170 ('p', 'show-stage', [],
2172 _('print parsed tree at the given stage'), _('NAME')),
2171 _('print parsed tree at the given stage'), _('NAME')),
2173 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2172 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2174 ('', 'verify-optimized', False, _('verify optimized result')),
2173 ('', 'verify-optimized', False, _('verify optimized result')),
2175 ],
2174 ],
2176 ('REVSPEC'))
2175 ('REVSPEC'))
2177 def debugrevspec(ui, repo, expr, **opts):
2176 def debugrevspec(ui, repo, expr, **opts):
2178 """parse and apply a revision specification
2177 """parse and apply a revision specification
2179
2178
2180 Use -p/--show-stage option to print the parsed tree at the given stages.
2179 Use -p/--show-stage option to print the parsed tree at the given stages.
2181 Use -p all to print tree at every stage.
2180 Use -p all to print tree at every stage.
2182
2181
2183 Use --no-show-revs option with -s or -p to print only the set
2182 Use --no-show-revs option with -s or -p to print only the set
2184 representation or the parsed tree respectively.
2183 representation or the parsed tree respectively.
2185
2184
2186 Use --verify-optimized to compare the optimized result with the unoptimized
2185 Use --verify-optimized to compare the optimized result with the unoptimized
2187 one. Returns 1 if the optimized result differs.
2186 one. Returns 1 if the optimized result differs.
2188 """
2187 """
2189 opts = pycompat.byteskwargs(opts)
2188 opts = pycompat.byteskwargs(opts)
2190 aliases = ui.configitems('revsetalias')
2189 aliases = ui.configitems('revsetalias')
2191 stages = [
2190 stages = [
2192 ('parsed', lambda tree: tree),
2191 ('parsed', lambda tree: tree),
2193 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2192 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2194 ui.warn)),
2193 ui.warn)),
2195 ('concatenated', revsetlang.foldconcat),
2194 ('concatenated', revsetlang.foldconcat),
2196 ('analyzed', revsetlang.analyze),
2195 ('analyzed', revsetlang.analyze),
2197 ('optimized', revsetlang.optimize),
2196 ('optimized', revsetlang.optimize),
2198 ]
2197 ]
2199 if opts['no_optimized']:
2198 if opts['no_optimized']:
2200 stages = stages[:-1]
2199 stages = stages[:-1]
2201 if opts['verify_optimized'] and opts['no_optimized']:
2200 if opts['verify_optimized'] and opts['no_optimized']:
2202 raise error.Abort(_('cannot use --verify-optimized with '
2201 raise error.Abort(_('cannot use --verify-optimized with '
2203 '--no-optimized'))
2202 '--no-optimized'))
2204 stagenames = set(n for n, f in stages)
2203 stagenames = set(n for n, f in stages)
2205
2204
2206 showalways = set()
2205 showalways = set()
2207 showchanged = set()
2206 showchanged = set()
2208 if ui.verbose and not opts['show_stage']:
2207 if ui.verbose and not opts['show_stage']:
2209 # show parsed tree by --verbose (deprecated)
2208 # show parsed tree by --verbose (deprecated)
2210 showalways.add('parsed')
2209 showalways.add('parsed')
2211 showchanged.update(['expanded', 'concatenated'])
2210 showchanged.update(['expanded', 'concatenated'])
2212 if opts['optimize']:
2211 if opts['optimize']:
2213 showalways.add('optimized')
2212 showalways.add('optimized')
2214 if opts['show_stage'] and opts['optimize']:
2213 if opts['show_stage'] and opts['optimize']:
2215 raise error.Abort(_('cannot use --optimize with --show-stage'))
2214 raise error.Abort(_('cannot use --optimize with --show-stage'))
2216 if opts['show_stage'] == ['all']:
2215 if opts['show_stage'] == ['all']:
2217 showalways.update(stagenames)
2216 showalways.update(stagenames)
2218 else:
2217 else:
2219 for n in opts['show_stage']:
2218 for n in opts['show_stage']:
2220 if n not in stagenames:
2219 if n not in stagenames:
2221 raise error.Abort(_('invalid stage name: %s') % n)
2220 raise error.Abort(_('invalid stage name: %s') % n)
2222 showalways.update(opts['show_stage'])
2221 showalways.update(opts['show_stage'])
2223
2222
2224 treebystage = {}
2223 treebystage = {}
2225 printedtree = None
2224 printedtree = None
2226 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2225 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2227 for n, f in stages:
2226 for n, f in stages:
2228 treebystage[n] = tree = f(tree)
2227 treebystage[n] = tree = f(tree)
2229 if n in showalways or (n in showchanged and tree != printedtree):
2228 if n in showalways or (n in showchanged and tree != printedtree):
2230 if opts['show_stage'] or n != 'parsed':
2229 if opts['show_stage'] or n != 'parsed':
2231 ui.write(("* %s:\n") % n)
2230 ui.write(("* %s:\n") % n)
2232 ui.write(revsetlang.prettyformat(tree), "\n")
2231 ui.write(revsetlang.prettyformat(tree), "\n")
2233 printedtree = tree
2232 printedtree = tree
2234
2233
2235 if opts['verify_optimized']:
2234 if opts['verify_optimized']:
2236 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2235 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2237 brevs = revset.makematcher(treebystage['optimized'])(repo)
2236 brevs = revset.makematcher(treebystage['optimized'])(repo)
2238 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2237 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2239 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2238 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2240 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2239 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2241 arevs = list(arevs)
2240 arevs = list(arevs)
2242 brevs = list(brevs)
2241 brevs = list(brevs)
2243 if arevs == brevs:
2242 if arevs == brevs:
2244 return 0
2243 return 0
2245 ui.write(('--- analyzed\n'), label='diff.file_a')
2244 ui.write(('--- analyzed\n'), label='diff.file_a')
2246 ui.write(('+++ optimized\n'), label='diff.file_b')
2245 ui.write(('+++ optimized\n'), label='diff.file_b')
2247 sm = difflib.SequenceMatcher(None, arevs, brevs)
2246 sm = difflib.SequenceMatcher(None, arevs, brevs)
2248 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2247 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2249 if tag in ('delete', 'replace'):
2248 if tag in ('delete', 'replace'):
2250 for c in arevs[alo:ahi]:
2249 for c in arevs[alo:ahi]:
2251 ui.write('-%s\n' % c, label='diff.deleted')
2250 ui.write('-%s\n' % c, label='diff.deleted')
2252 if tag in ('insert', 'replace'):
2251 if tag in ('insert', 'replace'):
2253 for c in brevs[blo:bhi]:
2252 for c in brevs[blo:bhi]:
2254 ui.write('+%s\n' % c, label='diff.inserted')
2253 ui.write('+%s\n' % c, label='diff.inserted')
2255 if tag == 'equal':
2254 if tag == 'equal':
2256 for c in arevs[alo:ahi]:
2255 for c in arevs[alo:ahi]:
2257 ui.write(' %s\n' % c)
2256 ui.write(' %s\n' % c)
2258 return 1
2257 return 1
2259
2258
2260 func = revset.makematcher(tree)
2259 func = revset.makematcher(tree)
2261 revs = func(repo)
2260 revs = func(repo)
2262 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2261 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2263 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2262 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2264 if not opts['show_revs']:
2263 if not opts['show_revs']:
2265 return
2264 return
2266 for c in revs:
2265 for c in revs:
2267 ui.write("%d\n" % c)
2266 ui.write("%d\n" % c)
2268
2267
2269 @command('debugserve', [
2268 @command('debugserve', [
2270 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2269 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2271 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2270 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2272 ('', 'logiofile', '', _('file to log server I/O to')),
2271 ('', 'logiofile', '', _('file to log server I/O to')),
2273 ], '')
2272 ], '')
2274 def debugserve(ui, repo, **opts):
2273 def debugserve(ui, repo, **opts):
2275 """run a server with advanced settings
2274 """run a server with advanced settings
2276
2275
2277 This command is similar to :hg:`serve`. It exists partially as a
2276 This command is similar to :hg:`serve`. It exists partially as a
2278 workaround to the fact that ``hg serve --stdio`` must have specific
2277 workaround to the fact that ``hg serve --stdio`` must have specific
2279 arguments for security reasons.
2278 arguments for security reasons.
2280 """
2279 """
2281 opts = pycompat.byteskwargs(opts)
2280 opts = pycompat.byteskwargs(opts)
2282
2281
2283 if not opts['sshstdio']:
2282 if not opts['sshstdio']:
2284 raise error.Abort(_('only --sshstdio is currently supported'))
2283 raise error.Abort(_('only --sshstdio is currently supported'))
2285
2284
2286 logfh = None
2285 logfh = None
2287
2286
2288 if opts['logiofd'] and opts['logiofile']:
2287 if opts['logiofd'] and opts['logiofile']:
2289 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2288 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2290
2289
2291 if opts['logiofd']:
2290 if opts['logiofd']:
2292 # Line buffered because output is line based.
2291 # Line buffered because output is line based.
2293 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2292 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2294 elif opts['logiofile']:
2293 elif opts['logiofile']:
2295 logfh = open(opts['logiofile'], 'ab', 1)
2294 logfh = open(opts['logiofile'], 'ab', 1)
2296
2295
2297 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2296 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2298 s.serve_forever()
2297 s.serve_forever()
2299
2298
2300 @command('debugsetparents', [], _('REV1 [REV2]'))
2299 @command('debugsetparents', [], _('REV1 [REV2]'))
2301 def debugsetparents(ui, repo, rev1, rev2=None):
2300 def debugsetparents(ui, repo, rev1, rev2=None):
2302 """manually set the parents of the current working directory
2301 """manually set the parents of the current working directory
2303
2302
2304 This is useful for writing repository conversion tools, but should
2303 This is useful for writing repository conversion tools, but should
2305 be used with care. For example, neither the working directory nor the
2304 be used with care. For example, neither the working directory nor the
2306 dirstate is updated, so file status may be incorrect after running this
2305 dirstate is updated, so file status may be incorrect after running this
2307 command.
2306 command.
2308
2307
2309 Returns 0 on success.
2308 Returns 0 on success.
2310 """
2309 """
2311
2310
2312 node1 = scmutil.revsingle(repo, rev1).node()
2311 node1 = scmutil.revsingle(repo, rev1).node()
2313 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2312 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2314
2313
2315 with repo.wlock():
2314 with repo.wlock():
2316 repo.setparents(node1, node2)
2315 repo.setparents(node1, node2)
2317
2316
2318 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2317 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2319 def debugssl(ui, repo, source=None, **opts):
2318 def debugssl(ui, repo, source=None, **opts):
2320 '''test a secure connection to a server
2319 '''test a secure connection to a server
2321
2320
2322 This builds the certificate chain for the server on Windows, installing the
2321 This builds the certificate chain for the server on Windows, installing the
2323 missing intermediates and trusted root via Windows Update if necessary. It
2322 missing intermediates and trusted root via Windows Update if necessary. It
2324 does nothing on other platforms.
2323 does nothing on other platforms.
2325
2324
2326 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2325 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2327 that server is used. See :hg:`help urls` for more information.
2326 that server is used. See :hg:`help urls` for more information.
2328
2327
2329 If the update succeeds, retry the original operation. Otherwise, the cause
2328 If the update succeeds, retry the original operation. Otherwise, the cause
2330 of the SSL error is likely another issue.
2329 of the SSL error is likely another issue.
2331 '''
2330 '''
2332 if not pycompat.iswindows:
2331 if not pycompat.iswindows:
2333 raise error.Abort(_('certificate chain building is only possible on '
2332 raise error.Abort(_('certificate chain building is only possible on '
2334 'Windows'))
2333 'Windows'))
2335
2334
2336 if not source:
2335 if not source:
2337 if not repo:
2336 if not repo:
2338 raise error.Abort(_("there is no Mercurial repository here, and no "
2337 raise error.Abort(_("there is no Mercurial repository here, and no "
2339 "server specified"))
2338 "server specified"))
2340 source = "default"
2339 source = "default"
2341
2340
2342 source, branches = hg.parseurl(ui.expandpath(source))
2341 source, branches = hg.parseurl(ui.expandpath(source))
2343 url = util.url(source)
2342 url = util.url(source)
2344 addr = None
2343 addr = None
2345
2344
2346 defaultport = {'https': 443, 'ssh': 22}
2345 defaultport = {'https': 443, 'ssh': 22}
2347 if url.scheme in defaultport:
2346 if url.scheme in defaultport:
2348 try:
2347 try:
2349 addr = (url.host, int(url.port or defaultport[url.scheme]))
2348 addr = (url.host, int(url.port or defaultport[url.scheme]))
2350 except ValueError:
2349 except ValueError:
2351 raise error.Abort(_("malformed port number in URL"))
2350 raise error.Abort(_("malformed port number in URL"))
2352 else:
2351 else:
2353 raise error.Abort(_("only https and ssh connections are supported"))
2352 raise error.Abort(_("only https and ssh connections are supported"))
2354
2353
2355 from . import win32
2354 from . import win32
2356
2355
2357 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2356 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2358 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2357 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2359
2358
2360 try:
2359 try:
2361 s.connect(addr)
2360 s.connect(addr)
2362 cert = s.getpeercert(True)
2361 cert = s.getpeercert(True)
2363
2362
2364 ui.status(_('checking the certificate chain for %s\n') % url.host)
2363 ui.status(_('checking the certificate chain for %s\n') % url.host)
2365
2364
2366 complete = win32.checkcertificatechain(cert, build=False)
2365 complete = win32.checkcertificatechain(cert, build=False)
2367
2366
2368 if not complete:
2367 if not complete:
2369 ui.status(_('certificate chain is incomplete, updating... '))
2368 ui.status(_('certificate chain is incomplete, updating... '))
2370
2369
2371 if not win32.checkcertificatechain(cert):
2370 if not win32.checkcertificatechain(cert):
2372 ui.status(_('failed.\n'))
2371 ui.status(_('failed.\n'))
2373 else:
2372 else:
2374 ui.status(_('done.\n'))
2373 ui.status(_('done.\n'))
2375 else:
2374 else:
2376 ui.status(_('full certificate chain is available\n'))
2375 ui.status(_('full certificate chain is available\n'))
2377 finally:
2376 finally:
2378 s.close()
2377 s.close()
2379
2378
2380 @command('debugsub',
2379 @command('debugsub',
2381 [('r', 'rev', '',
2380 [('r', 'rev', '',
2382 _('revision to check'), _('REV'))],
2381 _('revision to check'), _('REV'))],
2383 _('[-r REV] [REV]'))
2382 _('[-r REV] [REV]'))
2384 def debugsub(ui, repo, rev=None):
2383 def debugsub(ui, repo, rev=None):
2385 ctx = scmutil.revsingle(repo, rev, None)
2384 ctx = scmutil.revsingle(repo, rev, None)
2386 for k, v in sorted(ctx.substate.items()):
2385 for k, v in sorted(ctx.substate.items()):
2387 ui.write(('path %s\n') % k)
2386 ui.write(('path %s\n') % k)
2388 ui.write((' source %s\n') % v[0])
2387 ui.write((' source %s\n') % v[0])
2389 ui.write((' revision %s\n') % v[1])
2388 ui.write((' revision %s\n') % v[1])
2390
2389
2391 @command('debugsuccessorssets',
2390 @command('debugsuccessorssets',
2392 [('', 'closest', False, _('return closest successors sets only'))],
2391 [('', 'closest', False, _('return closest successors sets only'))],
2393 _('[REV]'))
2392 _('[REV]'))
2394 def debugsuccessorssets(ui, repo, *revs, **opts):
2393 def debugsuccessorssets(ui, repo, *revs, **opts):
2395 """show set of successors for revision
2394 """show set of successors for revision
2396
2395
2397 A successors set of changeset A is a consistent group of revisions that
2396 A successors set of changeset A is a consistent group of revisions that
2398 succeed A. It contains non-obsolete changesets only unless closests
2397 succeed A. It contains non-obsolete changesets only unless closests
2399 successors set is set.
2398 successors set is set.
2400
2399
2401 In most cases a changeset A has a single successors set containing a single
2400 In most cases a changeset A has a single successors set containing a single
2402 successor (changeset A replaced by A').
2401 successor (changeset A replaced by A').
2403
2402
2404 A changeset that is made obsolete with no successors are called "pruned".
2403 A changeset that is made obsolete with no successors are called "pruned".
2405 Such changesets have no successors sets at all.
2404 Such changesets have no successors sets at all.
2406
2405
2407 A changeset that has been "split" will have a successors set containing
2406 A changeset that has been "split" will have a successors set containing
2408 more than one successor.
2407 more than one successor.
2409
2408
2410 A changeset that has been rewritten in multiple different ways is called
2409 A changeset that has been rewritten in multiple different ways is called
2411 "divergent". Such changesets have multiple successor sets (each of which
2410 "divergent". Such changesets have multiple successor sets (each of which
2412 may also be split, i.e. have multiple successors).
2411 may also be split, i.e. have multiple successors).
2413
2412
2414 Results are displayed as follows::
2413 Results are displayed as follows::
2415
2414
2416 <rev1>
2415 <rev1>
2417 <successors-1A>
2416 <successors-1A>
2418 <rev2>
2417 <rev2>
2419 <successors-2A>
2418 <successors-2A>
2420 <successors-2B1> <successors-2B2> <successors-2B3>
2419 <successors-2B1> <successors-2B2> <successors-2B3>
2421
2420
2422 Here rev2 has two possible (i.e. divergent) successors sets. The first
2421 Here rev2 has two possible (i.e. divergent) successors sets. The first
2423 holds one element, whereas the second holds three (i.e. the changeset has
2422 holds one element, whereas the second holds three (i.e. the changeset has
2424 been split).
2423 been split).
2425 """
2424 """
2426 # passed to successorssets caching computation from one call to another
2425 # passed to successorssets caching computation from one call to another
2427 cache = {}
2426 cache = {}
2428 ctx2str = bytes
2427 ctx2str = bytes
2429 node2str = short
2428 node2str = short
2430 for rev in scmutil.revrange(repo, revs):
2429 for rev in scmutil.revrange(repo, revs):
2431 ctx = repo[rev]
2430 ctx = repo[rev]
2432 ui.write('%s\n'% ctx2str(ctx))
2431 ui.write('%s\n'% ctx2str(ctx))
2433 for succsset in obsutil.successorssets(repo, ctx.node(),
2432 for succsset in obsutil.successorssets(repo, ctx.node(),
2434 closest=opts[r'closest'],
2433 closest=opts[r'closest'],
2435 cache=cache):
2434 cache=cache):
2436 if succsset:
2435 if succsset:
2437 ui.write(' ')
2436 ui.write(' ')
2438 ui.write(node2str(succsset[0]))
2437 ui.write(node2str(succsset[0]))
2439 for node in succsset[1:]:
2438 for node in succsset[1:]:
2440 ui.write(' ')
2439 ui.write(' ')
2441 ui.write(node2str(node))
2440 ui.write(node2str(node))
2442 ui.write('\n')
2441 ui.write('\n')
2443
2442
2444 @command('debugtemplate',
2443 @command('debugtemplate',
2445 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2444 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2446 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2445 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2447 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2446 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2448 optionalrepo=True)
2447 optionalrepo=True)
2449 def debugtemplate(ui, repo, tmpl, **opts):
2448 def debugtemplate(ui, repo, tmpl, **opts):
2450 """parse and apply a template
2449 """parse and apply a template
2451
2450
2452 If -r/--rev is given, the template is processed as a log template and
2451 If -r/--rev is given, the template is processed as a log template and
2453 applied to the given changesets. Otherwise, it is processed as a generic
2452 applied to the given changesets. Otherwise, it is processed as a generic
2454 template.
2453 template.
2455
2454
2456 Use --verbose to print the parsed tree.
2455 Use --verbose to print the parsed tree.
2457 """
2456 """
2458 revs = None
2457 revs = None
2459 if opts[r'rev']:
2458 if opts[r'rev']:
2460 if repo is None:
2459 if repo is None:
2461 raise error.RepoError(_('there is no Mercurial repository here '
2460 raise error.RepoError(_('there is no Mercurial repository here '
2462 '(.hg not found)'))
2461 '(.hg not found)'))
2463 revs = scmutil.revrange(repo, opts[r'rev'])
2462 revs = scmutil.revrange(repo, opts[r'rev'])
2464
2463
2465 props = {}
2464 props = {}
2466 for d in opts[r'define']:
2465 for d in opts[r'define']:
2467 try:
2466 try:
2468 k, v = (e.strip() for e in d.split('=', 1))
2467 k, v = (e.strip() for e in d.split('=', 1))
2469 if not k or k == 'ui':
2468 if not k or k == 'ui':
2470 raise ValueError
2469 raise ValueError
2471 props[k] = v
2470 props[k] = v
2472 except ValueError:
2471 except ValueError:
2473 raise error.Abort(_('malformed keyword definition: %s') % d)
2472 raise error.Abort(_('malformed keyword definition: %s') % d)
2474
2473
2475 if ui.verbose:
2474 if ui.verbose:
2476 aliases = ui.configitems('templatealias')
2475 aliases = ui.configitems('templatealias')
2477 tree = templater.parse(tmpl)
2476 tree = templater.parse(tmpl)
2478 ui.note(templater.prettyformat(tree), '\n')
2477 ui.note(templater.prettyformat(tree), '\n')
2479 newtree = templater.expandaliases(tree, aliases)
2478 newtree = templater.expandaliases(tree, aliases)
2480 if newtree != tree:
2479 if newtree != tree:
2481 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2480 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2482
2481
2483 if revs is None:
2482 if revs is None:
2484 tres = formatter.templateresources(ui, repo)
2483 tres = formatter.templateresources(ui, repo)
2485 t = formatter.maketemplater(ui, tmpl, resources=tres)
2484 t = formatter.maketemplater(ui, tmpl, resources=tres)
2486 ui.write(t.renderdefault(props))
2485 ui.write(t.renderdefault(props))
2487 else:
2486 else:
2488 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2487 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2489 for r in revs:
2488 for r in revs:
2490 displayer.show(repo[r], **pycompat.strkwargs(props))
2489 displayer.show(repo[r], **pycompat.strkwargs(props))
2491 displayer.close()
2490 displayer.close()
2492
2491
2493 @command('debuguigetpass', [
2492 @command('debuguigetpass', [
2494 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2493 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2495 ], _('[-p TEXT]'), norepo=True)
2494 ], _('[-p TEXT]'), norepo=True)
2496 def debuguigetpass(ui, prompt=''):
2495 def debuguigetpass(ui, prompt=''):
2497 """show prompt to type password"""
2496 """show prompt to type password"""
2498 r = ui.getpass(prompt)
2497 r = ui.getpass(prompt)
2499 ui.write(('respose: %s\n') % r)
2498 ui.write(('respose: %s\n') % r)
2500
2499
2501 @command('debuguiprompt', [
2500 @command('debuguiprompt', [
2502 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2501 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2503 ], _('[-p TEXT]'), norepo=True)
2502 ], _('[-p TEXT]'), norepo=True)
2504 def debuguiprompt(ui, prompt=''):
2503 def debuguiprompt(ui, prompt=''):
2505 """show plain prompt"""
2504 """show plain prompt"""
2506 r = ui.prompt(prompt)
2505 r = ui.prompt(prompt)
2507 ui.write(('response: %s\n') % r)
2506 ui.write(('response: %s\n') % r)
2508
2507
2509 @command('debugupdatecaches', [])
2508 @command('debugupdatecaches', [])
2510 def debugupdatecaches(ui, repo, *pats, **opts):
2509 def debugupdatecaches(ui, repo, *pats, **opts):
2511 """warm all known caches in the repository"""
2510 """warm all known caches in the repository"""
2512 with repo.wlock(), repo.lock():
2511 with repo.wlock(), repo.lock():
2513 repo.updatecaches(full=True)
2512 repo.updatecaches(full=True)
2514
2513
2515 @command('debugupgraderepo', [
2514 @command('debugupgraderepo', [
2516 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2515 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2517 ('', 'run', False, _('performs an upgrade')),
2516 ('', 'run', False, _('performs an upgrade')),
2518 ])
2517 ])
2519 def debugupgraderepo(ui, repo, run=False, optimize=None):
2518 def debugupgraderepo(ui, repo, run=False, optimize=None):
2520 """upgrade a repository to use different features
2519 """upgrade a repository to use different features
2521
2520
2522 If no arguments are specified, the repository is evaluated for upgrade
2521 If no arguments are specified, the repository is evaluated for upgrade
2523 and a list of problems and potential optimizations is printed.
2522 and a list of problems and potential optimizations is printed.
2524
2523
2525 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2524 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2526 can be influenced via additional arguments. More details will be provided
2525 can be influenced via additional arguments. More details will be provided
2527 by the command output when run without ``--run``.
2526 by the command output when run without ``--run``.
2528
2527
2529 During the upgrade, the repository will be locked and no writes will be
2528 During the upgrade, the repository will be locked and no writes will be
2530 allowed.
2529 allowed.
2531
2530
2532 At the end of the upgrade, the repository may not be readable while new
2531 At the end of the upgrade, the repository may not be readable while new
2533 repository data is swapped in. This window will be as long as it takes to
2532 repository data is swapped in. This window will be as long as it takes to
2534 rename some directories inside the ``.hg`` directory. On most machines, this
2533 rename some directories inside the ``.hg`` directory. On most machines, this
2535 should complete almost instantaneously and the chances of a consumer being
2534 should complete almost instantaneously and the chances of a consumer being
2536 unable to access the repository should be low.
2535 unable to access the repository should be low.
2537 """
2536 """
2538 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2537 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2539
2538
2540 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2539 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2541 inferrepo=True)
2540 inferrepo=True)
2542 def debugwalk(ui, repo, *pats, **opts):
2541 def debugwalk(ui, repo, *pats, **opts):
2543 """show how files match on given patterns"""
2542 """show how files match on given patterns"""
2544 opts = pycompat.byteskwargs(opts)
2543 opts = pycompat.byteskwargs(opts)
2545 m = scmutil.match(repo[None], pats, opts)
2544 m = scmutil.match(repo[None], pats, opts)
2546 ui.write(('matcher: %r\n' % m))
2545 ui.write(('matcher: %r\n' % m))
2547 items = list(repo[None].walk(m))
2546 items = list(repo[None].walk(m))
2548 if not items:
2547 if not items:
2549 return
2548 return
2550 f = lambda fn: fn
2549 f = lambda fn: fn
2551 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2550 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2552 f = lambda fn: util.normpath(fn)
2551 f = lambda fn: util.normpath(fn)
2553 fmt = 'f %%-%ds %%-%ds %%s' % (
2552 fmt = 'f %%-%ds %%-%ds %%s' % (
2554 max([len(abs) for abs in items]),
2553 max([len(abs) for abs in items]),
2555 max([len(m.rel(abs)) for abs in items]))
2554 max([len(m.rel(abs)) for abs in items]))
2556 for abs in items:
2555 for abs in items:
2557 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2556 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2558 ui.write("%s\n" % line.rstrip())
2557 ui.write("%s\n" % line.rstrip())
2559
2558
2560 @command('debugwhyunstable', [], _('REV'))
2559 @command('debugwhyunstable', [], _('REV'))
2561 def debugwhyunstable(ui, repo, rev):
2560 def debugwhyunstable(ui, repo, rev):
2562 """explain instabilities of a changeset"""
2561 """explain instabilities of a changeset"""
2563 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2562 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2564 dnodes = ''
2563 dnodes = ''
2565 if entry.get('divergentnodes'):
2564 if entry.get('divergentnodes'):
2566 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2565 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2567 for ctx in entry['divergentnodes']) + ' '
2566 for ctx in entry['divergentnodes']) + ' '
2568 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2567 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2569 entry['reason'], entry['node']))
2568 entry['reason'], entry['node']))
2570
2569
2571 @command('debugwireargs',
2570 @command('debugwireargs',
2572 [('', 'three', '', 'three'),
2571 [('', 'three', '', 'three'),
2573 ('', 'four', '', 'four'),
2572 ('', 'four', '', 'four'),
2574 ('', 'five', '', 'five'),
2573 ('', 'five', '', 'five'),
2575 ] + cmdutil.remoteopts,
2574 ] + cmdutil.remoteopts,
2576 _('REPO [OPTIONS]... [ONE [TWO]]'),
2575 _('REPO [OPTIONS]... [ONE [TWO]]'),
2577 norepo=True)
2576 norepo=True)
2578 def debugwireargs(ui, repopath, *vals, **opts):
2577 def debugwireargs(ui, repopath, *vals, **opts):
2579 opts = pycompat.byteskwargs(opts)
2578 opts = pycompat.byteskwargs(opts)
2580 repo = hg.peer(ui, opts, repopath)
2579 repo = hg.peer(ui, opts, repopath)
2581 for opt in cmdutil.remoteopts:
2580 for opt in cmdutil.remoteopts:
2582 del opts[opt[1]]
2581 del opts[opt[1]]
2583 args = {}
2582 args = {}
2584 for k, v in opts.iteritems():
2583 for k, v in opts.iteritems():
2585 if v:
2584 if v:
2586 args[k] = v
2585 args[k] = v
2587 args = pycompat.strkwargs(args)
2586 args = pycompat.strkwargs(args)
2588 # run twice to check that we don't mess up the stream for the next command
2587 # run twice to check that we don't mess up the stream for the next command
2589 res1 = repo.debugwireargs(*vals, **args)
2588 res1 = repo.debugwireargs(*vals, **args)
2590 res2 = repo.debugwireargs(*vals, **args)
2589 res2 = repo.debugwireargs(*vals, **args)
2591 ui.write("%s\n" % res1)
2590 ui.write("%s\n" % res1)
2592 if res1 != res2:
2591 if res1 != res2:
2593 ui.warn("%s\n" % res2)
2592 ui.warn("%s\n" % res2)
2594
2593
2595 def _parsewirelangblocks(fh):
2594 def _parsewirelangblocks(fh):
2596 activeaction = None
2595 activeaction = None
2597 blocklines = []
2596 blocklines = []
2598
2597
2599 for line in fh:
2598 for line in fh:
2600 line = line.rstrip()
2599 line = line.rstrip()
2601 if not line:
2600 if not line:
2602 continue
2601 continue
2603
2602
2604 if line.startswith(b'#'):
2603 if line.startswith(b'#'):
2605 continue
2604 continue
2606
2605
2607 if not line.startswith(' '):
2606 if not line.startswith(' '):
2608 # New block. Flush previous one.
2607 # New block. Flush previous one.
2609 if activeaction:
2608 if activeaction:
2610 yield activeaction, blocklines
2609 yield activeaction, blocklines
2611
2610
2612 activeaction = line
2611 activeaction = line
2613 blocklines = []
2612 blocklines = []
2614 continue
2613 continue
2615
2614
2616 # Else we start with an indent.
2615 # Else we start with an indent.
2617
2616
2618 if not activeaction:
2617 if not activeaction:
2619 raise error.Abort(_('indented line outside of block'))
2618 raise error.Abort(_('indented line outside of block'))
2620
2619
2621 blocklines.append(line)
2620 blocklines.append(line)
2622
2621
2623 # Flush last block.
2622 # Flush last block.
2624 if activeaction:
2623 if activeaction:
2625 yield activeaction, blocklines
2624 yield activeaction, blocklines
2626
2625
2627 @command('debugwireproto',
2626 @command('debugwireproto',
2628 [
2627 [
2629 ('', 'localssh', False, _('start an SSH server for this repo')),
2628 ('', 'localssh', False, _('start an SSH server for this repo')),
2630 ('', 'peer', '', _('construct a specific version of the peer')),
2629 ('', 'peer', '', _('construct a specific version of the peer')),
2631 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2630 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2632 ('', 'nologhandshake', False,
2631 ('', 'nologhandshake', False,
2633 _('do not log I/O related to the peer handshake')),
2632 _('do not log I/O related to the peer handshake')),
2634 ] + cmdutil.remoteopts,
2633 ] + cmdutil.remoteopts,
2635 _('[PATH]'),
2634 _('[PATH]'),
2636 optionalrepo=True)
2635 optionalrepo=True)
2637 def debugwireproto(ui, repo, path=None, **opts):
2636 def debugwireproto(ui, repo, path=None, **opts):
2638 """send wire protocol commands to a server
2637 """send wire protocol commands to a server
2639
2638
2640 This command can be used to issue wire protocol commands to remote
2639 This command can be used to issue wire protocol commands to remote
2641 peers and to debug the raw data being exchanged.
2640 peers and to debug the raw data being exchanged.
2642
2641
2643 ``--localssh`` will start an SSH server against the current repository
2642 ``--localssh`` will start an SSH server against the current repository
2644 and connect to that. By default, the connection will perform a handshake
2643 and connect to that. By default, the connection will perform a handshake
2645 and establish an appropriate peer instance.
2644 and establish an appropriate peer instance.
2646
2645
2647 ``--peer`` can be used to bypass the handshake protocol and construct a
2646 ``--peer`` can be used to bypass the handshake protocol and construct a
2648 peer instance using the specified class type. Valid values are ``raw``,
2647 peer instance using the specified class type. Valid values are ``raw``,
2649 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2648 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2650 raw data payloads and don't support higher-level command actions.
2649 raw data payloads and don't support higher-level command actions.
2651
2650
2652 ``--noreadstderr`` can be used to disable automatic reading from stderr
2651 ``--noreadstderr`` can be used to disable automatic reading from stderr
2653 of the peer (for SSH connections only). Disabling automatic reading of
2652 of the peer (for SSH connections only). Disabling automatic reading of
2654 stderr is useful for making output more deterministic.
2653 stderr is useful for making output more deterministic.
2655
2654
2656 Commands are issued via a mini language which is specified via stdin.
2655 Commands are issued via a mini language which is specified via stdin.
2657 The language consists of individual actions to perform. An action is
2656 The language consists of individual actions to perform. An action is
2658 defined by a block. A block is defined as a line with no leading
2657 defined by a block. A block is defined as a line with no leading
2659 space followed by 0 or more lines with leading space. Blocks are
2658 space followed by 0 or more lines with leading space. Blocks are
2660 effectively a high-level command with additional metadata.
2659 effectively a high-level command with additional metadata.
2661
2660
2662 Lines beginning with ``#`` are ignored.
2661 Lines beginning with ``#`` are ignored.
2663
2662
2664 The following sections denote available actions.
2663 The following sections denote available actions.
2665
2664
2666 raw
2665 raw
2667 ---
2666 ---
2668
2667
2669 Send raw data to the server.
2668 Send raw data to the server.
2670
2669
2671 The block payload contains the raw data to send as one atomic send
2670 The block payload contains the raw data to send as one atomic send
2672 operation. The data may not actually be delivered in a single system
2671 operation. The data may not actually be delivered in a single system
2673 call: it depends on the abilities of the transport being used.
2672 call: it depends on the abilities of the transport being used.
2674
2673
2675 Each line in the block is de-indented and concatenated. Then, that
2674 Each line in the block is de-indented and concatenated. Then, that
2676 value is evaluated as a Python b'' literal. This allows the use of
2675 value is evaluated as a Python b'' literal. This allows the use of
2677 backslash escaping, etc.
2676 backslash escaping, etc.
2678
2677
2679 raw+
2678 raw+
2680 ----
2679 ----
2681
2680
2682 Behaves like ``raw`` except flushes output afterwards.
2681 Behaves like ``raw`` except flushes output afterwards.
2683
2682
2684 command <X>
2683 command <X>
2685 -----------
2684 -----------
2686
2685
2687 Send a request to run a named command, whose name follows the ``command``
2686 Send a request to run a named command, whose name follows the ``command``
2688 string.
2687 string.
2689
2688
2690 Arguments to the command are defined as lines in this block. The format of
2689 Arguments to the command are defined as lines in this block. The format of
2691 each line is ``<key> <value>``. e.g.::
2690 each line is ``<key> <value>``. e.g.::
2692
2691
2693 command listkeys
2692 command listkeys
2694 namespace bookmarks
2693 namespace bookmarks
2695
2694
2696 If the value begins with ``eval:``, it will be interpreted as a Python
2695 If the value begins with ``eval:``, it will be interpreted as a Python
2697 literal expression. Otherwise values are interpreted as Python b'' literals.
2696 literal expression. Otherwise values are interpreted as Python b'' literals.
2698 This allows sending complex types and encoding special byte sequences via
2697 This allows sending complex types and encoding special byte sequences via
2699 backslash escaping.
2698 backslash escaping.
2700
2699
2701 The following arguments have special meaning:
2700 The following arguments have special meaning:
2702
2701
2703 ``PUSHFILE``
2702 ``PUSHFILE``
2704 When defined, the *push* mechanism of the peer will be used instead
2703 When defined, the *push* mechanism of the peer will be used instead
2705 of the static request-response mechanism and the content of the
2704 of the static request-response mechanism and the content of the
2706 file specified in the value of this argument will be sent as the
2705 file specified in the value of this argument will be sent as the
2707 command payload.
2706 command payload.
2708
2707
2709 This can be used to submit a local bundle file to the remote.
2708 This can be used to submit a local bundle file to the remote.
2710
2709
2711 batchbegin
2710 batchbegin
2712 ----------
2711 ----------
2713
2712
2714 Instruct the peer to begin a batched send.
2713 Instruct the peer to begin a batched send.
2715
2714
2716 All ``command`` blocks are queued for execution until the next
2715 All ``command`` blocks are queued for execution until the next
2717 ``batchsubmit`` block.
2716 ``batchsubmit`` block.
2718
2717
2719 batchsubmit
2718 batchsubmit
2720 -----------
2719 -----------
2721
2720
2722 Submit previously queued ``command`` blocks as a batch request.
2721 Submit previously queued ``command`` blocks as a batch request.
2723
2722
2724 This action MUST be paired with a ``batchbegin`` action.
2723 This action MUST be paired with a ``batchbegin`` action.
2725
2724
2726 httprequest <method> <path>
2725 httprequest <method> <path>
2727 ---------------------------
2726 ---------------------------
2728
2727
2729 (HTTP peer only)
2728 (HTTP peer only)
2730
2729
2731 Send an HTTP request to the peer.
2730 Send an HTTP request to the peer.
2732
2731
2733 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2732 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2734
2733
2735 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2734 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2736 headers to add to the request. e.g. ``Accept: foo``.
2735 headers to add to the request. e.g. ``Accept: foo``.
2737
2736
2738 The following arguments are special:
2737 The following arguments are special:
2739
2738
2740 ``BODYFILE``
2739 ``BODYFILE``
2741 The content of the file defined as the value to this argument will be
2740 The content of the file defined as the value to this argument will be
2742 transferred verbatim as the HTTP request body.
2741 transferred verbatim as the HTTP request body.
2743
2742
2744 ``frame <type> <flags> <payload>``
2743 ``frame <type> <flags> <payload>``
2745 Send a unified protocol frame as part of the request body.
2744 Send a unified protocol frame as part of the request body.
2746
2745
2747 All frames will be collected and sent as the body to the HTTP
2746 All frames will be collected and sent as the body to the HTTP
2748 request.
2747 request.
2749
2748
2750 close
2749 close
2751 -----
2750 -----
2752
2751
2753 Close the connection to the server.
2752 Close the connection to the server.
2754
2753
2755 flush
2754 flush
2756 -----
2755 -----
2757
2756
2758 Flush data written to the server.
2757 Flush data written to the server.
2759
2758
2760 readavailable
2759 readavailable
2761 -------------
2760 -------------
2762
2761
2763 Close the write end of the connection and read all available data from
2762 Close the write end of the connection and read all available data from
2764 the server.
2763 the server.
2765
2764
2766 If the connection to the server encompasses multiple pipes, we poll both
2765 If the connection to the server encompasses multiple pipes, we poll both
2767 pipes and read available data.
2766 pipes and read available data.
2768
2767
2769 readline
2768 readline
2770 --------
2769 --------
2771
2770
2772 Read a line of output from the server. If there are multiple output
2771 Read a line of output from the server. If there are multiple output
2773 pipes, reads only the main pipe.
2772 pipes, reads only the main pipe.
2774
2773
2775 ereadline
2774 ereadline
2776 ---------
2775 ---------
2777
2776
2778 Like ``readline``, but read from the stderr pipe, if available.
2777 Like ``readline``, but read from the stderr pipe, if available.
2779
2778
2780 read <X>
2779 read <X>
2781 --------
2780 --------
2782
2781
2783 ``read()`` N bytes from the server's main output pipe.
2782 ``read()`` N bytes from the server's main output pipe.
2784
2783
2785 eread <X>
2784 eread <X>
2786 ---------
2785 ---------
2787
2786
2788 ``read()`` N bytes from the server's stderr pipe, if available.
2787 ``read()`` N bytes from the server's stderr pipe, if available.
2789
2788
2790 Specifying Unified Frame-Based Protocol Frames
2789 Specifying Unified Frame-Based Protocol Frames
2791 ----------------------------------------------
2790 ----------------------------------------------
2792
2791
2793 It is possible to emit a *Unified Frame-Based Protocol* by using special
2792 It is possible to emit a *Unified Frame-Based Protocol* by using special
2794 syntax.
2793 syntax.
2795
2794
2796 A frame is composed as a type, flags, and payload. These can be parsed
2795 A frame is composed as a type, flags, and payload. These can be parsed
2797 from a string of the form:
2796 from a string of the form:
2798
2797
2799 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2798 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2800
2799
2801 ``request-id`` and ``stream-id`` are integers defining the request and
2800 ``request-id`` and ``stream-id`` are integers defining the request and
2802 stream identifiers.
2801 stream identifiers.
2803
2802
2804 ``type`` can be an integer value for the frame type or the string name
2803 ``type`` can be an integer value for the frame type or the string name
2805 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2804 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2806 ``command-name``.
2805 ``command-name``.
2807
2806
2808 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2807 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2809 components. Each component (and there can be just one) can be an integer
2808 components. Each component (and there can be just one) can be an integer
2810 or a flag name for stream flags or frame flags, respectively. Values are
2809 or a flag name for stream flags or frame flags, respectively. Values are
2811 resolved to integers and then bitwise OR'd together.
2810 resolved to integers and then bitwise OR'd together.
2812
2811
2813 ``payload`` represents the raw frame payload. If it begins with
2812 ``payload`` represents the raw frame payload. If it begins with
2814 ``cbor:``, the following string is evaluated as Python code and the
2813 ``cbor:``, the following string is evaluated as Python code and the
2815 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2814 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2816 as a Python byte string literal.
2815 as a Python byte string literal.
2817 """
2816 """
2818 opts = pycompat.byteskwargs(opts)
2817 opts = pycompat.byteskwargs(opts)
2819
2818
2820 if opts['localssh'] and not repo:
2819 if opts['localssh'] and not repo:
2821 raise error.Abort(_('--localssh requires a repository'))
2820 raise error.Abort(_('--localssh requires a repository'))
2822
2821
2823 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2822 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2824 raise error.Abort(_('invalid value for --peer'),
2823 raise error.Abort(_('invalid value for --peer'),
2825 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2824 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2826
2825
2827 if path and opts['localssh']:
2826 if path and opts['localssh']:
2828 raise error.Abort(_('cannot specify --localssh with an explicit '
2827 raise error.Abort(_('cannot specify --localssh with an explicit '
2829 'path'))
2828 'path'))
2830
2829
2831 if ui.interactive():
2830 if ui.interactive():
2832 ui.write(_('(waiting for commands on stdin)\n'))
2831 ui.write(_('(waiting for commands on stdin)\n'))
2833
2832
2834 blocks = list(_parsewirelangblocks(ui.fin))
2833 blocks = list(_parsewirelangblocks(ui.fin))
2835
2834
2836 proc = None
2835 proc = None
2837 stdin = None
2836 stdin = None
2838 stdout = None
2837 stdout = None
2839 stderr = None
2838 stderr = None
2840 opener = None
2839 opener = None
2841
2840
2842 if opts['localssh']:
2841 if opts['localssh']:
2843 # We start the SSH server in its own process so there is process
2842 # We start the SSH server in its own process so there is process
2844 # separation. This prevents a whole class of potential bugs around
2843 # separation. This prevents a whole class of potential bugs around
2845 # shared state from interfering with server operation.
2844 # shared state from interfering with server operation.
2846 args = procutil.hgcmd() + [
2845 args = procutil.hgcmd() + [
2847 '-R', repo.root,
2846 '-R', repo.root,
2848 'debugserve', '--sshstdio',
2847 'debugserve', '--sshstdio',
2849 ]
2848 ]
2850 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2849 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2851 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2850 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2852 bufsize=0)
2851 bufsize=0)
2853
2852
2854 stdin = proc.stdin
2853 stdin = proc.stdin
2855 stdout = proc.stdout
2854 stdout = proc.stdout
2856 stderr = proc.stderr
2855 stderr = proc.stderr
2857
2856
2858 # We turn the pipes into observers so we can log I/O.
2857 # We turn the pipes into observers so we can log I/O.
2859 if ui.verbose or opts['peer'] == 'raw':
2858 if ui.verbose or opts['peer'] == 'raw':
2860 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2859 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2861 logdata=True)
2860 logdata=True)
2862 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2861 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2863 logdata=True)
2862 logdata=True)
2864 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2863 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2865 logdata=True)
2864 logdata=True)
2866
2865
2867 # --localssh also implies the peer connection settings.
2866 # --localssh also implies the peer connection settings.
2868
2867
2869 url = 'ssh://localserver'
2868 url = 'ssh://localserver'
2870 autoreadstderr = not opts['noreadstderr']
2869 autoreadstderr = not opts['noreadstderr']
2871
2870
2872 if opts['peer'] == 'ssh1':
2871 if opts['peer'] == 'ssh1':
2873 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2872 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2874 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2873 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2875 None, autoreadstderr=autoreadstderr)
2874 None, autoreadstderr=autoreadstderr)
2876 elif opts['peer'] == 'ssh2':
2875 elif opts['peer'] == 'ssh2':
2877 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2876 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2878 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2877 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2879 None, autoreadstderr=autoreadstderr)
2878 None, autoreadstderr=autoreadstderr)
2880 elif opts['peer'] == 'raw':
2879 elif opts['peer'] == 'raw':
2881 ui.write(_('using raw connection to peer\n'))
2880 ui.write(_('using raw connection to peer\n'))
2882 peer = None
2881 peer = None
2883 else:
2882 else:
2884 ui.write(_('creating ssh peer from handshake results\n'))
2883 ui.write(_('creating ssh peer from handshake results\n'))
2885 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2884 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2886 autoreadstderr=autoreadstderr)
2885 autoreadstderr=autoreadstderr)
2887
2886
2888 elif path:
2887 elif path:
2889 # We bypass hg.peer() so we can proxy the sockets.
2888 # We bypass hg.peer() so we can proxy the sockets.
2890 # TODO consider not doing this because we skip
2889 # TODO consider not doing this because we skip
2891 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2890 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2892 u = util.url(path)
2891 u = util.url(path)
2893 if u.scheme != 'http':
2892 if u.scheme != 'http':
2894 raise error.Abort(_('only http:// paths are currently supported'))
2893 raise error.Abort(_('only http:// paths are currently supported'))
2895
2894
2896 url, authinfo = u.authinfo()
2895 url, authinfo = u.authinfo()
2897 openerargs = {
2896 openerargs = {
2898 r'useragent': b'Mercurial debugwireproto',
2897 r'useragent': b'Mercurial debugwireproto',
2899 }
2898 }
2900
2899
2901 # Turn pipes/sockets into observers so we can log I/O.
2900 # Turn pipes/sockets into observers so we can log I/O.
2902 if ui.verbose:
2901 if ui.verbose:
2903 openerargs.update({
2902 openerargs.update({
2904 r'loggingfh': ui,
2903 r'loggingfh': ui,
2905 r'loggingname': b's',
2904 r'loggingname': b's',
2906 r'loggingopts': {
2905 r'loggingopts': {
2907 r'logdata': True,
2906 r'logdata': True,
2908 r'logdataapis': False,
2907 r'logdataapis': False,
2909 },
2908 },
2910 })
2909 })
2911
2910
2912 if ui.debugflag:
2911 if ui.debugflag:
2913 openerargs[r'loggingopts'][r'logdataapis'] = True
2912 openerargs[r'loggingopts'][r'logdataapis'] = True
2914
2913
2915 # Don't send default headers when in raw mode. This allows us to
2914 # Don't send default headers when in raw mode. This allows us to
2916 # bypass most of the behavior of our URL handling code so we can
2915 # bypass most of the behavior of our URL handling code so we can
2917 # have near complete control over what's sent on the wire.
2916 # have near complete control over what's sent on the wire.
2918 if opts['peer'] == 'raw':
2917 if opts['peer'] == 'raw':
2919 openerargs[r'sendaccept'] = False
2918 openerargs[r'sendaccept'] = False
2920
2919
2921 opener = urlmod.opener(ui, authinfo, **openerargs)
2920 opener = urlmod.opener(ui, authinfo, **openerargs)
2922
2921
2923 if opts['peer'] == 'http2':
2922 if opts['peer'] == 'http2':
2924 ui.write(_('creating http peer for wire protocol version 2\n'))
2923 ui.write(_('creating http peer for wire protocol version 2\n'))
2925 # We go through makepeer() because we need an API descriptor for
2924 # We go through makepeer() because we need an API descriptor for
2926 # the peer instance to be useful.
2925 # the peer instance to be useful.
2927 with ui.configoverride({
2926 with ui.configoverride({
2928 ('experimental', 'httppeer.advertise-v2'): True}):
2927 ('experimental', 'httppeer.advertise-v2'): True}):
2929 if opts['nologhandshake']:
2928 if opts['nologhandshake']:
2930 ui.pushbuffer()
2929 ui.pushbuffer()
2931
2930
2932 peer = httppeer.makepeer(ui, path, opener=opener)
2931 peer = httppeer.makepeer(ui, path, opener=opener)
2933
2932
2934 if opts['nologhandshake']:
2933 if opts['nologhandshake']:
2935 ui.popbuffer()
2934 ui.popbuffer()
2936
2935
2937 if not isinstance(peer, httppeer.httpv2peer):
2936 if not isinstance(peer, httppeer.httpv2peer):
2938 raise error.Abort(_('could not instantiate HTTP peer for '
2937 raise error.Abort(_('could not instantiate HTTP peer for '
2939 'wire protocol version 2'),
2938 'wire protocol version 2'),
2940 hint=_('the server may not have the feature '
2939 hint=_('the server may not have the feature '
2941 'enabled or is not allowing this '
2940 'enabled or is not allowing this '
2942 'client version'))
2941 'client version'))
2943
2942
2944 elif opts['peer'] == 'raw':
2943 elif opts['peer'] == 'raw':
2945 ui.write(_('using raw connection to peer\n'))
2944 ui.write(_('using raw connection to peer\n'))
2946 peer = None
2945 peer = None
2947 elif opts['peer']:
2946 elif opts['peer']:
2948 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2947 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2949 opts['peer'])
2948 opts['peer'])
2950 else:
2949 else:
2951 peer = httppeer.makepeer(ui, path, opener=opener)
2950 peer = httppeer.makepeer(ui, path, opener=opener)
2952
2951
2953 # We /could/ populate stdin/stdout with sock.makefile()...
2952 # We /could/ populate stdin/stdout with sock.makefile()...
2954 else:
2953 else:
2955 raise error.Abort(_('unsupported connection configuration'))
2954 raise error.Abort(_('unsupported connection configuration'))
2956
2955
2957 batchedcommands = None
2956 batchedcommands = None
2958
2957
2959 # Now perform actions based on the parsed wire language instructions.
2958 # Now perform actions based on the parsed wire language instructions.
2960 for action, lines in blocks:
2959 for action, lines in blocks:
2961 if action in ('raw', 'raw+'):
2960 if action in ('raw', 'raw+'):
2962 if not stdin:
2961 if not stdin:
2963 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2962 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2964
2963
2965 # Concatenate the data together.
2964 # Concatenate the data together.
2966 data = ''.join(l.lstrip() for l in lines)
2965 data = ''.join(l.lstrip() for l in lines)
2967 data = stringutil.unescapestr(data)
2966 data = stringutil.unescapestr(data)
2968 stdin.write(data)
2967 stdin.write(data)
2969
2968
2970 if action == 'raw+':
2969 if action == 'raw+':
2971 stdin.flush()
2970 stdin.flush()
2972 elif action == 'flush':
2971 elif action == 'flush':
2973 if not stdin:
2972 if not stdin:
2974 raise error.Abort(_('cannot call flush on this peer'))
2973 raise error.Abort(_('cannot call flush on this peer'))
2975 stdin.flush()
2974 stdin.flush()
2976 elif action.startswith('command'):
2975 elif action.startswith('command'):
2977 if not peer:
2976 if not peer:
2978 raise error.Abort(_('cannot send commands unless peer instance '
2977 raise error.Abort(_('cannot send commands unless peer instance '
2979 'is available'))
2978 'is available'))
2980
2979
2981 command = action.split(' ', 1)[1]
2980 command = action.split(' ', 1)[1]
2982
2981
2983 args = {}
2982 args = {}
2984 for line in lines:
2983 for line in lines:
2985 # We need to allow empty values.
2984 # We need to allow empty values.
2986 fields = line.lstrip().split(' ', 1)
2985 fields = line.lstrip().split(' ', 1)
2987 if len(fields) == 1:
2986 if len(fields) == 1:
2988 key = fields[0]
2987 key = fields[0]
2989 value = ''
2988 value = ''
2990 else:
2989 else:
2991 key, value = fields
2990 key, value = fields
2992
2991
2993 if value.startswith('eval:'):
2992 if value.startswith('eval:'):
2994 value = stringutil.evalpythonliteral(value[5:])
2993 value = stringutil.evalpythonliteral(value[5:])
2995 else:
2994 else:
2996 value = stringutil.unescapestr(value)
2995 value = stringutil.unescapestr(value)
2997
2996
2998 args[key] = value
2997 args[key] = value
2999
2998
3000 if batchedcommands is not None:
2999 if batchedcommands is not None:
3001 batchedcommands.append((command, args))
3000 batchedcommands.append((command, args))
3002 continue
3001 continue
3003
3002
3004 ui.status(_('sending %s command\n') % command)
3003 ui.status(_('sending %s command\n') % command)
3005
3004
3006 if 'PUSHFILE' in args:
3005 if 'PUSHFILE' in args:
3007 with open(args['PUSHFILE'], r'rb') as fh:
3006 with open(args['PUSHFILE'], r'rb') as fh:
3008 del args['PUSHFILE']
3007 del args['PUSHFILE']
3009 res, output = peer._callpush(command, fh,
3008 res, output = peer._callpush(command, fh,
3010 **pycompat.strkwargs(args))
3009 **pycompat.strkwargs(args))
3011 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3010 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3012 ui.status(_('remote output: %s\n') %
3011 ui.status(_('remote output: %s\n') %
3013 stringutil.escapestr(output))
3012 stringutil.escapestr(output))
3014 else:
3013 else:
3015 with peer.commandexecutor() as e:
3014 with peer.commandexecutor() as e:
3016 res = e.callcommand(command, args).result()
3015 res = e.callcommand(command, args).result()
3017
3016
3018 if isinstance(res, wireprotov2peer.commandresponse):
3017 if isinstance(res, wireprotov2peer.commandresponse):
3019 val = list(res.cborobjects())
3018 val = list(res.cborobjects())
3020 ui.status(_('response: %s\n') %
3019 ui.status(_('response: %s\n') %
3021 stringutil.pprint(val, bprefix=True))
3020 stringutil.pprint(val, bprefix=True))
3022
3021
3023 else:
3022 else:
3024 ui.status(_('response: %s\n') %
3023 ui.status(_('response: %s\n') %
3025 stringutil.pprint(res, bprefix=True))
3024 stringutil.pprint(res, bprefix=True))
3026
3025
3027 elif action == 'batchbegin':
3026 elif action == 'batchbegin':
3028 if batchedcommands is not None:
3027 if batchedcommands is not None:
3029 raise error.Abort(_('nested batchbegin not allowed'))
3028 raise error.Abort(_('nested batchbegin not allowed'))
3030
3029
3031 batchedcommands = []
3030 batchedcommands = []
3032 elif action == 'batchsubmit':
3031 elif action == 'batchsubmit':
3033 # There is a batching API we could go through. But it would be
3032 # There is a batching API we could go through. But it would be
3034 # difficult to normalize requests into function calls. It is easier
3033 # difficult to normalize requests into function calls. It is easier
3035 # to bypass this layer and normalize to commands + args.
3034 # to bypass this layer and normalize to commands + args.
3036 ui.status(_('sending batch with %d sub-commands\n') %
3035 ui.status(_('sending batch with %d sub-commands\n') %
3037 len(batchedcommands))
3036 len(batchedcommands))
3038 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3037 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3039 ui.status(_('response #%d: %s\n') %
3038 ui.status(_('response #%d: %s\n') %
3040 (i, stringutil.escapestr(chunk)))
3039 (i, stringutil.escapestr(chunk)))
3041
3040
3042 batchedcommands = None
3041 batchedcommands = None
3043
3042
3044 elif action.startswith('httprequest '):
3043 elif action.startswith('httprequest '):
3045 if not opener:
3044 if not opener:
3046 raise error.Abort(_('cannot use httprequest without an HTTP '
3045 raise error.Abort(_('cannot use httprequest without an HTTP '
3047 'peer'))
3046 'peer'))
3048
3047
3049 request = action.split(' ', 2)
3048 request = action.split(' ', 2)
3050 if len(request) != 3:
3049 if len(request) != 3:
3051 raise error.Abort(_('invalid httprequest: expected format is '
3050 raise error.Abort(_('invalid httprequest: expected format is '
3052 '"httprequest <method> <path>'))
3051 '"httprequest <method> <path>'))
3053
3052
3054 method, httppath = request[1:]
3053 method, httppath = request[1:]
3055 headers = {}
3054 headers = {}
3056 body = None
3055 body = None
3057 frames = []
3056 frames = []
3058 for line in lines:
3057 for line in lines:
3059 line = line.lstrip()
3058 line = line.lstrip()
3060 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3059 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3061 if m:
3060 if m:
3062 headers[m.group(1)] = m.group(2)
3061 headers[m.group(1)] = m.group(2)
3063 continue
3062 continue
3064
3063
3065 if line.startswith(b'BODYFILE '):
3064 if line.startswith(b'BODYFILE '):
3066 with open(line.split(b' ', 1), 'rb') as fh:
3065 with open(line.split(b' ', 1), 'rb') as fh:
3067 body = fh.read()
3066 body = fh.read()
3068 elif line.startswith(b'frame '):
3067 elif line.startswith(b'frame '):
3069 frame = wireprotoframing.makeframefromhumanstring(
3068 frame = wireprotoframing.makeframefromhumanstring(
3070 line[len(b'frame '):])
3069 line[len(b'frame '):])
3071
3070
3072 frames.append(frame)
3071 frames.append(frame)
3073 else:
3072 else:
3074 raise error.Abort(_('unknown argument to httprequest: %s') %
3073 raise error.Abort(_('unknown argument to httprequest: %s') %
3075 line)
3074 line)
3076
3075
3077 url = path + httppath
3076 url = path + httppath
3078
3077
3079 if frames:
3078 if frames:
3080 body = b''.join(bytes(f) for f in frames)
3079 body = b''.join(bytes(f) for f in frames)
3081
3080
3082 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3081 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3083
3082
3084 # urllib.Request insists on using has_data() as a proxy for
3083 # urllib.Request insists on using has_data() as a proxy for
3085 # determining the request method. Override that to use our
3084 # determining the request method. Override that to use our
3086 # explicitly requested method.
3085 # explicitly requested method.
3087 req.get_method = lambda: method
3086 req.get_method = lambda: method
3088
3087
3089 try:
3088 try:
3090 res = opener.open(req)
3089 res = opener.open(req)
3091 body = res.read()
3090 body = res.read()
3092 except util.urlerr.urlerror as e:
3091 except util.urlerr.urlerror as e:
3093 e.read()
3092 e.read()
3094 continue
3093 continue
3095
3094
3096 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3095 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3097 ui.write(_('cbor> %s\n') %
3096 ui.write(_('cbor> %s\n') %
3098 stringutil.pprint(cbor.loads(body), bprefix=True))
3097 stringutil.pprint(cbor.loads(body), bprefix=True))
3099
3098
3100 elif action == 'close':
3099 elif action == 'close':
3101 peer.close()
3100 peer.close()
3102 elif action == 'readavailable':
3101 elif action == 'readavailable':
3103 if not stdout or not stderr:
3102 if not stdout or not stderr:
3104 raise error.Abort(_('readavailable not available on this peer'))
3103 raise error.Abort(_('readavailable not available on this peer'))
3105
3104
3106 stdin.close()
3105 stdin.close()
3107 stdout.read()
3106 stdout.read()
3108 stderr.read()
3107 stderr.read()
3109
3108
3110 elif action == 'readline':
3109 elif action == 'readline':
3111 if not stdout:
3110 if not stdout:
3112 raise error.Abort(_('readline not available on this peer'))
3111 raise error.Abort(_('readline not available on this peer'))
3113 stdout.readline()
3112 stdout.readline()
3114 elif action == 'ereadline':
3113 elif action == 'ereadline':
3115 if not stderr:
3114 if not stderr:
3116 raise error.Abort(_('ereadline not available on this peer'))
3115 raise error.Abort(_('ereadline not available on this peer'))
3117 stderr.readline()
3116 stderr.readline()
3118 elif action.startswith('read '):
3117 elif action.startswith('read '):
3119 count = int(action.split(' ', 1)[1])
3118 count = int(action.split(' ', 1)[1])
3120 if not stdout:
3119 if not stdout:
3121 raise error.Abort(_('read not available on this peer'))
3120 raise error.Abort(_('read not available on this peer'))
3122 stdout.read(count)
3121 stdout.read(count)
3123 elif action.startswith('eread '):
3122 elif action.startswith('eread '):
3124 count = int(action.split(' ', 1)[1])
3123 count = int(action.split(' ', 1)[1])
3125 if not stderr:
3124 if not stderr:
3126 raise error.Abort(_('eread not available on this peer'))
3125 raise error.Abort(_('eread not available on this peer'))
3127 stderr.read(count)
3126 stderr.read(count)
3128 else:
3127 else:
3129 raise error.Abort(_('unknown action: %s') % action)
3128 raise error.Abort(_('unknown action: %s') % action)
3130
3129
3131 if batchedcommands is not None:
3130 if batchedcommands is not None:
3132 raise error.Abort(_('unclosed "batchbegin" request'))
3131 raise error.Abort(_('unclosed "batchbegin" request'))
3133
3132
3134 if peer:
3133 if peer:
3135 peer.close()
3134 peer.close()
3136
3135
3137 if proc:
3136 if proc:
3138 proc.kill()
3137 proc.kill()
@@ -1,1145 +1,1131 b''
1 # smartset.py - data structure for revision set
1 # smartset.py - data structure for revision set
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from . import (
10 from . import (
11 encoding,
11 encoding,
12 error,
12 error,
13 pycompat,
13 pycompat,
14 util,
14 util,
15 )
15 )
16
16
17 def _formatsetrepr(r):
17 def _formatsetrepr(r):
18 """Format an optional printable representation of a set
18 """Format an optional printable representation of a set
19
19
20 ======== =================================
20 ======== =================================
21 type(r) example
21 type(r) example
22 ======== =================================
22 ======== =================================
23 tuple ('<not %r>', other)
23 tuple ('<not %r>', other)
24 bytes '<branch closed>'
24 bytes '<branch closed>'
25 callable lambda: '<branch %r>' % sorted(b)
25 callable lambda: '<branch %r>' % sorted(b)
26 object other
26 object other
27 ======== =================================
27 ======== =================================
28 """
28 """
29 if r is None:
29 if r is None:
30 return ''
30 return ''
31 elif isinstance(r, tuple):
31 elif isinstance(r, tuple):
32 return r[0] % util.rapply(pycompat.maybebytestr, r[1:])
32 return r[0] % util.rapply(pycompat.maybebytestr, r[1:])
33 elif isinstance(r, bytes):
33 elif isinstance(r, bytes):
34 return r
34 return r
35 elif callable(r):
35 elif callable(r):
36 return r()
36 return r()
37 else:
37 else:
38 return pycompat.byterepr(r)
38 return pycompat.byterepr(r)
39
39
40 def _typename(o):
40 def _typename(o):
41 return pycompat.sysbytes(type(o).__name__).lstrip('_')
41 return pycompat.sysbytes(type(o).__name__).lstrip('_')
42
42
43 class abstractsmartset(object):
43 class abstractsmartset(object):
44
44
45 def __nonzero__(self):
45 def __nonzero__(self):
46 """True if the smartset is not empty"""
46 """True if the smartset is not empty"""
47 raise NotImplementedError()
47 raise NotImplementedError()
48
48
49 __bool__ = __nonzero__
49 __bool__ = __nonzero__
50
50
51 def __contains__(self, rev):
51 def __contains__(self, rev):
52 """provide fast membership testing"""
52 """provide fast membership testing"""
53 raise NotImplementedError()
53 raise NotImplementedError()
54
54
55 def __iter__(self):
55 def __iter__(self):
56 """iterate the set in the order it is supposed to be iterated"""
56 """iterate the set in the order it is supposed to be iterated"""
57 raise NotImplementedError()
57 raise NotImplementedError()
58
58
59 # Attributes containing a function to perform a fast iteration in a given
59 # Attributes containing a function to perform a fast iteration in a given
60 # direction. A smartset can have none, one, or both defined.
60 # direction. A smartset can have none, one, or both defined.
61 #
61 #
62 # Default value is None instead of a function returning None to avoid
62 # Default value is None instead of a function returning None to avoid
63 # initializing an iterator just for testing if a fast method exists.
63 # initializing an iterator just for testing if a fast method exists.
64 fastasc = None
64 fastasc = None
65 fastdesc = None
65 fastdesc = None
66
66
67 def isascending(self):
67 def isascending(self):
68 """True if the set will iterate in ascending order"""
68 """True if the set will iterate in ascending order"""
69 raise NotImplementedError()
69 raise NotImplementedError()
70
70
71 def isdescending(self):
71 def isdescending(self):
72 """True if the set will iterate in descending order"""
72 """True if the set will iterate in descending order"""
73 raise NotImplementedError()
73 raise NotImplementedError()
74
74
75 def istopo(self):
75 def istopo(self):
76 """True if the set will iterate in topographical order"""
76 """True if the set will iterate in topographical order"""
77 raise NotImplementedError()
77 raise NotImplementedError()
78
78
79 def min(self):
79 def min(self):
80 """return the minimum element in the set"""
80 """return the minimum element in the set"""
81 if self.fastasc is None:
81 if self.fastasc is None:
82 v = min(self)
82 v = min(self)
83 else:
83 else:
84 for v in self.fastasc():
84 for v in self.fastasc():
85 break
85 break
86 else:
86 else:
87 raise ValueError('arg is an empty sequence')
87 raise ValueError('arg is an empty sequence')
88 self.min = lambda: v
88 self.min = lambda: v
89 return v
89 return v
90
90
91 def max(self):
91 def max(self):
92 """return the maximum element in the set"""
92 """return the maximum element in the set"""
93 if self.fastdesc is None:
93 if self.fastdesc is None:
94 return max(self)
94 return max(self)
95 else:
95 else:
96 for v in self.fastdesc():
96 for v in self.fastdesc():
97 break
97 break
98 else:
98 else:
99 raise ValueError('arg is an empty sequence')
99 raise ValueError('arg is an empty sequence')
100 self.max = lambda: v
100 self.max = lambda: v
101 return v
101 return v
102
102
103 def first(self):
103 def first(self):
104 """return the first element in the set (user iteration perspective)
104 """return the first element in the set (user iteration perspective)
105
105
106 Return None if the set is empty"""
106 Return None if the set is empty"""
107 raise NotImplementedError()
107 raise NotImplementedError()
108
108
109 def last(self):
109 def last(self):
110 """return the last element in the set (user iteration perspective)
110 """return the last element in the set (user iteration perspective)
111
111
112 Return None if the set is empty"""
112 Return None if the set is empty"""
113 raise NotImplementedError()
113 raise NotImplementedError()
114
114
115 def __len__(self):
115 def __len__(self):
116 """return the length of the smartsets
116 """return the length of the smartsets
117
117
118 This can be expensive on smartset that could be lazy otherwise."""
118 This can be expensive on smartset that could be lazy otherwise."""
119 raise NotImplementedError()
119 raise NotImplementedError()
120
120
121 def reverse(self):
121 def reverse(self):
122 """reverse the expected iteration order"""
122 """reverse the expected iteration order"""
123 raise NotImplementedError()
123 raise NotImplementedError()
124
124
125 def sort(self, reverse=False):
125 def sort(self, reverse=False):
126 """get the set to iterate in an ascending or descending order"""
126 """get the set to iterate in an ascending or descending order"""
127 raise NotImplementedError()
127 raise NotImplementedError()
128
128
129 def __and__(self, other):
129 def __and__(self, other):
130 """Returns a new object with the intersection of the two collections.
130 """Returns a new object with the intersection of the two collections.
131
131
132 This is part of the mandatory API for smartset."""
132 This is part of the mandatory API for smartset."""
133 if isinstance(other, fullreposet):
133 if isinstance(other, fullreposet):
134 return self
134 return self
135 return self.filter(other.__contains__, condrepr=other, cache=False)
135 return self.filter(other.__contains__, condrepr=other, cache=False)
136
136
137 def __add__(self, other):
137 def __add__(self, other):
138 """Returns a new object with the union of the two collections.
138 """Returns a new object with the union of the two collections.
139
139
140 This is part of the mandatory API for smartset."""
140 This is part of the mandatory API for smartset."""
141 return addset(self, other)
141 return addset(self, other)
142
142
143 def __sub__(self, other):
143 def __sub__(self, other):
144 """Returns a new object with the substraction of the two collections.
144 """Returns a new object with the substraction of the two collections.
145
145
146 This is part of the mandatory API for smartset."""
146 This is part of the mandatory API for smartset."""
147 c = other.__contains__
147 c = other.__contains__
148 return self.filter(lambda r: not c(r), condrepr=('<not %r>', other),
148 return self.filter(lambda r: not c(r), condrepr=('<not %r>', other),
149 cache=False)
149 cache=False)
150
150
151 def filter(self, condition, condrepr=None, cache=True):
151 def filter(self, condition, condrepr=None, cache=True):
152 """Returns this smartset filtered by condition as a new smartset.
152 """Returns this smartset filtered by condition as a new smartset.
153
153
154 `condition` is a callable which takes a revision number and returns a
154 `condition` is a callable which takes a revision number and returns a
155 boolean. Optional `condrepr` provides a printable representation of
155 boolean. Optional `condrepr` provides a printable representation of
156 the given `condition`.
156 the given `condition`.
157
157
158 This is part of the mandatory API for smartset."""
158 This is part of the mandatory API for smartset."""
159 # builtin cannot be cached. but do not needs to
159 # builtin cannot be cached. but do not needs to
160 if cache and util.safehasattr(condition, 'func_code'):
160 if cache and util.safehasattr(condition, 'func_code'):
161 condition = util.cachefunc(condition)
161 condition = util.cachefunc(condition)
162 return filteredset(self, condition, condrepr)
162 return filteredset(self, condition, condrepr)
163
163
164 def slice(self, start, stop):
164 def slice(self, start, stop):
165 """Return new smartset that contains selected elements from this set"""
165 """Return new smartset that contains selected elements from this set"""
166 if start < 0 or stop < 0:
166 if start < 0 or stop < 0:
167 raise error.ProgrammingError('negative index not allowed')
167 raise error.ProgrammingError('negative index not allowed')
168 return self._slice(start, stop)
168 return self._slice(start, stop)
169
169
170 def _slice(self, start, stop):
170 def _slice(self, start, stop):
171 # sub classes may override this. start and stop must not be negative,
171 # sub classes may override this. start and stop must not be negative,
172 # but start > stop is allowed, which should be an empty set.
172 # but start > stop is allowed, which should be an empty set.
173 ys = []
173 ys = []
174 it = iter(self)
174 it = iter(self)
175 for x in xrange(start):
175 for x in xrange(start):
176 y = next(it, None)
176 y = next(it, None)
177 if y is None:
177 if y is None:
178 break
178 break
179 for x in xrange(stop - start):
179 for x in xrange(stop - start):
180 y = next(it, None)
180 y = next(it, None)
181 if y is None:
181 if y is None:
182 break
182 break
183 ys.append(y)
183 ys.append(y)
184 return baseset(ys, datarepr=('slice=%d:%d %r', start, stop, self))
184 return baseset(ys, datarepr=('slice=%d:%d %r', start, stop, self))
185
185
186 class baseset(abstractsmartset):
186 class baseset(abstractsmartset):
187 """Basic data structure that represents a revset and contains the basic
187 """Basic data structure that represents a revset and contains the basic
188 operation that it should be able to perform.
188 operation that it should be able to perform.
189
189
190 Every method in this class should be implemented by any smartset class.
190 Every method in this class should be implemented by any smartset class.
191
191
192 This class could be constructed by an (unordered) set, or an (ordered)
192 This class could be constructed by an (unordered) set, or an (ordered)
193 list-like object. If a set is provided, it'll be sorted lazily.
193 list-like object. If a set is provided, it'll be sorted lazily.
194
194
195 >>> x = [4, 0, 7, 6]
195 >>> x = [4, 0, 7, 6]
196 >>> y = [5, 6, 7, 3]
196 >>> y = [5, 6, 7, 3]
197
197
198 Construct by a set:
198 Construct by a set:
199 >>> xs = baseset(set(x))
199 >>> xs = baseset(set(x))
200 >>> ys = baseset(set(y))
200 >>> ys = baseset(set(y))
201 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
201 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
202 [[0, 4, 6, 7, 3, 5], [6, 7], [0, 4]]
202 [[0, 4, 6, 7, 3, 5], [6, 7], [0, 4]]
203 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
203 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
204 ['addset', 'baseset', 'baseset']
204 ['addset', 'baseset', 'baseset']
205
205
206 Construct by a list-like:
206 Construct by a list-like:
207 >>> xs = baseset(x)
207 >>> xs = baseset(x)
208 >>> ys = baseset(i for i in y)
208 >>> ys = baseset(i for i in y)
209 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
209 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
210 [[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
210 [[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
211 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
211 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
212 ['addset', 'filteredset', 'filteredset']
212 ['addset', 'filteredset', 'filteredset']
213
213
214 Populate "_set" fields in the lists so set optimization may be used:
214 Populate "_set" fields in the lists so set optimization may be used:
215 >>> [1 in xs, 3 in ys]
215 >>> [1 in xs, 3 in ys]
216 [False, True]
216 [False, True]
217
217
218 Without sort(), results won't be changed:
218 Without sort(), results won't be changed:
219 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
219 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
220 [[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
220 [[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
221 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
221 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
222 ['addset', 'filteredset', 'filteredset']
222 ['addset', 'filteredset', 'filteredset']
223
223
224 With sort(), set optimization could be used:
224 With sort(), set optimization could be used:
225 >>> xs.sort(reverse=True)
225 >>> xs.sort(reverse=True)
226 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
226 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
227 [[7, 6, 4, 0, 5, 3], [7, 6], [4, 0]]
227 [[7, 6, 4, 0, 5, 3], [7, 6], [4, 0]]
228 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
228 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
229 ['addset', 'baseset', 'baseset']
229 ['addset', 'baseset', 'baseset']
230
230
231 >>> ys.sort()
231 >>> ys.sort()
232 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
232 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
233 [[7, 6, 4, 0, 3, 5], [7, 6], [4, 0]]
233 [[7, 6, 4, 0, 3, 5], [7, 6], [4, 0]]
234 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
234 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
235 ['addset', 'baseset', 'baseset']
235 ['addset', 'baseset', 'baseset']
236
236
237 istopo is preserved across set operations
237 istopo is preserved across set operations
238 >>> xs = baseset(set(x), istopo=True)
238 >>> xs = baseset(set(x), istopo=True)
239 >>> rs = xs & ys
239 >>> rs = xs & ys
240 >>> type(rs).__name__
240 >>> type(rs).__name__
241 'baseset'
241 'baseset'
242 >>> rs._istopo
242 >>> rs._istopo
243 True
243 True
244 """
244 """
245 def __init__(self, data=(), datarepr=None, istopo=False):
245 def __init__(self, data=(), datarepr=None, istopo=False):
246 """
246 """
247 datarepr: a tuple of (format, obj, ...), a function or an object that
247 datarepr: a tuple of (format, obj, ...), a function or an object that
248 provides a printable representation of the given data.
248 provides a printable representation of the given data.
249 """
249 """
250 self._ascending = None
250 self._ascending = None
251 self._istopo = istopo
251 self._istopo = istopo
252 if isinstance(data, set):
252 if isinstance(data, set):
253 # converting set to list has a cost, do it lazily
253 # converting set to list has a cost, do it lazily
254 self._set = data
254 self._set = data
255 # set has no order we pick one for stability purpose
255 # set has no order we pick one for stability purpose
256 self._ascending = True
256 self._ascending = True
257 else:
257 else:
258 if not isinstance(data, list):
258 if not isinstance(data, list):
259 data = list(data)
259 data = list(data)
260 self._list = data
260 self._list = data
261 self._datarepr = datarepr
261 self._datarepr = datarepr
262
262
263 @util.propertycache
263 @util.propertycache
264 def _set(self):
264 def _set(self):
265 return set(self._list)
265 return set(self._list)
266
266
267 @util.propertycache
267 @util.propertycache
268 def _asclist(self):
268 def _asclist(self):
269 asclist = self._list[:]
269 asclist = self._list[:]
270 asclist.sort()
270 asclist.sort()
271 return asclist
271 return asclist
272
272
273 @util.propertycache
273 @util.propertycache
274 def _list(self):
274 def _list(self):
275 # _list is only lazily constructed if we have _set
275 # _list is only lazily constructed if we have _set
276 assert r'_set' in self.__dict__
276 assert r'_set' in self.__dict__
277 return list(self._set)
277 return list(self._set)
278
278
279 def __iter__(self):
279 def __iter__(self):
280 if self._ascending is None:
280 if self._ascending is None:
281 return iter(self._list)
281 return iter(self._list)
282 elif self._ascending:
282 elif self._ascending:
283 return iter(self._asclist)
283 return iter(self._asclist)
284 else:
284 else:
285 return reversed(self._asclist)
285 return reversed(self._asclist)
286
286
287 def fastasc(self):
287 def fastasc(self):
288 return iter(self._asclist)
288 return iter(self._asclist)
289
289
290 def fastdesc(self):
290 def fastdesc(self):
291 return reversed(self._asclist)
291 return reversed(self._asclist)
292
292
293 @util.propertycache
293 @util.propertycache
294 def __contains__(self):
294 def __contains__(self):
295 return self._set.__contains__
295 return self._set.__contains__
296
296
297 def __nonzero__(self):
297 def __nonzero__(self):
298 return bool(len(self))
298 return bool(len(self))
299
299
300 __bool__ = __nonzero__
300 __bool__ = __nonzero__
301
301
302 def sort(self, reverse=False):
302 def sort(self, reverse=False):
303 self._ascending = not bool(reverse)
303 self._ascending = not bool(reverse)
304 self._istopo = False
304 self._istopo = False
305
305
306 def reverse(self):
306 def reverse(self):
307 if self._ascending is None:
307 if self._ascending is None:
308 self._list.reverse()
308 self._list.reverse()
309 else:
309 else:
310 self._ascending = not self._ascending
310 self._ascending = not self._ascending
311 self._istopo = False
311 self._istopo = False
312
312
313 def __len__(self):
313 def __len__(self):
314 if r'_list' in self.__dict__:
314 if r'_list' in self.__dict__:
315 return len(self._list)
315 return len(self._list)
316 else:
316 else:
317 return len(self._set)
317 return len(self._set)
318
318
319 def isascending(self):
319 def isascending(self):
320 """Returns True if the collection is ascending order, False if not.
320 """Returns True if the collection is ascending order, False if not.
321
321
322 This is part of the mandatory API for smartset."""
322 This is part of the mandatory API for smartset."""
323 if len(self) <= 1:
323 if len(self) <= 1:
324 return True
324 return True
325 return self._ascending is not None and self._ascending
325 return self._ascending is not None and self._ascending
326
326
327 def isdescending(self):
327 def isdescending(self):
328 """Returns True if the collection is descending order, False if not.
328 """Returns True if the collection is descending order, False if not.
329
329
330 This is part of the mandatory API for smartset."""
330 This is part of the mandatory API for smartset."""
331 if len(self) <= 1:
331 if len(self) <= 1:
332 return True
332 return True
333 return self._ascending is not None and not self._ascending
333 return self._ascending is not None and not self._ascending
334
334
335 def istopo(self):
335 def istopo(self):
336 """Is the collection is in topographical order or not.
336 """Is the collection is in topographical order or not.
337
337
338 This is part of the mandatory API for smartset."""
338 This is part of the mandatory API for smartset."""
339 if len(self) <= 1:
339 if len(self) <= 1:
340 return True
340 return True
341 return self._istopo
341 return self._istopo
342
342
343 def first(self):
343 def first(self):
344 if self:
344 if self:
345 if self._ascending is None:
345 if self._ascending is None:
346 return self._list[0]
346 return self._list[0]
347 elif self._ascending:
347 elif self._ascending:
348 return self._asclist[0]
348 return self._asclist[0]
349 else:
349 else:
350 return self._asclist[-1]
350 return self._asclist[-1]
351 return None
351 return None
352
352
353 def last(self):
353 def last(self):
354 if self:
354 if self:
355 if self._ascending is None:
355 if self._ascending is None:
356 return self._list[-1]
356 return self._list[-1]
357 elif self._ascending:
357 elif self._ascending:
358 return self._asclist[-1]
358 return self._asclist[-1]
359 else:
359 else:
360 return self._asclist[0]
360 return self._asclist[0]
361 return None
361 return None
362
362
363 def _fastsetop(self, other, op):
363 def _fastsetop(self, other, op):
364 # try to use native set operations as fast paths
364 # try to use native set operations as fast paths
365 if (type(other) is baseset and r'_set' in other.__dict__ and r'_set' in
365 if (type(other) is baseset and r'_set' in other.__dict__ and r'_set' in
366 self.__dict__ and self._ascending is not None):
366 self.__dict__ and self._ascending is not None):
367 s = baseset(data=getattr(self._set, op)(other._set),
367 s = baseset(data=getattr(self._set, op)(other._set),
368 istopo=self._istopo)
368 istopo=self._istopo)
369 s._ascending = self._ascending
369 s._ascending = self._ascending
370 else:
370 else:
371 s = getattr(super(baseset, self), op)(other)
371 s = getattr(super(baseset, self), op)(other)
372 return s
372 return s
373
373
374 def __and__(self, other):
374 def __and__(self, other):
375 return self._fastsetop(other, '__and__')
375 return self._fastsetop(other, '__and__')
376
376
377 def __sub__(self, other):
377 def __sub__(self, other):
378 return self._fastsetop(other, '__sub__')
378 return self._fastsetop(other, '__sub__')
379
379
380 def _slice(self, start, stop):
380 def _slice(self, start, stop):
381 # creating new list should be generally cheaper than iterating items
381 # creating new list should be generally cheaper than iterating items
382 if self._ascending is None:
382 if self._ascending is None:
383 return baseset(self._list[start:stop], istopo=self._istopo)
383 return baseset(self._list[start:stop], istopo=self._istopo)
384
384
385 data = self._asclist
385 data = self._asclist
386 if not self._ascending:
386 if not self._ascending:
387 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0)
387 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0)
388 s = baseset(data[start:stop], istopo=self._istopo)
388 s = baseset(data[start:stop], istopo=self._istopo)
389 s._ascending = self._ascending
389 s._ascending = self._ascending
390 return s
390 return s
391
391
392 @encoding.strmethod
392 @encoding.strmethod
393 def __repr__(self):
393 def __repr__(self):
394 d = {None: '', False: '-', True: '+'}[self._ascending]
394 d = {None: '', False: '-', True: '+'}[self._ascending]
395 s = _formatsetrepr(self._datarepr)
395 s = _formatsetrepr(self._datarepr)
396 if not s:
396 if not s:
397 l = self._list
397 l = self._list
398 # if _list has been built from a set, it might have a different
398 # if _list has been built from a set, it might have a different
399 # order from one python implementation to another.
399 # order from one python implementation to another.
400 # We fallback to the sorted version for a stable output.
400 # We fallback to the sorted version for a stable output.
401 if self._ascending is not None:
401 if self._ascending is not None:
402 l = self._asclist
402 l = self._asclist
403 s = pycompat.byterepr(l)
403 s = pycompat.byterepr(l)
404 return '<%s%s %s>' % (_typename(self), d, s)
404 return '<%s%s %s>' % (_typename(self), d, s)
405
405
406 class filteredset(abstractsmartset):
406 class filteredset(abstractsmartset):
407 """Duck type for baseset class which iterates lazily over the revisions in
407 """Duck type for baseset class which iterates lazily over the revisions in
408 the subset and contains a function which tests for membership in the
408 the subset and contains a function which tests for membership in the
409 revset
409 revset
410 """
410 """
411 def __init__(self, subset, condition=lambda x: True, condrepr=None):
411 def __init__(self, subset, condition=lambda x: True, condrepr=None):
412 """
412 """
413 condition: a function that decide whether a revision in the subset
413 condition: a function that decide whether a revision in the subset
414 belongs to the revset or not.
414 belongs to the revset or not.
415 condrepr: a tuple of (format, obj, ...), a function or an object that
415 condrepr: a tuple of (format, obj, ...), a function or an object that
416 provides a printable representation of the given condition.
416 provides a printable representation of the given condition.
417 """
417 """
418 self._subset = subset
418 self._subset = subset
419 self._condition = condition
419 self._condition = condition
420 self._condrepr = condrepr
420 self._condrepr = condrepr
421
421
422 def __contains__(self, x):
422 def __contains__(self, x):
423 return x in self._subset and self._condition(x)
423 return x in self._subset and self._condition(x)
424
424
425 def __iter__(self):
425 def __iter__(self):
426 return self._iterfilter(self._subset)
426 return self._iterfilter(self._subset)
427
427
428 def _iterfilter(self, it):
428 def _iterfilter(self, it):
429 cond = self._condition
429 cond = self._condition
430 for x in it:
430 for x in it:
431 if cond(x):
431 if cond(x):
432 yield x
432 yield x
433
433
434 @property
434 @property
435 def fastasc(self):
435 def fastasc(self):
436 it = self._subset.fastasc
436 it = self._subset.fastasc
437 if it is None:
437 if it is None:
438 return None
438 return None
439 return lambda: self._iterfilter(it())
439 return lambda: self._iterfilter(it())
440
440
441 @property
441 @property
442 def fastdesc(self):
442 def fastdesc(self):
443 it = self._subset.fastdesc
443 it = self._subset.fastdesc
444 if it is None:
444 if it is None:
445 return None
445 return None
446 return lambda: self._iterfilter(it())
446 return lambda: self._iterfilter(it())
447
447
448 def __nonzero__(self):
448 def __nonzero__(self):
449 fast = None
449 fast = None
450 candidates = [self.fastasc if self.isascending() else None,
450 candidates = [self.fastasc if self.isascending() else None,
451 self.fastdesc if self.isdescending() else None,
451 self.fastdesc if self.isdescending() else None,
452 self.fastasc,
452 self.fastasc,
453 self.fastdesc]
453 self.fastdesc]
454 for candidate in candidates:
454 for candidate in candidates:
455 if candidate is not None:
455 if candidate is not None:
456 fast = candidate
456 fast = candidate
457 break
457 break
458
458
459 if fast is not None:
459 if fast is not None:
460 it = fast()
460 it = fast()
461 else:
461 else:
462 it = self
462 it = self
463
463
464 for r in it:
464 for r in it:
465 return True
465 return True
466 return False
466 return False
467
467
468 __bool__ = __nonzero__
468 __bool__ = __nonzero__
469
469
470 def __len__(self):
470 def __len__(self):
471 # Basic implementation to be changed in future patches.
471 # Basic implementation to be changed in future patches.
472 # until this gets improved, we use generator expression
472 # until this gets improved, we use generator expression
473 # here, since list comprehensions are free to call __len__ again
473 # here, since list comprehensions are free to call __len__ again
474 # causing infinite recursion
474 # causing infinite recursion
475 l = baseset(r for r in self)
475 l = baseset(r for r in self)
476 return len(l)
476 return len(l)
477
477
478 def sort(self, reverse=False):
478 def sort(self, reverse=False):
479 self._subset.sort(reverse=reverse)
479 self._subset.sort(reverse=reverse)
480
480
481 def reverse(self):
481 def reverse(self):
482 self._subset.reverse()
482 self._subset.reverse()
483
483
484 def isascending(self):
484 def isascending(self):
485 return self._subset.isascending()
485 return self._subset.isascending()
486
486
487 def isdescending(self):
487 def isdescending(self):
488 return self._subset.isdescending()
488 return self._subset.isdescending()
489
489
490 def istopo(self):
490 def istopo(self):
491 return self._subset.istopo()
491 return self._subset.istopo()
492
492
493 def first(self):
493 def first(self):
494 for x in self:
494 for x in self:
495 return x
495 return x
496 return None
496 return None
497
497
498 def last(self):
498 def last(self):
499 it = None
499 it = None
500 if self.isascending():
500 if self.isascending():
501 it = self.fastdesc
501 it = self.fastdesc
502 elif self.isdescending():
502 elif self.isdescending():
503 it = self.fastasc
503 it = self.fastasc
504 if it is not None:
504 if it is not None:
505 for x in it():
505 for x in it():
506 return x
506 return x
507 return None #empty case
507 return None #empty case
508 else:
508 else:
509 x = None
509 x = None
510 for x in self:
510 for x in self:
511 pass
511 pass
512 return x
512 return x
513
513
514 @encoding.strmethod
514 @encoding.strmethod
515 def __repr__(self):
515 def __repr__(self):
516 xs = [pycompat.byterepr(self._subset)]
516 xs = [pycompat.byterepr(self._subset)]
517 s = _formatsetrepr(self._condrepr)
517 s = _formatsetrepr(self._condrepr)
518 if s:
518 if s:
519 xs.append(s)
519 xs.append(s)
520 return '<%s %s>' % (_typename(self), ', '.join(xs))
520 return '<%s %s>' % (_typename(self), ', '.join(xs))
521
521
522 def _iterordered(ascending, iter1, iter2):
522 def _iterordered(ascending, iter1, iter2):
523 """produce an ordered iteration from two iterators with the same order
523 """produce an ordered iteration from two iterators with the same order
524
524
525 The ascending is used to indicated the iteration direction.
525 The ascending is used to indicated the iteration direction.
526 """
526 """
527 choice = max
527 choice = max
528 if ascending:
528 if ascending:
529 choice = min
529 choice = min
530
530
531 val1 = None
531 val1 = None
532 val2 = None
532 val2 = None
533 try:
533 try:
534 # Consume both iterators in an ordered way until one is empty
534 # Consume both iterators in an ordered way until one is empty
535 while True:
535 while True:
536 if val1 is None:
536 if val1 is None:
537 val1 = next(iter1)
537 val1 = next(iter1)
538 if val2 is None:
538 if val2 is None:
539 val2 = next(iter2)
539 val2 = next(iter2)
540 n = choice(val1, val2)
540 n = choice(val1, val2)
541 yield n
541 yield n
542 if val1 == n:
542 if val1 == n:
543 val1 = None
543 val1 = None
544 if val2 == n:
544 if val2 == n:
545 val2 = None
545 val2 = None
546 except StopIteration:
546 except StopIteration:
547 # Flush any remaining values and consume the other one
547 # Flush any remaining values and consume the other one
548 it = iter2
548 it = iter2
549 if val1 is not None:
549 if val1 is not None:
550 yield val1
550 yield val1
551 it = iter1
551 it = iter1
552 elif val2 is not None:
552 elif val2 is not None:
553 # might have been equality and both are empty
553 # might have been equality and both are empty
554 yield val2
554 yield val2
555 for val in it:
555 for val in it:
556 yield val
556 yield val
557
557
558 class addset(abstractsmartset):
558 class addset(abstractsmartset):
559 """Represent the addition of two sets
559 """Represent the addition of two sets
560
560
561 Wrapper structure for lazily adding two structures without losing much
561 Wrapper structure for lazily adding two structures without losing much
562 performance on the __contains__ method
562 performance on the __contains__ method
563
563
564 If the ascending attribute is set, that means the two structures are
564 If the ascending attribute is set, that means the two structures are
565 ordered in either an ascending or descending way. Therefore, we can add
565 ordered in either an ascending or descending way. Therefore, we can add
566 them maintaining the order by iterating over both at the same time
566 them maintaining the order by iterating over both at the same time
567
567
568 >>> xs = baseset([0, 3, 2])
568 >>> xs = baseset([0, 3, 2])
569 >>> ys = baseset([5, 2, 4])
569 >>> ys = baseset([5, 2, 4])
570
570
571 >>> rs = addset(xs, ys)
571 >>> rs = addset(xs, ys)
572 >>> bool(rs), 0 in rs, 1 in rs, 5 in rs, rs.first(), rs.last()
572 >>> bool(rs), 0 in rs, 1 in rs, 5 in rs, rs.first(), rs.last()
573 (True, True, False, True, 0, 4)
573 (True, True, False, True, 0, 4)
574 >>> rs = addset(xs, baseset([]))
574 >>> rs = addset(xs, baseset([]))
575 >>> bool(rs), 0 in rs, 1 in rs, rs.first(), rs.last()
575 >>> bool(rs), 0 in rs, 1 in rs, rs.first(), rs.last()
576 (True, True, False, 0, 2)
576 (True, True, False, 0, 2)
577 >>> rs = addset(baseset([]), baseset([]))
577 >>> rs = addset(baseset([]), baseset([]))
578 >>> bool(rs), 0 in rs, rs.first(), rs.last()
578 >>> bool(rs), 0 in rs, rs.first(), rs.last()
579 (False, False, None, None)
579 (False, False, None, None)
580
580
581 iterate unsorted:
581 iterate unsorted:
582 >>> rs = addset(xs, ys)
582 >>> rs = addset(xs, ys)
583 >>> # (use generator because pypy could call len())
583 >>> # (use generator because pypy could call len())
584 >>> list(x for x in rs) # without _genlist
584 >>> list(x for x in rs) # without _genlist
585 [0, 3, 2, 5, 4]
585 [0, 3, 2, 5, 4]
586 >>> assert not rs._genlist
586 >>> assert not rs._genlist
587 >>> len(rs)
587 >>> len(rs)
588 5
588 5
589 >>> [x for x in rs] # with _genlist
589 >>> [x for x in rs] # with _genlist
590 [0, 3, 2, 5, 4]
590 [0, 3, 2, 5, 4]
591 >>> assert rs._genlist
591 >>> assert rs._genlist
592
592
593 iterate ascending:
593 iterate ascending:
594 >>> rs = addset(xs, ys, ascending=True)
594 >>> rs = addset(xs, ys, ascending=True)
595 >>> # (use generator because pypy could call len())
595 >>> # (use generator because pypy could call len())
596 >>> list(x for x in rs), list(x for x in rs.fastasc()) # without _asclist
596 >>> list(x for x in rs), list(x for x in rs.fastasc()) # without _asclist
597 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
597 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
598 >>> assert not rs._asclist
598 >>> assert not rs._asclist
599 >>> len(rs)
599 >>> len(rs)
600 5
600 5
601 >>> [x for x in rs], [x for x in rs.fastasc()]
601 >>> [x for x in rs], [x for x in rs.fastasc()]
602 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
602 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5])
603 >>> assert rs._asclist
603 >>> assert rs._asclist
604
604
605 iterate descending:
605 iterate descending:
606 >>> rs = addset(xs, ys, ascending=False)
606 >>> rs = addset(xs, ys, ascending=False)
607 >>> # (use generator because pypy could call len())
607 >>> # (use generator because pypy could call len())
608 >>> list(x for x in rs), list(x for x in rs.fastdesc()) # without _asclist
608 >>> list(x for x in rs), list(x for x in rs.fastdesc()) # without _asclist
609 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
609 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
610 >>> assert not rs._asclist
610 >>> assert not rs._asclist
611 >>> len(rs)
611 >>> len(rs)
612 5
612 5
613 >>> [x for x in rs], [x for x in rs.fastdesc()]
613 >>> [x for x in rs], [x for x in rs.fastdesc()]
614 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
614 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0])
615 >>> assert rs._asclist
615 >>> assert rs._asclist
616
616
617 iterate ascending without fastasc:
617 iterate ascending without fastasc:
618 >>> rs = addset(xs, generatorset(ys), ascending=True)
618 >>> rs = addset(xs, generatorset(ys), ascending=True)
619 >>> assert rs.fastasc is None
619 >>> assert rs.fastasc is None
620 >>> [x for x in rs]
620 >>> [x for x in rs]
621 [0, 2, 3, 4, 5]
621 [0, 2, 3, 4, 5]
622
622
623 iterate descending without fastdesc:
623 iterate descending without fastdesc:
624 >>> rs = addset(generatorset(xs), ys, ascending=False)
624 >>> rs = addset(generatorset(xs), ys, ascending=False)
625 >>> assert rs.fastdesc is None
625 >>> assert rs.fastdesc is None
626 >>> [x for x in rs]
626 >>> [x for x in rs]
627 [5, 4, 3, 2, 0]
627 [5, 4, 3, 2, 0]
628 """
628 """
629 def __init__(self, revs1, revs2, ascending=None):
629 def __init__(self, revs1, revs2, ascending=None):
630 self._r1 = revs1
630 self._r1 = revs1
631 self._r2 = revs2
631 self._r2 = revs2
632 self._iter = None
632 self._iter = None
633 self._ascending = ascending
633 self._ascending = ascending
634 self._genlist = None
634 self._genlist = None
635 self._asclist = None
635 self._asclist = None
636
636
637 def __len__(self):
637 def __len__(self):
638 return len(self._list)
638 return len(self._list)
639
639
640 def __nonzero__(self):
640 def __nonzero__(self):
641 return bool(self._r1) or bool(self._r2)
641 return bool(self._r1) or bool(self._r2)
642
642
643 __bool__ = __nonzero__
643 __bool__ = __nonzero__
644
644
645 @util.propertycache
645 @util.propertycache
646 def _list(self):
646 def _list(self):
647 if not self._genlist:
647 if not self._genlist:
648 self._genlist = baseset(iter(self))
648 self._genlist = baseset(iter(self))
649 return self._genlist
649 return self._genlist
650
650
651 def __iter__(self):
651 def __iter__(self):
652 """Iterate over both collections without repeating elements
652 """Iterate over both collections without repeating elements
653
653
654 If the ascending attribute is not set, iterate over the first one and
654 If the ascending attribute is not set, iterate over the first one and
655 then over the second one checking for membership on the first one so we
655 then over the second one checking for membership on the first one so we
656 dont yield any duplicates.
656 dont yield any duplicates.
657
657
658 If the ascending attribute is set, iterate over both collections at the
658 If the ascending attribute is set, iterate over both collections at the
659 same time, yielding only one value at a time in the given order.
659 same time, yielding only one value at a time in the given order.
660 """
660 """
661 if self._ascending is None:
661 if self._ascending is None:
662 if self._genlist:
662 if self._genlist:
663 return iter(self._genlist)
663 return iter(self._genlist)
664 def arbitraryordergen():
664 def arbitraryordergen():
665 for r in self._r1:
665 for r in self._r1:
666 yield r
666 yield r
667 inr1 = self._r1.__contains__
667 inr1 = self._r1.__contains__
668 for r in self._r2:
668 for r in self._r2:
669 if not inr1(r):
669 if not inr1(r):
670 yield r
670 yield r
671 return arbitraryordergen()
671 return arbitraryordergen()
672 # try to use our own fast iterator if it exists
672 # try to use our own fast iterator if it exists
673 self._trysetasclist()
673 self._trysetasclist()
674 if self._ascending:
674 if self._ascending:
675 attr = 'fastasc'
675 attr = 'fastasc'
676 else:
676 else:
677 attr = 'fastdesc'
677 attr = 'fastdesc'
678 it = getattr(self, attr)
678 it = getattr(self, attr)
679 if it is not None:
679 if it is not None:
680 return it()
680 return it()
681 # maybe half of the component supports fast
681 # maybe half of the component supports fast
682 # get iterator for _r1
682 # get iterator for _r1
683 iter1 = getattr(self._r1, attr)
683 iter1 = getattr(self._r1, attr)
684 if iter1 is None:
684 if iter1 is None:
685 # let's avoid side effect (not sure it matters)
685 # let's avoid side effect (not sure it matters)
686 iter1 = iter(sorted(self._r1, reverse=not self._ascending))
686 iter1 = iter(sorted(self._r1, reverse=not self._ascending))
687 else:
687 else:
688 iter1 = iter1()
688 iter1 = iter1()
689 # get iterator for _r2
689 # get iterator for _r2
690 iter2 = getattr(self._r2, attr)
690 iter2 = getattr(self._r2, attr)
691 if iter2 is None:
691 if iter2 is None:
692 # let's avoid side effect (not sure it matters)
692 # let's avoid side effect (not sure it matters)
693 iter2 = iter(sorted(self._r2, reverse=not self._ascending))
693 iter2 = iter(sorted(self._r2, reverse=not self._ascending))
694 else:
694 else:
695 iter2 = iter2()
695 iter2 = iter2()
696 return _iterordered(self._ascending, iter1, iter2)
696 return _iterordered(self._ascending, iter1, iter2)
697
697
698 def _trysetasclist(self):
698 def _trysetasclist(self):
699 """populate the _asclist attribute if possible and necessary"""
699 """populate the _asclist attribute if possible and necessary"""
700 if self._genlist is not None and self._asclist is None:
700 if self._genlist is not None and self._asclist is None:
701 self._asclist = sorted(self._genlist)
701 self._asclist = sorted(self._genlist)
702
702
703 @property
703 @property
704 def fastasc(self):
704 def fastasc(self):
705 self._trysetasclist()
705 self._trysetasclist()
706 if self._asclist is not None:
706 if self._asclist is not None:
707 return self._asclist.__iter__
707 return self._asclist.__iter__
708 iter1 = self._r1.fastasc
708 iter1 = self._r1.fastasc
709 iter2 = self._r2.fastasc
709 iter2 = self._r2.fastasc
710 if None in (iter1, iter2):
710 if None in (iter1, iter2):
711 return None
711 return None
712 return lambda: _iterordered(True, iter1(), iter2())
712 return lambda: _iterordered(True, iter1(), iter2())
713
713
714 @property
714 @property
715 def fastdesc(self):
715 def fastdesc(self):
716 self._trysetasclist()
716 self._trysetasclist()
717 if self._asclist is not None:
717 if self._asclist is not None:
718 return self._asclist.__reversed__
718 return self._asclist.__reversed__
719 iter1 = self._r1.fastdesc
719 iter1 = self._r1.fastdesc
720 iter2 = self._r2.fastdesc
720 iter2 = self._r2.fastdesc
721 if None in (iter1, iter2):
721 if None in (iter1, iter2):
722 return None
722 return None
723 return lambda: _iterordered(False, iter1(), iter2())
723 return lambda: _iterordered(False, iter1(), iter2())
724
724
725 def __contains__(self, x):
725 def __contains__(self, x):
726 return x in self._r1 or x in self._r2
726 return x in self._r1 or x in self._r2
727
727
728 def sort(self, reverse=False):
728 def sort(self, reverse=False):
729 """Sort the added set
729 """Sort the added set
730
730
731 For this we use the cached list with all the generated values and if we
731 For this we use the cached list with all the generated values and if we
732 know they are ascending or descending we can sort them in a smart way.
732 know they are ascending or descending we can sort them in a smart way.
733 """
733 """
734 self._ascending = not reverse
734 self._ascending = not reverse
735
735
736 def isascending(self):
736 def isascending(self):
737 return self._ascending is not None and self._ascending
737 return self._ascending is not None and self._ascending
738
738
739 def isdescending(self):
739 def isdescending(self):
740 return self._ascending is not None and not self._ascending
740 return self._ascending is not None and not self._ascending
741
741
742 def istopo(self):
742 def istopo(self):
743 # not worth the trouble asserting if the two sets combined are still
743 # not worth the trouble asserting if the two sets combined are still
744 # in topographical order. Use the sort() predicate to explicitly sort
744 # in topographical order. Use the sort() predicate to explicitly sort
745 # again instead.
745 # again instead.
746 return False
746 return False
747
747
748 def reverse(self):
748 def reverse(self):
749 if self._ascending is None:
749 if self._ascending is None:
750 self._list.reverse()
750 self._list.reverse()
751 else:
751 else:
752 self._ascending = not self._ascending
752 self._ascending = not self._ascending
753
753
754 def first(self):
754 def first(self):
755 for x in self:
755 for x in self:
756 return x
756 return x
757 return None
757 return None
758
758
759 def last(self):
759 def last(self):
760 self.reverse()
760 self.reverse()
761 val = self.first()
761 val = self.first()
762 self.reverse()
762 self.reverse()
763 return val
763 return val
764
764
765 @encoding.strmethod
765 @encoding.strmethod
766 def __repr__(self):
766 def __repr__(self):
767 d = {None: '', False: '-', True: '+'}[self._ascending]
767 d = {None: '', False: '-', True: '+'}[self._ascending]
768 return '<%s%s %r, %r>' % (_typename(self), d, self._r1, self._r2)
768 return '<%s%s %r, %r>' % (_typename(self), d, self._r1, self._r2)
769
769
770 class generatorset(abstractsmartset):
770 class generatorset(abstractsmartset):
771 """Wrap a generator for lazy iteration
771 """Wrap a generator for lazy iteration
772
772
773 Wrapper structure for generators that provides lazy membership and can
773 Wrapper structure for generators that provides lazy membership and can
774 be iterated more than once.
774 be iterated more than once.
775 When asked for membership it generates values until either it finds the
775 When asked for membership it generates values until either it finds the
776 requested one or has gone through all the elements in the generator
776 requested one or has gone through all the elements in the generator
777
777
778 >>> xs = generatorset([0, 1, 4], iterasc=True)
778 >>> xs = generatorset([0, 1, 4], iterasc=True)
779 >>> assert xs.last() == xs.last()
779 >>> assert xs.last() == xs.last()
780 >>> xs.last() # cached
780 >>> xs.last() # cached
781 4
781 4
782 """
782 """
783 def __new__(cls, gen, iterasc=None):
783 def __new__(cls, gen, iterasc=None):
784 if iterasc is None:
784 if iterasc is None:
785 typ = cls
785 typ = cls
786 elif iterasc:
786 elif iterasc:
787 typ = _generatorsetasc
787 typ = _generatorsetasc
788 else:
788 else:
789 typ = _generatorsetdesc
789 typ = _generatorsetdesc
790
790
791 return super(generatorset, cls).__new__(typ)
791 return super(generatorset, cls).__new__(typ)
792
792
793 def __init__(self, gen, iterasc=None):
793 def __init__(self, gen, iterasc=None):
794 """
794 """
795 gen: a generator producing the values for the generatorset.
795 gen: a generator producing the values for the generatorset.
796 """
796 """
797 self._gen = gen
797 self._gen = gen
798 self._asclist = None
798 self._asclist = None
799 self._cache = {}
799 self._cache = {}
800 self._genlist = []
800 self._genlist = []
801 self._finished = False
801 self._finished = False
802 self._ascending = True
802 self._ascending = True
803
803
804 def __nonzero__(self):
804 def __nonzero__(self):
805 # Do not use 'for r in self' because it will enforce the iteration
805 # Do not use 'for r in self' because it will enforce the iteration
806 # order (default ascending), possibly unrolling a whole descending
806 # order (default ascending), possibly unrolling a whole descending
807 # iterator.
807 # iterator.
808 if self._genlist:
808 if self._genlist:
809 return True
809 return True
810 for r in self._consumegen():
810 for r in self._consumegen():
811 return True
811 return True
812 return False
812 return False
813
813
814 __bool__ = __nonzero__
814 __bool__ = __nonzero__
815
815
816 def __contains__(self, x):
816 def __contains__(self, x):
817 if x in self._cache:
817 if x in self._cache:
818 return self._cache[x]
818 return self._cache[x]
819
819
820 # Use new values only, as existing values would be cached.
820 # Use new values only, as existing values would be cached.
821 for l in self._consumegen():
821 for l in self._consumegen():
822 if l == x:
822 if l == x:
823 return True
823 return True
824
824
825 self._cache[x] = False
825 self._cache[x] = False
826 return False
826 return False
827
827
828 def __iter__(self):
828 def __iter__(self):
829 if self._ascending:
829 if self._ascending:
830 it = self.fastasc
830 it = self.fastasc
831 else:
831 else:
832 it = self.fastdesc
832 it = self.fastdesc
833 if it is not None:
833 if it is not None:
834 return it()
834 return it()
835 # we need to consume the iterator
835 # we need to consume the iterator
836 for x in self._consumegen():
836 for x in self._consumegen():
837 pass
837 pass
838 # recall the same code
838 # recall the same code
839 return iter(self)
839 return iter(self)
840
840
841 def _iterator(self):
841 def _iterator(self):
842 if self._finished:
842 if self._finished:
843 return iter(self._genlist)
843 return iter(self._genlist)
844
844
845 # We have to use this complex iteration strategy to allow multiple
845 # We have to use this complex iteration strategy to allow multiple
846 # iterations at the same time. We need to be able to catch revision
846 # iterations at the same time. We need to be able to catch revision
847 # removed from _consumegen and added to genlist in another instance.
847 # removed from _consumegen and added to genlist in another instance.
848 #
848 #
849 # Getting rid of it would provide an about 15% speed up on this
849 # Getting rid of it would provide an about 15% speed up on this
850 # iteration.
850 # iteration.
851 genlist = self._genlist
851 genlist = self._genlist
852 nextgen = self._consumegen()
852 nextgen = self._consumegen()
853 _len, _next = len, next # cache global lookup
853 _len, _next = len, next # cache global lookup
854 def gen():
854 def gen():
855 i = 0
855 i = 0
856 while True:
856 while True:
857 if i < _len(genlist):
857 if i < _len(genlist):
858 yield genlist[i]
858 yield genlist[i]
859 else:
859 else:
860 try:
860 try:
861 yield _next(nextgen)
861 yield _next(nextgen)
862 except StopIteration:
862 except StopIteration:
863 return
863 return
864 i += 1
864 i += 1
865 return gen()
865 return gen()
866
866
867 def _consumegen(self):
867 def _consumegen(self):
868 cache = self._cache
868 cache = self._cache
869 genlist = self._genlist.append
869 genlist = self._genlist.append
870 for item in self._gen:
870 for item in self._gen:
871 cache[item] = True
871 cache[item] = True
872 genlist(item)
872 genlist(item)
873 yield item
873 yield item
874 if not self._finished:
874 if not self._finished:
875 self._finished = True
875 self._finished = True
876 asc = self._genlist[:]
876 asc = self._genlist[:]
877 asc.sort()
877 asc.sort()
878 self._asclist = asc
878 self._asclist = asc
879 self.fastasc = asc.__iter__
879 self.fastasc = asc.__iter__
880 self.fastdesc = asc.__reversed__
880 self.fastdesc = asc.__reversed__
881
881
882 def __len__(self):
882 def __len__(self):
883 for x in self._consumegen():
883 for x in self._consumegen():
884 pass
884 pass
885 return len(self._genlist)
885 return len(self._genlist)
886
886
887 def sort(self, reverse=False):
887 def sort(self, reverse=False):
888 self._ascending = not reverse
888 self._ascending = not reverse
889
889
890 def reverse(self):
890 def reverse(self):
891 self._ascending = not self._ascending
891 self._ascending = not self._ascending
892
892
893 def isascending(self):
893 def isascending(self):
894 return self._ascending
894 return self._ascending
895
895
896 def isdescending(self):
896 def isdescending(self):
897 return not self._ascending
897 return not self._ascending
898
898
899 def istopo(self):
899 def istopo(self):
900 # not worth the trouble asserting if the two sets combined are still
900 # not worth the trouble asserting if the two sets combined are still
901 # in topographical order. Use the sort() predicate to explicitly sort
901 # in topographical order. Use the sort() predicate to explicitly sort
902 # again instead.
902 # again instead.
903 return False
903 return False
904
904
905 def first(self):
905 def first(self):
906 if self._ascending:
906 if self._ascending:
907 it = self.fastasc
907 it = self.fastasc
908 else:
908 else:
909 it = self.fastdesc
909 it = self.fastdesc
910 if it is None:
910 if it is None:
911 # we need to consume all and try again
911 # we need to consume all and try again
912 for x in self._consumegen():
912 for x in self._consumegen():
913 pass
913 pass
914 return self.first()
914 return self.first()
915 return next(it(), None)
915 return next(it(), None)
916
916
917 def last(self):
917 def last(self):
918 if self._ascending:
918 if self._ascending:
919 it = self.fastdesc
919 it = self.fastdesc
920 else:
920 else:
921 it = self.fastasc
921 it = self.fastasc
922 if it is None:
922 if it is None:
923 # we need to consume all and try again
923 # we need to consume all and try again
924 for x in self._consumegen():
924 for x in self._consumegen():
925 pass
925 pass
926 return self.last()
926 return self.last()
927 return next(it(), None)
927 return next(it(), None)
928
928
929 @encoding.strmethod
929 @encoding.strmethod
930 def __repr__(self):
930 def __repr__(self):
931 d = {False: '-', True: '+'}[self._ascending]
931 d = {False: '-', True: '+'}[self._ascending]
932 return '<%s%s>' % (_typename(self), d)
932 return '<%s%s>' % (_typename(self), d)
933
933
934 class _generatorsetasc(generatorset):
934 class _generatorsetasc(generatorset):
935 """Special case of generatorset optimized for ascending generators."""
935 """Special case of generatorset optimized for ascending generators."""
936
936
937 fastasc = generatorset._iterator
937 fastasc = generatorset._iterator
938
938
939 def __contains__(self, x):
939 def __contains__(self, x):
940 if x in self._cache:
940 if x in self._cache:
941 return self._cache[x]
941 return self._cache[x]
942
942
943 # Use new values only, as existing values would be cached.
943 # Use new values only, as existing values would be cached.
944 for l in self._consumegen():
944 for l in self._consumegen():
945 if l == x:
945 if l == x:
946 return True
946 return True
947 if l > x:
947 if l > x:
948 break
948 break
949
949
950 self._cache[x] = False
950 self._cache[x] = False
951 return False
951 return False
952
952
953 class _generatorsetdesc(generatorset):
953 class _generatorsetdesc(generatorset):
954 """Special case of generatorset optimized for descending generators."""
954 """Special case of generatorset optimized for descending generators."""
955
955
956 fastdesc = generatorset._iterator
956 fastdesc = generatorset._iterator
957
957
958 def __contains__(self, x):
958 def __contains__(self, x):
959 if x in self._cache:
959 if x in self._cache:
960 return self._cache[x]
960 return self._cache[x]
961
961
962 # Use new values only, as existing values would be cached.
962 # Use new values only, as existing values would be cached.
963 for l in self._consumegen():
963 for l in self._consumegen():
964 if l == x:
964 if l == x:
965 return True
965 return True
966 if l < x:
966 if l < x:
967 break
967 break
968
968
969 self._cache[x] = False
969 self._cache[x] = False
970 return False
970 return False
971
971
972 def spanset(repo, start=0, end=None):
972 def spanset(repo, start=0, end=None):
973 """Create a spanset that represents a range of repository revisions
973 """Create a spanset that represents a range of repository revisions
974
974
975 start: first revision included the set (default to 0)
975 start: first revision included the set (default to 0)
976 end: first revision excluded (last+1) (default to len(repo))
976 end: first revision excluded (last+1) (default to len(repo))
977
977
978 Spanset will be descending if `end` < `start`.
978 Spanset will be descending if `end` < `start`.
979 """
979 """
980 if end is None:
980 if end is None:
981 end = len(repo)
981 end = len(repo)
982 ascending = start <= end
982 ascending = start <= end
983 if not ascending:
983 if not ascending:
984 start, end = end + 1, start + 1
984 start, end = end + 1, start + 1
985 return _spanset(start, end, ascending, repo.changelog.filteredrevs)
985 return _spanset(start, end, ascending, repo.changelog.filteredrevs)
986
986
987 class _spanset(abstractsmartset):
987 class _spanset(abstractsmartset):
988 """Duck type for baseset class which represents a range of revisions and
988 """Duck type for baseset class which represents a range of revisions and
989 can work lazily and without having all the range in memory
989 can work lazily and without having all the range in memory
990
990
991 Note that spanset(x, y) behave almost like xrange(x, y) except for two
991 Note that spanset(x, y) behave almost like xrange(x, y) except for two
992 notable points:
992 notable points:
993 - when x < y it will be automatically descending,
993 - when x < y it will be automatically descending,
994 - revision filtered with this repoview will be skipped.
994 - revision filtered with this repoview will be skipped.
995
995
996 """
996 """
997 def __init__(self, start, end, ascending, hiddenrevs):
997 def __init__(self, start, end, ascending, hiddenrevs):
998 self._start = start
998 self._start = start
999 self._end = end
999 self._end = end
1000 self._ascending = ascending
1000 self._ascending = ascending
1001 self._hiddenrevs = hiddenrevs
1001 self._hiddenrevs = hiddenrevs
1002
1002
1003 def sort(self, reverse=False):
1003 def sort(self, reverse=False):
1004 self._ascending = not reverse
1004 self._ascending = not reverse
1005
1005
1006 def reverse(self):
1006 def reverse(self):
1007 self._ascending = not self._ascending
1007 self._ascending = not self._ascending
1008
1008
1009 def istopo(self):
1009 def istopo(self):
1010 # not worth the trouble asserting if the two sets combined are still
1010 # not worth the trouble asserting if the two sets combined are still
1011 # in topographical order. Use the sort() predicate to explicitly sort
1011 # in topographical order. Use the sort() predicate to explicitly sort
1012 # again instead.
1012 # again instead.
1013 return False
1013 return False
1014
1014
1015 def _iterfilter(self, iterrange):
1015 def _iterfilter(self, iterrange):
1016 s = self._hiddenrevs
1016 s = self._hiddenrevs
1017 for r in iterrange:
1017 for r in iterrange:
1018 if r not in s:
1018 if r not in s:
1019 yield r
1019 yield r
1020
1020
1021 def __iter__(self):
1021 def __iter__(self):
1022 if self._ascending:
1022 if self._ascending:
1023 return self.fastasc()
1023 return self.fastasc()
1024 else:
1024 else:
1025 return self.fastdesc()
1025 return self.fastdesc()
1026
1026
1027 def fastasc(self):
1027 def fastasc(self):
1028 iterrange = xrange(self._start, self._end)
1028 iterrange = xrange(self._start, self._end)
1029 if self._hiddenrevs:
1029 if self._hiddenrevs:
1030 return self._iterfilter(iterrange)
1030 return self._iterfilter(iterrange)
1031 return iter(iterrange)
1031 return iter(iterrange)
1032
1032
1033 def fastdesc(self):
1033 def fastdesc(self):
1034 iterrange = xrange(self._end - 1, self._start - 1, -1)
1034 iterrange = xrange(self._end - 1, self._start - 1, -1)
1035 if self._hiddenrevs:
1035 if self._hiddenrevs:
1036 return self._iterfilter(iterrange)
1036 return self._iterfilter(iterrange)
1037 return iter(iterrange)
1037 return iter(iterrange)
1038
1038
1039 def __contains__(self, rev):
1039 def __contains__(self, rev):
1040 hidden = self._hiddenrevs
1040 hidden = self._hiddenrevs
1041 return ((self._start <= rev < self._end)
1041 return ((self._start <= rev < self._end)
1042 and not (hidden and rev in hidden))
1042 and not (hidden and rev in hidden))
1043
1043
1044 def __nonzero__(self):
1044 def __nonzero__(self):
1045 for r in self:
1045 for r in self:
1046 return True
1046 return True
1047 return False
1047 return False
1048
1048
1049 __bool__ = __nonzero__
1049 __bool__ = __nonzero__
1050
1050
1051 def __len__(self):
1051 def __len__(self):
1052 if not self._hiddenrevs:
1052 if not self._hiddenrevs:
1053 return abs(self._end - self._start)
1053 return abs(self._end - self._start)
1054 else:
1054 else:
1055 count = 0
1055 count = 0
1056 start = self._start
1056 start = self._start
1057 end = self._end
1057 end = self._end
1058 for rev in self._hiddenrevs:
1058 for rev in self._hiddenrevs:
1059 if (end < rev <= start) or (start <= rev < end):
1059 if (end < rev <= start) or (start <= rev < end):
1060 count += 1
1060 count += 1
1061 return abs(self._end - self._start) - count
1061 return abs(self._end - self._start) - count
1062
1062
1063 def isascending(self):
1063 def isascending(self):
1064 return self._ascending
1064 return self._ascending
1065
1065
1066 def isdescending(self):
1066 def isdescending(self):
1067 return not self._ascending
1067 return not self._ascending
1068
1068
1069 def first(self):
1069 def first(self):
1070 if self._ascending:
1070 if self._ascending:
1071 it = self.fastasc
1071 it = self.fastasc
1072 else:
1072 else:
1073 it = self.fastdesc
1073 it = self.fastdesc
1074 for x in it():
1074 for x in it():
1075 return x
1075 return x
1076 return None
1076 return None
1077
1077
1078 def last(self):
1078 def last(self):
1079 if self._ascending:
1079 if self._ascending:
1080 it = self.fastdesc
1080 it = self.fastdesc
1081 else:
1081 else:
1082 it = self.fastasc
1082 it = self.fastasc
1083 for x in it():
1083 for x in it():
1084 return x
1084 return x
1085 return None
1085 return None
1086
1086
1087 def _slice(self, start, stop):
1087 def _slice(self, start, stop):
1088 if self._hiddenrevs:
1088 if self._hiddenrevs:
1089 # unoptimized since all hidden revisions in range has to be scanned
1089 # unoptimized since all hidden revisions in range has to be scanned
1090 return super(_spanset, self)._slice(start, stop)
1090 return super(_spanset, self)._slice(start, stop)
1091 if self._ascending:
1091 if self._ascending:
1092 x = min(self._start + start, self._end)
1092 x = min(self._start + start, self._end)
1093 y = min(self._start + stop, self._end)
1093 y = min(self._start + stop, self._end)
1094 else:
1094 else:
1095 x = max(self._end - stop, self._start)
1095 x = max(self._end - stop, self._start)
1096 y = max(self._end - start, self._start)
1096 y = max(self._end - start, self._start)
1097 return _spanset(x, y, self._ascending, self._hiddenrevs)
1097 return _spanset(x, y, self._ascending, self._hiddenrevs)
1098
1098
1099 @encoding.strmethod
1099 @encoding.strmethod
1100 def __repr__(self):
1100 def __repr__(self):
1101 d = {False: '-', True: '+'}[self._ascending]
1101 d = {False: '-', True: '+'}[self._ascending]
1102 return '<%s%s %d:%d>' % (_typename(self), d, self._start, self._end)
1102 return '<%s%s %d:%d>' % (_typename(self), d, self._start, self._end)
1103
1103
1104 class fullreposet(_spanset):
1104 class fullreposet(_spanset):
1105 """a set containing all revisions in the repo
1105 """a set containing all revisions in the repo
1106
1106
1107 This class exists to host special optimization and magic to handle virtual
1107 This class exists to host special optimization and magic to handle virtual
1108 revisions such as "null".
1108 revisions such as "null".
1109 """
1109 """
1110
1110
1111 def __init__(self, repo):
1111 def __init__(self, repo):
1112 super(fullreposet, self).__init__(0, len(repo), True,
1112 super(fullreposet, self).__init__(0, len(repo), True,
1113 repo.changelog.filteredrevs)
1113 repo.changelog.filteredrevs)
1114
1114
1115 def __and__(self, other):
1115 def __and__(self, other):
1116 """As self contains the whole repo, all of the other set should also be
1116 """As self contains the whole repo, all of the other set should also be
1117 in self. Therefore `self & other = other`.
1117 in self. Therefore `self & other = other`.
1118
1118
1119 This boldly assumes the other contains valid revs only.
1119 This boldly assumes the other contains valid revs only.
1120 """
1120 """
1121 # other not a smartset, make is so
1121 # other not a smartset, make is so
1122 if not util.safehasattr(other, 'isascending'):
1122 if not util.safehasattr(other, 'isascending'):
1123 # filter out hidden revision
1123 # filter out hidden revision
1124 # (this boldly assumes all smartset are pure)
1124 # (this boldly assumes all smartset are pure)
1125 #
1125 #
1126 # `other` was used with "&", let's assume this is a set like
1126 # `other` was used with "&", let's assume this is a set like
1127 # object.
1127 # object.
1128 other = baseset(other - self._hiddenrevs)
1128 other = baseset(other - self._hiddenrevs)
1129
1129
1130 other.sort(reverse=self.isdescending())
1130 other.sort(reverse=self.isdescending())
1131 return other
1131 return other
1132
1133 def prettyformat(revs):
1134 lines = []
1135 rs = pycompat.byterepr(revs)
1136 p = 0
1137 while p < len(rs):
1138 q = rs.find('<', p + 1)
1139 if q < 0:
1140 q = len(rs)
1141 l = rs.count('<', 0, p) - rs.count('>', 0, p)
1142 assert l >= 0
1143 lines.append((l, rs[p:q].rstrip()))
1144 p = q
1145 return '\n'.join(' ' * l + s for l, s in lines)
@@ -1,515 +1,530 b''
1 # stringutil.py - utility for generic string formatting, parsing, etc.
1 # stringutil.py - utility for generic string formatting, parsing, etc.
2 #
2 #
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 from __future__ import absolute_import
10 from __future__ import absolute_import
11
11
12 import ast
12 import ast
13 import codecs
13 import codecs
14 import re as remod
14 import re as remod
15 import textwrap
15 import textwrap
16
16
17 from ..i18n import _
17 from ..i18n import _
18 from ..thirdparty import attr
18 from ..thirdparty import attr
19
19
20 from .. import (
20 from .. import (
21 encoding,
21 encoding,
22 error,
22 error,
23 pycompat,
23 pycompat,
24 )
24 )
25
25
26 def pprint(o, bprefix=False):
26 def pprint(o, bprefix=False):
27 """Pretty print an object."""
27 """Pretty print an object."""
28 if isinstance(o, bytes):
28 if isinstance(o, bytes):
29 if bprefix:
29 if bprefix:
30 return "b'%s'" % escapestr(o)
30 return "b'%s'" % escapestr(o)
31 return "'%s'" % escapestr(o)
31 return "'%s'" % escapestr(o)
32 elif isinstance(o, bytearray):
32 elif isinstance(o, bytearray):
33 # codecs.escape_encode() can't handle bytearray, so escapestr fails
33 # codecs.escape_encode() can't handle bytearray, so escapestr fails
34 # without coercion.
34 # without coercion.
35 return "bytearray['%s']" % escapestr(bytes(o))
35 return "bytearray['%s']" % escapestr(bytes(o))
36 elif isinstance(o, list):
36 elif isinstance(o, list):
37 return '[%s]' % (b', '.join(pprint(a, bprefix=bprefix) for a in o))
37 return '[%s]' % (b', '.join(pprint(a, bprefix=bprefix) for a in o))
38 elif isinstance(o, dict):
38 elif isinstance(o, dict):
39 return '{%s}' % (b', '.join(
39 return '{%s}' % (b', '.join(
40 '%s: %s' % (pprint(k, bprefix=bprefix),
40 '%s: %s' % (pprint(k, bprefix=bprefix),
41 pprint(v, bprefix=bprefix))
41 pprint(v, bprefix=bprefix))
42 for k, v in sorted(o.items())))
42 for k, v in sorted(o.items())))
43 elif isinstance(o, tuple):
43 elif isinstance(o, tuple):
44 return '(%s)' % (b', '.join(pprint(a, bprefix=bprefix) for a in o))
44 return '(%s)' % (b', '.join(pprint(a, bprefix=bprefix) for a in o))
45 else:
45 else:
46 return pycompat.byterepr(o)
46 return pycompat.byterepr(o)
47
47
48 def prettyrepr(o):
49 """Pretty print a representation of a possibly-nested object"""
50 lines = []
51 rs = pycompat.byterepr(o)
52 p = 0
53 while p < len(rs):
54 q = rs.find('<', p + 1)
55 if q < 0:
56 q = len(rs)
57 l = rs.count('<', 0, p) - rs.count('>', 0, p)
58 assert l >= 0
59 lines.append((l, rs[p:q].rstrip()))
60 p = q
61 return '\n'.join(' ' * l + s for l, s in lines)
62
48 def binary(s):
63 def binary(s):
49 """return true if a string is binary data"""
64 """return true if a string is binary data"""
50 return bool(s and '\0' in s)
65 return bool(s and '\0' in s)
51
66
52 def stringmatcher(pattern, casesensitive=True):
67 def stringmatcher(pattern, casesensitive=True):
53 """
68 """
54 accepts a string, possibly starting with 're:' or 'literal:' prefix.
69 accepts a string, possibly starting with 're:' or 'literal:' prefix.
55 returns the matcher name, pattern, and matcher function.
70 returns the matcher name, pattern, and matcher function.
56 missing or unknown prefixes are treated as literal matches.
71 missing or unknown prefixes are treated as literal matches.
57
72
58 helper for tests:
73 helper for tests:
59 >>> def test(pattern, *tests):
74 >>> def test(pattern, *tests):
60 ... kind, pattern, matcher = stringmatcher(pattern)
75 ... kind, pattern, matcher = stringmatcher(pattern)
61 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
76 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
62 >>> def itest(pattern, *tests):
77 >>> def itest(pattern, *tests):
63 ... kind, pattern, matcher = stringmatcher(pattern, casesensitive=False)
78 ... kind, pattern, matcher = stringmatcher(pattern, casesensitive=False)
64 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
79 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
65
80
66 exact matching (no prefix):
81 exact matching (no prefix):
67 >>> test(b'abcdefg', b'abc', b'def', b'abcdefg')
82 >>> test(b'abcdefg', b'abc', b'def', b'abcdefg')
68 ('literal', 'abcdefg', [False, False, True])
83 ('literal', 'abcdefg', [False, False, True])
69
84
70 regex matching ('re:' prefix)
85 regex matching ('re:' prefix)
71 >>> test(b're:a.+b', b'nomatch', b'fooadef', b'fooadefbar')
86 >>> test(b're:a.+b', b'nomatch', b'fooadef', b'fooadefbar')
72 ('re', 'a.+b', [False, False, True])
87 ('re', 'a.+b', [False, False, True])
73
88
74 force exact matches ('literal:' prefix)
89 force exact matches ('literal:' prefix)
75 >>> test(b'literal:re:foobar', b'foobar', b're:foobar')
90 >>> test(b'literal:re:foobar', b'foobar', b're:foobar')
76 ('literal', 're:foobar', [False, True])
91 ('literal', 're:foobar', [False, True])
77
92
78 unknown prefixes are ignored and treated as literals
93 unknown prefixes are ignored and treated as literals
79 >>> test(b'foo:bar', b'foo', b'bar', b'foo:bar')
94 >>> test(b'foo:bar', b'foo', b'bar', b'foo:bar')
80 ('literal', 'foo:bar', [False, False, True])
95 ('literal', 'foo:bar', [False, False, True])
81
96
82 case insensitive regex matches
97 case insensitive regex matches
83 >>> itest(b're:A.+b', b'nomatch', b'fooadef', b'fooadefBar')
98 >>> itest(b're:A.+b', b'nomatch', b'fooadef', b'fooadefBar')
84 ('re', 'A.+b', [False, False, True])
99 ('re', 'A.+b', [False, False, True])
85
100
86 case insensitive literal matches
101 case insensitive literal matches
87 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg')
102 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg')
88 ('literal', 'ABCDEFG', [False, False, True])
103 ('literal', 'ABCDEFG', [False, False, True])
89 """
104 """
90 if pattern.startswith('re:'):
105 if pattern.startswith('re:'):
91 pattern = pattern[3:]
106 pattern = pattern[3:]
92 try:
107 try:
93 flags = 0
108 flags = 0
94 if not casesensitive:
109 if not casesensitive:
95 flags = remod.I
110 flags = remod.I
96 regex = remod.compile(pattern, flags)
111 regex = remod.compile(pattern, flags)
97 except remod.error as e:
112 except remod.error as e:
98 raise error.ParseError(_('invalid regular expression: %s')
113 raise error.ParseError(_('invalid regular expression: %s')
99 % e)
114 % e)
100 return 're', pattern, regex.search
115 return 're', pattern, regex.search
101 elif pattern.startswith('literal:'):
116 elif pattern.startswith('literal:'):
102 pattern = pattern[8:]
117 pattern = pattern[8:]
103
118
104 match = pattern.__eq__
119 match = pattern.__eq__
105
120
106 if not casesensitive:
121 if not casesensitive:
107 ipat = encoding.lower(pattern)
122 ipat = encoding.lower(pattern)
108 match = lambda s: ipat == encoding.lower(s)
123 match = lambda s: ipat == encoding.lower(s)
109 return 'literal', pattern, match
124 return 'literal', pattern, match
110
125
111 def shortuser(user):
126 def shortuser(user):
112 """Return a short representation of a user name or email address."""
127 """Return a short representation of a user name or email address."""
113 f = user.find('@')
128 f = user.find('@')
114 if f >= 0:
129 if f >= 0:
115 user = user[:f]
130 user = user[:f]
116 f = user.find('<')
131 f = user.find('<')
117 if f >= 0:
132 if f >= 0:
118 user = user[f + 1:]
133 user = user[f + 1:]
119 f = user.find(' ')
134 f = user.find(' ')
120 if f >= 0:
135 if f >= 0:
121 user = user[:f]
136 user = user[:f]
122 f = user.find('.')
137 f = user.find('.')
123 if f >= 0:
138 if f >= 0:
124 user = user[:f]
139 user = user[:f]
125 return user
140 return user
126
141
127 def emailuser(user):
142 def emailuser(user):
128 """Return the user portion of an email address."""
143 """Return the user portion of an email address."""
129 f = user.find('@')
144 f = user.find('@')
130 if f >= 0:
145 if f >= 0:
131 user = user[:f]
146 user = user[:f]
132 f = user.find('<')
147 f = user.find('<')
133 if f >= 0:
148 if f >= 0:
134 user = user[f + 1:]
149 user = user[f + 1:]
135 return user
150 return user
136
151
137 def email(author):
152 def email(author):
138 '''get email of author.'''
153 '''get email of author.'''
139 r = author.find('>')
154 r = author.find('>')
140 if r == -1:
155 if r == -1:
141 r = None
156 r = None
142 return author[author.find('<') + 1:r]
157 return author[author.find('<') + 1:r]
143
158
144 def person(author):
159 def person(author):
145 """Returns the name before an email address,
160 """Returns the name before an email address,
146 interpreting it as per RFC 5322
161 interpreting it as per RFC 5322
147
162
148 >>> person(b'foo@bar')
163 >>> person(b'foo@bar')
149 'foo'
164 'foo'
150 >>> person(b'Foo Bar <foo@bar>')
165 >>> person(b'Foo Bar <foo@bar>')
151 'Foo Bar'
166 'Foo Bar'
152 >>> person(b'"Foo Bar" <foo@bar>')
167 >>> person(b'"Foo Bar" <foo@bar>')
153 'Foo Bar'
168 'Foo Bar'
154 >>> person(b'"Foo \"buz\" Bar" <foo@bar>')
169 >>> person(b'"Foo \"buz\" Bar" <foo@bar>')
155 'Foo "buz" Bar'
170 'Foo "buz" Bar'
156 >>> # The following are invalid, but do exist in real-life
171 >>> # The following are invalid, but do exist in real-life
157 ...
172 ...
158 >>> person(b'Foo "buz" Bar <foo@bar>')
173 >>> person(b'Foo "buz" Bar <foo@bar>')
159 'Foo "buz" Bar'
174 'Foo "buz" Bar'
160 >>> person(b'"Foo Bar <foo@bar>')
175 >>> person(b'"Foo Bar <foo@bar>')
161 'Foo Bar'
176 'Foo Bar'
162 """
177 """
163 if '@' not in author:
178 if '@' not in author:
164 return author
179 return author
165 f = author.find('<')
180 f = author.find('<')
166 if f != -1:
181 if f != -1:
167 return author[:f].strip(' "').replace('\\"', '"')
182 return author[:f].strip(' "').replace('\\"', '"')
168 f = author.find('@')
183 f = author.find('@')
169 return author[:f].replace('.', ' ')
184 return author[:f].replace('.', ' ')
170
185
171 @attr.s(hash=True)
186 @attr.s(hash=True)
172 class mailmapping(object):
187 class mailmapping(object):
173 '''Represents a username/email key or value in
188 '''Represents a username/email key or value in
174 a mailmap file'''
189 a mailmap file'''
175 email = attr.ib()
190 email = attr.ib()
176 name = attr.ib(default=None)
191 name = attr.ib(default=None)
177
192
178 def _ismailmaplineinvalid(names, emails):
193 def _ismailmaplineinvalid(names, emails):
179 '''Returns True if the parsed names and emails
194 '''Returns True if the parsed names and emails
180 in a mailmap entry are invalid.
195 in a mailmap entry are invalid.
181
196
182 >>> # No names or emails fails
197 >>> # No names or emails fails
183 >>> names, emails = [], []
198 >>> names, emails = [], []
184 >>> _ismailmaplineinvalid(names, emails)
199 >>> _ismailmaplineinvalid(names, emails)
185 True
200 True
186 >>> # Only one email fails
201 >>> # Only one email fails
187 >>> emails = [b'email@email.com']
202 >>> emails = [b'email@email.com']
188 >>> _ismailmaplineinvalid(names, emails)
203 >>> _ismailmaplineinvalid(names, emails)
189 True
204 True
190 >>> # One email and one name passes
205 >>> # One email and one name passes
191 >>> names = [b'Test Name']
206 >>> names = [b'Test Name']
192 >>> _ismailmaplineinvalid(names, emails)
207 >>> _ismailmaplineinvalid(names, emails)
193 False
208 False
194 >>> # No names but two emails passes
209 >>> # No names but two emails passes
195 >>> names = []
210 >>> names = []
196 >>> emails = [b'proper@email.com', b'commit@email.com']
211 >>> emails = [b'proper@email.com', b'commit@email.com']
197 >>> _ismailmaplineinvalid(names, emails)
212 >>> _ismailmaplineinvalid(names, emails)
198 False
213 False
199 '''
214 '''
200 return not emails or not names and len(emails) < 2
215 return not emails or not names and len(emails) < 2
201
216
202 def parsemailmap(mailmapcontent):
217 def parsemailmap(mailmapcontent):
203 """Parses data in the .mailmap format
218 """Parses data in the .mailmap format
204
219
205 >>> mmdata = b"\\n".join([
220 >>> mmdata = b"\\n".join([
206 ... b'# Comment',
221 ... b'# Comment',
207 ... b'Name <commit1@email.xx>',
222 ... b'Name <commit1@email.xx>',
208 ... b'<name@email.xx> <commit2@email.xx>',
223 ... b'<name@email.xx> <commit2@email.xx>',
209 ... b'Name <proper@email.xx> <commit3@email.xx>',
224 ... b'Name <proper@email.xx> <commit3@email.xx>',
210 ... b'Name <proper@email.xx> Commit <commit4@email.xx>',
225 ... b'Name <proper@email.xx> Commit <commit4@email.xx>',
211 ... ])
226 ... ])
212 >>> mm = parsemailmap(mmdata)
227 >>> mm = parsemailmap(mmdata)
213 >>> for key in sorted(mm.keys()):
228 >>> for key in sorted(mm.keys()):
214 ... print(key)
229 ... print(key)
215 mailmapping(email='commit1@email.xx', name=None)
230 mailmapping(email='commit1@email.xx', name=None)
216 mailmapping(email='commit2@email.xx', name=None)
231 mailmapping(email='commit2@email.xx', name=None)
217 mailmapping(email='commit3@email.xx', name=None)
232 mailmapping(email='commit3@email.xx', name=None)
218 mailmapping(email='commit4@email.xx', name='Commit')
233 mailmapping(email='commit4@email.xx', name='Commit')
219 >>> for val in sorted(mm.values()):
234 >>> for val in sorted(mm.values()):
220 ... print(val)
235 ... print(val)
221 mailmapping(email='commit1@email.xx', name='Name')
236 mailmapping(email='commit1@email.xx', name='Name')
222 mailmapping(email='name@email.xx', name=None)
237 mailmapping(email='name@email.xx', name=None)
223 mailmapping(email='proper@email.xx', name='Name')
238 mailmapping(email='proper@email.xx', name='Name')
224 mailmapping(email='proper@email.xx', name='Name')
239 mailmapping(email='proper@email.xx', name='Name')
225 """
240 """
226 mailmap = {}
241 mailmap = {}
227
242
228 if mailmapcontent is None:
243 if mailmapcontent is None:
229 return mailmap
244 return mailmap
230
245
231 for line in mailmapcontent.splitlines():
246 for line in mailmapcontent.splitlines():
232
247
233 # Don't bother checking the line if it is a comment or
248 # Don't bother checking the line if it is a comment or
234 # is an improperly formed author field
249 # is an improperly formed author field
235 if line.lstrip().startswith('#'):
250 if line.lstrip().startswith('#'):
236 continue
251 continue
237
252
238 # names, emails hold the parsed emails and names for each line
253 # names, emails hold the parsed emails and names for each line
239 # name_builder holds the words in a persons name
254 # name_builder holds the words in a persons name
240 names, emails = [], []
255 names, emails = [], []
241 namebuilder = []
256 namebuilder = []
242
257
243 for element in line.split():
258 for element in line.split():
244 if element.startswith('#'):
259 if element.startswith('#'):
245 # If we reach a comment in the mailmap file, move on
260 # If we reach a comment in the mailmap file, move on
246 break
261 break
247
262
248 elif element.startswith('<') and element.endswith('>'):
263 elif element.startswith('<') and element.endswith('>'):
249 # We have found an email.
264 # We have found an email.
250 # Parse it, and finalize any names from earlier
265 # Parse it, and finalize any names from earlier
251 emails.append(element[1:-1]) # Slice off the "<>"
266 emails.append(element[1:-1]) # Slice off the "<>"
252
267
253 if namebuilder:
268 if namebuilder:
254 names.append(' '.join(namebuilder))
269 names.append(' '.join(namebuilder))
255 namebuilder = []
270 namebuilder = []
256
271
257 # Break if we have found a second email, any other
272 # Break if we have found a second email, any other
258 # data does not fit the spec for .mailmap
273 # data does not fit the spec for .mailmap
259 if len(emails) > 1:
274 if len(emails) > 1:
260 break
275 break
261
276
262 else:
277 else:
263 # We have found another word in the committers name
278 # We have found another word in the committers name
264 namebuilder.append(element)
279 namebuilder.append(element)
265
280
266 # Check to see if we have parsed the line into a valid form
281 # Check to see if we have parsed the line into a valid form
267 # We require at least one email, and either at least one
282 # We require at least one email, and either at least one
268 # name or a second email
283 # name or a second email
269 if _ismailmaplineinvalid(names, emails):
284 if _ismailmaplineinvalid(names, emails):
270 continue
285 continue
271
286
272 mailmapkey = mailmapping(
287 mailmapkey = mailmapping(
273 email=emails[-1],
288 email=emails[-1],
274 name=names[-1] if len(names) == 2 else None,
289 name=names[-1] if len(names) == 2 else None,
275 )
290 )
276
291
277 mailmap[mailmapkey] = mailmapping(
292 mailmap[mailmapkey] = mailmapping(
278 email=emails[0],
293 email=emails[0],
279 name=names[0] if names else None,
294 name=names[0] if names else None,
280 )
295 )
281
296
282 return mailmap
297 return mailmap
283
298
284 def mapname(mailmap, author):
299 def mapname(mailmap, author):
285 """Returns the author field according to the mailmap cache, or
300 """Returns the author field according to the mailmap cache, or
286 the original author field.
301 the original author field.
287
302
288 >>> mmdata = b"\\n".join([
303 >>> mmdata = b"\\n".join([
289 ... b'# Comment',
304 ... b'# Comment',
290 ... b'Name <commit1@email.xx>',
305 ... b'Name <commit1@email.xx>',
291 ... b'<name@email.xx> <commit2@email.xx>',
306 ... b'<name@email.xx> <commit2@email.xx>',
292 ... b'Name <proper@email.xx> <commit3@email.xx>',
307 ... b'Name <proper@email.xx> <commit3@email.xx>',
293 ... b'Name <proper@email.xx> Commit <commit4@email.xx>',
308 ... b'Name <proper@email.xx> Commit <commit4@email.xx>',
294 ... ])
309 ... ])
295 >>> m = parsemailmap(mmdata)
310 >>> m = parsemailmap(mmdata)
296 >>> mapname(m, b'Commit <commit1@email.xx>')
311 >>> mapname(m, b'Commit <commit1@email.xx>')
297 'Name <commit1@email.xx>'
312 'Name <commit1@email.xx>'
298 >>> mapname(m, b'Name <commit2@email.xx>')
313 >>> mapname(m, b'Name <commit2@email.xx>')
299 'Name <name@email.xx>'
314 'Name <name@email.xx>'
300 >>> mapname(m, b'Commit <commit3@email.xx>')
315 >>> mapname(m, b'Commit <commit3@email.xx>')
301 'Name <proper@email.xx>'
316 'Name <proper@email.xx>'
302 >>> mapname(m, b'Commit <commit4@email.xx>')
317 >>> mapname(m, b'Commit <commit4@email.xx>')
303 'Name <proper@email.xx>'
318 'Name <proper@email.xx>'
304 >>> mapname(m, b'Unknown Name <unknown@email.com>')
319 >>> mapname(m, b'Unknown Name <unknown@email.com>')
305 'Unknown Name <unknown@email.com>'
320 'Unknown Name <unknown@email.com>'
306 """
321 """
307 # If the author field coming in isn't in the correct format,
322 # If the author field coming in isn't in the correct format,
308 # or the mailmap is empty just return the original author field
323 # or the mailmap is empty just return the original author field
309 if not isauthorwellformed(author) or not mailmap:
324 if not isauthorwellformed(author) or not mailmap:
310 return author
325 return author
311
326
312 # Turn the user name into a mailmapping
327 # Turn the user name into a mailmapping
313 commit = mailmapping(name=person(author), email=email(author))
328 commit = mailmapping(name=person(author), email=email(author))
314
329
315 try:
330 try:
316 # Try and use both the commit email and name as the key
331 # Try and use both the commit email and name as the key
317 proper = mailmap[commit]
332 proper = mailmap[commit]
318
333
319 except KeyError:
334 except KeyError:
320 # If the lookup fails, use just the email as the key instead
335 # If the lookup fails, use just the email as the key instead
321 # We call this commit2 as not to erase original commit fields
336 # We call this commit2 as not to erase original commit fields
322 commit2 = mailmapping(email=commit.email)
337 commit2 = mailmapping(email=commit.email)
323 proper = mailmap.get(commit2, mailmapping(None, None))
338 proper = mailmap.get(commit2, mailmapping(None, None))
324
339
325 # Return the author field with proper values filled in
340 # Return the author field with proper values filled in
326 return '%s <%s>' % (
341 return '%s <%s>' % (
327 proper.name if proper.name else commit.name,
342 proper.name if proper.name else commit.name,
328 proper.email if proper.email else commit.email,
343 proper.email if proper.email else commit.email,
329 )
344 )
330
345
331 _correctauthorformat = remod.compile(br'^[^<]+\s\<[^<>]+@[^<>]+\>$')
346 _correctauthorformat = remod.compile(br'^[^<]+\s\<[^<>]+@[^<>]+\>$')
332
347
333 def isauthorwellformed(author):
348 def isauthorwellformed(author):
334 '''Return True if the author field is well formed
349 '''Return True if the author field is well formed
335 (ie "Contributor Name <contrib@email.dom>")
350 (ie "Contributor Name <contrib@email.dom>")
336
351
337 >>> isauthorwellformed(b'Good Author <good@author.com>')
352 >>> isauthorwellformed(b'Good Author <good@author.com>')
338 True
353 True
339 >>> isauthorwellformed(b'Author <good@author.com>')
354 >>> isauthorwellformed(b'Author <good@author.com>')
340 True
355 True
341 >>> isauthorwellformed(b'Bad Author')
356 >>> isauthorwellformed(b'Bad Author')
342 False
357 False
343 >>> isauthorwellformed(b'Bad Author <author@author.com')
358 >>> isauthorwellformed(b'Bad Author <author@author.com')
344 False
359 False
345 >>> isauthorwellformed(b'Bad Author author@author.com')
360 >>> isauthorwellformed(b'Bad Author author@author.com')
346 False
361 False
347 >>> isauthorwellformed(b'<author@author.com>')
362 >>> isauthorwellformed(b'<author@author.com>')
348 False
363 False
349 >>> isauthorwellformed(b'Bad Author <author>')
364 >>> isauthorwellformed(b'Bad Author <author>')
350 False
365 False
351 '''
366 '''
352 return _correctauthorformat.match(author) is not None
367 return _correctauthorformat.match(author) is not None
353
368
354 def ellipsis(text, maxlength=400):
369 def ellipsis(text, maxlength=400):
355 """Trim string to at most maxlength (default: 400) columns in display."""
370 """Trim string to at most maxlength (default: 400) columns in display."""
356 return encoding.trim(text, maxlength, ellipsis='...')
371 return encoding.trim(text, maxlength, ellipsis='...')
357
372
358 def escapestr(s):
373 def escapestr(s):
359 # call underlying function of s.encode('string_escape') directly for
374 # call underlying function of s.encode('string_escape') directly for
360 # Python 3 compatibility
375 # Python 3 compatibility
361 return codecs.escape_encode(s)[0]
376 return codecs.escape_encode(s)[0]
362
377
363 def unescapestr(s):
378 def unescapestr(s):
364 return codecs.escape_decode(s)[0]
379 return codecs.escape_decode(s)[0]
365
380
366 def forcebytestr(obj):
381 def forcebytestr(obj):
367 """Portably format an arbitrary object (e.g. exception) into a byte
382 """Portably format an arbitrary object (e.g. exception) into a byte
368 string."""
383 string."""
369 try:
384 try:
370 return pycompat.bytestr(obj)
385 return pycompat.bytestr(obj)
371 except UnicodeEncodeError:
386 except UnicodeEncodeError:
372 # non-ascii string, may be lossy
387 # non-ascii string, may be lossy
373 return pycompat.bytestr(encoding.strtolocal(str(obj)))
388 return pycompat.bytestr(encoding.strtolocal(str(obj)))
374
389
375 def uirepr(s):
390 def uirepr(s):
376 # Avoid double backslash in Windows path repr()
391 # Avoid double backslash in Windows path repr()
377 return pycompat.byterepr(pycompat.bytestr(s)).replace(b'\\\\', b'\\')
392 return pycompat.byterepr(pycompat.bytestr(s)).replace(b'\\\\', b'\\')
378
393
379 # delay import of textwrap
394 # delay import of textwrap
380 def _MBTextWrapper(**kwargs):
395 def _MBTextWrapper(**kwargs):
381 class tw(textwrap.TextWrapper):
396 class tw(textwrap.TextWrapper):
382 """
397 """
383 Extend TextWrapper for width-awareness.
398 Extend TextWrapper for width-awareness.
384
399
385 Neither number of 'bytes' in any encoding nor 'characters' is
400 Neither number of 'bytes' in any encoding nor 'characters' is
386 appropriate to calculate terminal columns for specified string.
401 appropriate to calculate terminal columns for specified string.
387
402
388 Original TextWrapper implementation uses built-in 'len()' directly,
403 Original TextWrapper implementation uses built-in 'len()' directly,
389 so overriding is needed to use width information of each characters.
404 so overriding is needed to use width information of each characters.
390
405
391 In addition, characters classified into 'ambiguous' width are
406 In addition, characters classified into 'ambiguous' width are
392 treated as wide in East Asian area, but as narrow in other.
407 treated as wide in East Asian area, but as narrow in other.
393
408
394 This requires use decision to determine width of such characters.
409 This requires use decision to determine width of such characters.
395 """
410 """
396 def _cutdown(self, ucstr, space_left):
411 def _cutdown(self, ucstr, space_left):
397 l = 0
412 l = 0
398 colwidth = encoding.ucolwidth
413 colwidth = encoding.ucolwidth
399 for i in xrange(len(ucstr)):
414 for i in xrange(len(ucstr)):
400 l += colwidth(ucstr[i])
415 l += colwidth(ucstr[i])
401 if space_left < l:
416 if space_left < l:
402 return (ucstr[:i], ucstr[i:])
417 return (ucstr[:i], ucstr[i:])
403 return ucstr, ''
418 return ucstr, ''
404
419
405 # overriding of base class
420 # overriding of base class
406 def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
421 def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
407 space_left = max(width - cur_len, 1)
422 space_left = max(width - cur_len, 1)
408
423
409 if self.break_long_words:
424 if self.break_long_words:
410 cut, res = self._cutdown(reversed_chunks[-1], space_left)
425 cut, res = self._cutdown(reversed_chunks[-1], space_left)
411 cur_line.append(cut)
426 cur_line.append(cut)
412 reversed_chunks[-1] = res
427 reversed_chunks[-1] = res
413 elif not cur_line:
428 elif not cur_line:
414 cur_line.append(reversed_chunks.pop())
429 cur_line.append(reversed_chunks.pop())
415
430
416 # this overriding code is imported from TextWrapper of Python 2.6
431 # this overriding code is imported from TextWrapper of Python 2.6
417 # to calculate columns of string by 'encoding.ucolwidth()'
432 # to calculate columns of string by 'encoding.ucolwidth()'
418 def _wrap_chunks(self, chunks):
433 def _wrap_chunks(self, chunks):
419 colwidth = encoding.ucolwidth
434 colwidth = encoding.ucolwidth
420
435
421 lines = []
436 lines = []
422 if self.width <= 0:
437 if self.width <= 0:
423 raise ValueError("invalid width %r (must be > 0)" % self.width)
438 raise ValueError("invalid width %r (must be > 0)" % self.width)
424
439
425 # Arrange in reverse order so items can be efficiently popped
440 # Arrange in reverse order so items can be efficiently popped
426 # from a stack of chucks.
441 # from a stack of chucks.
427 chunks.reverse()
442 chunks.reverse()
428
443
429 while chunks:
444 while chunks:
430
445
431 # Start the list of chunks that will make up the current line.
446 # Start the list of chunks that will make up the current line.
432 # cur_len is just the length of all the chunks in cur_line.
447 # cur_len is just the length of all the chunks in cur_line.
433 cur_line = []
448 cur_line = []
434 cur_len = 0
449 cur_len = 0
435
450
436 # Figure out which static string will prefix this line.
451 # Figure out which static string will prefix this line.
437 if lines:
452 if lines:
438 indent = self.subsequent_indent
453 indent = self.subsequent_indent
439 else:
454 else:
440 indent = self.initial_indent
455 indent = self.initial_indent
441
456
442 # Maximum width for this line.
457 # Maximum width for this line.
443 width = self.width - len(indent)
458 width = self.width - len(indent)
444
459
445 # First chunk on line is whitespace -- drop it, unless this
460 # First chunk on line is whitespace -- drop it, unless this
446 # is the very beginning of the text (i.e. no lines started yet).
461 # is the very beginning of the text (i.e. no lines started yet).
447 if self.drop_whitespace and chunks[-1].strip() == r'' and lines:
462 if self.drop_whitespace and chunks[-1].strip() == r'' and lines:
448 del chunks[-1]
463 del chunks[-1]
449
464
450 while chunks:
465 while chunks:
451 l = colwidth(chunks[-1])
466 l = colwidth(chunks[-1])
452
467
453 # Can at least squeeze this chunk onto the current line.
468 # Can at least squeeze this chunk onto the current line.
454 if cur_len + l <= width:
469 if cur_len + l <= width:
455 cur_line.append(chunks.pop())
470 cur_line.append(chunks.pop())
456 cur_len += l
471 cur_len += l
457
472
458 # Nope, this line is full.
473 # Nope, this line is full.
459 else:
474 else:
460 break
475 break
461
476
462 # The current line is full, and the next chunk is too big to
477 # The current line is full, and the next chunk is too big to
463 # fit on *any* line (not just this one).
478 # fit on *any* line (not just this one).
464 if chunks and colwidth(chunks[-1]) > width:
479 if chunks and colwidth(chunks[-1]) > width:
465 self._handle_long_word(chunks, cur_line, cur_len, width)
480 self._handle_long_word(chunks, cur_line, cur_len, width)
466
481
467 # If the last chunk on this line is all whitespace, drop it.
482 # If the last chunk on this line is all whitespace, drop it.
468 if (self.drop_whitespace and
483 if (self.drop_whitespace and
469 cur_line and cur_line[-1].strip() == r''):
484 cur_line and cur_line[-1].strip() == r''):
470 del cur_line[-1]
485 del cur_line[-1]
471
486
472 # Convert current line back to a string and store it in list
487 # Convert current line back to a string and store it in list
473 # of all lines (return value).
488 # of all lines (return value).
474 if cur_line:
489 if cur_line:
475 lines.append(indent + r''.join(cur_line))
490 lines.append(indent + r''.join(cur_line))
476
491
477 return lines
492 return lines
478
493
479 global _MBTextWrapper
494 global _MBTextWrapper
480 _MBTextWrapper = tw
495 _MBTextWrapper = tw
481 return tw(**kwargs)
496 return tw(**kwargs)
482
497
483 def wrap(line, width, initindent='', hangindent=''):
498 def wrap(line, width, initindent='', hangindent=''):
484 maxindent = max(len(hangindent), len(initindent))
499 maxindent = max(len(hangindent), len(initindent))
485 if width <= maxindent:
500 if width <= maxindent:
486 # adjust for weird terminal size
501 # adjust for weird terminal size
487 width = max(78, maxindent + 1)
502 width = max(78, maxindent + 1)
488 line = line.decode(pycompat.sysstr(encoding.encoding),
503 line = line.decode(pycompat.sysstr(encoding.encoding),
489 pycompat.sysstr(encoding.encodingmode))
504 pycompat.sysstr(encoding.encodingmode))
490 initindent = initindent.decode(pycompat.sysstr(encoding.encoding),
505 initindent = initindent.decode(pycompat.sysstr(encoding.encoding),
491 pycompat.sysstr(encoding.encodingmode))
506 pycompat.sysstr(encoding.encodingmode))
492 hangindent = hangindent.decode(pycompat.sysstr(encoding.encoding),
507 hangindent = hangindent.decode(pycompat.sysstr(encoding.encoding),
493 pycompat.sysstr(encoding.encodingmode))
508 pycompat.sysstr(encoding.encodingmode))
494 wrapper = _MBTextWrapper(width=width,
509 wrapper = _MBTextWrapper(width=width,
495 initial_indent=initindent,
510 initial_indent=initindent,
496 subsequent_indent=hangindent)
511 subsequent_indent=hangindent)
497 return wrapper.fill(line).encode(pycompat.sysstr(encoding.encoding))
512 return wrapper.fill(line).encode(pycompat.sysstr(encoding.encoding))
498
513
499 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True, 'always': True,
514 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True, 'always': True,
500 '0': False, 'no': False, 'false': False, 'off': False,
515 '0': False, 'no': False, 'false': False, 'off': False,
501 'never': False}
516 'never': False}
502
517
503 def parsebool(s):
518 def parsebool(s):
504 """Parse s into a boolean.
519 """Parse s into a boolean.
505
520
506 If s is not a valid boolean, returns None.
521 If s is not a valid boolean, returns None.
507 """
522 """
508 return _booleans.get(s.lower(), None)
523 return _booleans.get(s.lower(), None)
509
524
510 def evalpythonliteral(s):
525 def evalpythonliteral(s):
511 """Evaluate a string containing a Python literal expression"""
526 """Evaluate a string containing a Python literal expression"""
512 # We could backport our tokenizer hack to rewrite '' to u'' if we want
527 # We could backport our tokenizer hack to rewrite '' to u'' if we want
513 if pycompat.ispy3:
528 if pycompat.ispy3:
514 return ast.literal_eval(s.decode('latin1'))
529 return ast.literal_eval(s.decode('latin1'))
515 return ast.literal_eval(s)
530 return ast.literal_eval(s)
@@ -1,3487 +1,3488 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 $ commit()
72 $ commit()
73 > {
73 > {
74 > rev=$1
74 > rev=$1
75 > msg=$2
75 > msg=$2
76 > shift 2
76 > shift 2
77 > if [ "$#" -gt 0 ]; then
77 > if [ "$#" -gt 0 ]; then
78 > hg debugsetparents "$@"
78 > hg debugsetparents "$@"
79 > fi
79 > fi
80 > echo $rev > a
80 > echo $rev > a
81 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
81 > hg commit -Aqd "$rev 0" -m "($rev) $msg"
82 > }
82 > }
83
83
84 $ cat > printrevset.py <<EOF
84 $ cat > printrevset.py <<EOF
85 > from __future__ import absolute_import
85 > from __future__ import absolute_import
86 > from mercurial import (
86 > from mercurial import (
87 > cmdutil,
87 > cmdutil,
88 > commands,
88 > commands,
89 > extensions,
89 > extensions,
90 > logcmdutil,
90 > logcmdutil,
91 > revsetlang,
91 > revsetlang,
92 > smartset,
92 > smartset,
93 > )
93 > )
94 > from mercurial.utils import stringutil
94 >
95 >
95 > def logrevset(repo, pats, opts):
96 > def logrevset(repo, pats, opts):
96 > revs = logcmdutil._initialrevs(repo, opts)
97 > revs = logcmdutil._initialrevs(repo, opts)
97 > if not revs:
98 > if not revs:
98 > return None
99 > return None
99 > match, pats, slowpath = logcmdutil._makematcher(repo, revs, pats, opts)
100 > match, pats, slowpath = logcmdutil._makematcher(repo, revs, pats, opts)
100 > return logcmdutil._makerevset(repo, match, pats, slowpath, opts)
101 > return logcmdutil._makerevset(repo, match, pats, slowpath, opts)
101 >
102 >
102 > def uisetup(ui):
103 > def uisetup(ui):
103 > def printrevset(orig, repo, pats, opts):
104 > def printrevset(orig, repo, pats, opts):
104 > revs, filematcher = orig(repo, pats, opts)
105 > revs, filematcher = orig(repo, pats, opts)
105 > if opts.get(b'print_revset'):
106 > if opts.get(b'print_revset'):
106 > expr = logrevset(repo, pats, opts)
107 > expr = logrevset(repo, pats, opts)
107 > if expr:
108 > if expr:
108 > tree = revsetlang.parse(expr)
109 > tree = revsetlang.parse(expr)
109 > tree = revsetlang.analyze(tree)
110 > tree = revsetlang.analyze(tree)
110 > else:
111 > else:
111 > tree = []
112 > tree = []
112 > ui = repo.ui
113 > ui = repo.ui
113 > ui.write(b'%r\n' % (opts.get(b'rev', []),))
114 > ui.write(b'%r\n' % (opts.get(b'rev', []),))
114 > ui.write(revsetlang.prettyformat(tree) + b'\n')
115 > ui.write(revsetlang.prettyformat(tree) + b'\n')
115 > ui.write(smartset.prettyformat(revs) + b'\n')
116 > ui.write(stringutil.prettyrepr(revs) + b'\n')
116 > revs = smartset.baseset() # display no revisions
117 > revs = smartset.baseset() # display no revisions
117 > return revs, filematcher
118 > return revs, filematcher
118 > extensions.wrapfunction(logcmdutil, 'getrevs', printrevset)
119 > extensions.wrapfunction(logcmdutil, 'getrevs', printrevset)
119 > aliases, entry = cmdutil.findcmd(b'log', commands.table)
120 > aliases, entry = cmdutil.findcmd(b'log', commands.table)
120 > entry[1].append((b'', b'print-revset', False,
121 > entry[1].append((b'', b'print-revset', False,
121 > b'print generated revset and exit (DEPRECATED)'))
122 > b'print generated revset and exit (DEPRECATED)'))
122 > EOF
123 > EOF
123
124
124 $ echo "[extensions]" >> $HGRCPATH
125 $ echo "[extensions]" >> $HGRCPATH
125 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
126 $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
126
127
127 $ hg init repo
128 $ hg init repo
128 $ cd repo
129 $ cd repo
129
130
130 Empty repo:
131 Empty repo:
131
132
132 $ hg log -G
133 $ hg log -G
133
134
134
135
135 Building DAG:
136 Building DAG:
136
137
137 $ commit 0 "root"
138 $ commit 0 "root"
138 $ commit 1 "collapse" 0
139 $ commit 1 "collapse" 0
139 $ commit 2 "collapse" 1
140 $ commit 2 "collapse" 1
140 $ commit 3 "collapse" 2
141 $ commit 3 "collapse" 2
141 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
142 $ commit 4 "merge two known; one immediate left, one immediate right" 1 3
142 $ commit 5 "expand" 3 4
143 $ commit 5 "expand" 3 4
143 $ commit 6 "merge two known; one immediate left, one far left" 2 5
144 $ commit 6 "merge two known; one immediate left, one far left" 2 5
144 $ commit 7 "expand" 2 5
145 $ commit 7 "expand" 2 5
145 $ commit 8 "merge two known; one immediate left, one far right" 0 7
146 $ commit 8 "merge two known; one immediate left, one far right" 0 7
146 $ commit 9 "expand" 7 8
147 $ commit 9 "expand" 7 8
147 $ commit 10 "merge two known; one immediate left, one near right" 0 6
148 $ commit 10 "merge two known; one immediate left, one near right" 0 6
148 $ commit 11 "expand" 6 10
149 $ commit 11 "expand" 6 10
149 $ commit 12 "merge two known; one immediate right, one far left" 1 9
150 $ commit 12 "merge two known; one immediate right, one far left" 1 9
150 $ commit 13 "expand" 9 11
151 $ commit 13 "expand" 9 11
151 $ commit 14 "merge two known; one immediate right, one far right" 0 12
152 $ commit 14 "merge two known; one immediate right, one far right" 0 12
152 $ commit 15 "expand" 13 14
153 $ commit 15 "expand" 13 14
153 $ commit 16 "merge two known; one immediate right, one near right" 0 1
154 $ commit 16 "merge two known; one immediate right, one near right" 0 1
154 $ commit 17 "expand" 12 16
155 $ commit 17 "expand" 12 16
155 $ commit 18 "merge two known; two far left" 1 15
156 $ commit 18 "merge two known; two far left" 1 15
156 $ commit 19 "expand" 15 17
157 $ commit 19 "expand" 15 17
157 $ commit 20 "merge two known; two far right" 0 18
158 $ commit 20 "merge two known; two far right" 0 18
158 $ commit 21 "expand" 19 20
159 $ commit 21 "expand" 19 20
159 $ commit 22 "merge two known; one far left, one far right" 18 21
160 $ commit 22 "merge two known; one far left, one far right" 18 21
160 $ commit 23 "merge one known; immediate left" 1 22
161 $ commit 23 "merge one known; immediate left" 1 22
161 $ commit 24 "merge one known; immediate right" 0 23
162 $ commit 24 "merge one known; immediate right" 0 23
162 $ commit 25 "merge one known; far left" 21 24
163 $ commit 25 "merge one known; far left" 21 24
163 $ commit 26 "merge one known; far right" 18 25
164 $ commit 26 "merge one known; far right" 18 25
164 $ commit 27 "collapse" 21
165 $ commit 27 "collapse" 21
165 $ commit 28 "merge zero known" 1 26
166 $ commit 28 "merge zero known" 1 26
166 $ commit 29 "regular commit" 0
167 $ commit 29 "regular commit" 0
167 $ commit 30 "expand" 28 29
168 $ commit 30 "expand" 28 29
168 $ commit 31 "expand" 21 30
169 $ commit 31 "expand" 21 30
169 $ commit 32 "expand" 27 31
170 $ commit 32 "expand" 27 31
170 $ commit 33 "head" 18
171 $ commit 33 "head" 18
171 $ commit 34 "head" 32
172 $ commit 34 "head" 32
172
173
173
174
174 $ hg log -G -q
175 $ hg log -G -q
175 @ 34:fea3ac5810e0
176 @ 34:fea3ac5810e0
176 |
177 |
177 | o 33:68608f5145f9
178 | o 33:68608f5145f9
178 | |
179 | |
179 o | 32:d06dffa21a31
180 o | 32:d06dffa21a31
180 |\ \
181 |\ \
181 | o \ 31:621d83e11f67
182 | o \ 31:621d83e11f67
182 | |\ \
183 | |\ \
183 | | o \ 30:6e11cd4b648f
184 | | o \ 30:6e11cd4b648f
184 | | |\ \
185 | | |\ \
185 | | | o | 29:cd9bb2be7593
186 | | | o | 29:cd9bb2be7593
186 | | | | |
187 | | | | |
187 | | o | | 28:44ecd0b9ae99
188 | | o | | 28:44ecd0b9ae99
188 | | |\ \ \
189 | | |\ \ \
189 o | | | | | 27:886ed638191b
190 o | | | | | 27:886ed638191b
190 |/ / / / /
191 |/ / / / /
191 | | o---+ 26:7f25b6c2f0b9
192 | | o---+ 26:7f25b6c2f0b9
192 | | | | |
193 | | | | |
193 +---o | | 25:91da8ed57247
194 +---o | | 25:91da8ed57247
194 | | | | |
195 | | | | |
195 | | o | | 24:a9c19a3d96b7
196 | | o | | 24:a9c19a3d96b7
196 | | |\| |
197 | | |\| |
197 | | o | | 23:a01cddf0766d
198 | | o | | 23:a01cddf0766d
198 | |/| | |
199 | |/| | |
199 +---o---+ 22:e0d9cccacb5d
200 +---o---+ 22:e0d9cccacb5d
200 | | / /
201 | | / /
201 o | | | 21:d42a756af44d
202 o | | | 21:d42a756af44d
202 |\ \ \ \
203 |\ \ \ \
203 | o---+-+ 20:d30ed6450e32
204 | o---+-+ 20:d30ed6450e32
204 | / / /
205 | / / /
205 o | | | 19:31ddc2c1573b
206 o | | | 19:31ddc2c1573b
206 |\ \ \ \
207 |\ \ \ \
207 +---+---o 18:1aa84d96232a
208 +---+---o 18:1aa84d96232a
208 | | | |
209 | | | |
209 | o | | 17:44765d7c06e0
210 | o | | 17:44765d7c06e0
210 | |\ \ \
211 | |\ \ \
211 | | o---+ 16:3677d192927d
212 | | o---+ 16:3677d192927d
212 | | |/ /
213 | | |/ /
213 o | | | 15:1dda3f72782d
214 o | | | 15:1dda3f72782d
214 |\ \ \ \
215 |\ \ \ \
215 | o-----+ 14:8eac370358ef
216 | o-----+ 14:8eac370358ef
216 | |/ / /
217 | |/ / /
217 o | | | 13:22d8966a97e3
218 o | | | 13:22d8966a97e3
218 |\ \ \ \
219 |\ \ \ \
219 +---o | | 12:86b91144a6e9
220 +---o | | 12:86b91144a6e9
220 | | |/ /
221 | | |/ /
221 | o | | 11:832d76e6bdf2
222 | o | | 11:832d76e6bdf2
222 | |\ \ \
223 | |\ \ \
223 | | o---+ 10:74c64d036d72
224 | | o---+ 10:74c64d036d72
224 | |/ / /
225 | |/ / /
225 o | | | 9:7010c0af0a35
226 o | | | 9:7010c0af0a35
226 |\ \ \ \
227 |\ \ \ \
227 | o-----+ 8:7a0b11f71937
228 | o-----+ 8:7a0b11f71937
228 |/ / / /
229 |/ / / /
229 o | | | 7:b632bb1b1224
230 o | | | 7:b632bb1b1224
230 |\ \ \ \
231 |\ \ \ \
231 +---o | | 6:b105a072e251
232 +---o | | 6:b105a072e251
232 | |/ / /
233 | |/ / /
233 | o | | 5:4409d547b708
234 | o | | 5:4409d547b708
234 | |\ \ \
235 | |\ \ \
235 | | o | | 4:26a8bac39d9f
236 | | o | | 4:26a8bac39d9f
236 | |/|/ /
237 | |/|/ /
237 | o / / 3:27eef8ed80b4
238 | o / / 3:27eef8ed80b4
238 |/ / /
239 |/ / /
239 o / / 2:3d9a33b8d1e1
240 o / / 2:3d9a33b8d1e1
240 |/ /
241 |/ /
241 o / 1:6db2ef61d156
242 o / 1:6db2ef61d156
242 |/
243 |/
243 o 0:e6eb3150255d
244 o 0:e6eb3150255d
244
245
245
246
246 $ hg log -G
247 $ hg log -G
247 @ changeset: 34:fea3ac5810e0
248 @ changeset: 34:fea3ac5810e0
248 | tag: tip
249 | tag: tip
249 | parent: 32:d06dffa21a31
250 | parent: 32:d06dffa21a31
250 | user: test
251 | user: test
251 | date: Thu Jan 01 00:00:34 1970 +0000
252 | date: Thu Jan 01 00:00:34 1970 +0000
252 | summary: (34) head
253 | summary: (34) head
253 |
254 |
254 | o changeset: 33:68608f5145f9
255 | o changeset: 33:68608f5145f9
255 | | parent: 18:1aa84d96232a
256 | | parent: 18:1aa84d96232a
256 | | user: test
257 | | user: test
257 | | date: Thu Jan 01 00:00:33 1970 +0000
258 | | date: Thu Jan 01 00:00:33 1970 +0000
258 | | summary: (33) head
259 | | summary: (33) head
259 | |
260 | |
260 o | changeset: 32:d06dffa21a31
261 o | changeset: 32:d06dffa21a31
261 |\ \ parent: 27:886ed638191b
262 |\ \ parent: 27:886ed638191b
262 | | | parent: 31:621d83e11f67
263 | | | parent: 31:621d83e11f67
263 | | | user: test
264 | | | user: test
264 | | | date: Thu Jan 01 00:00:32 1970 +0000
265 | | | date: Thu Jan 01 00:00:32 1970 +0000
265 | | | summary: (32) expand
266 | | | summary: (32) expand
266 | | |
267 | | |
267 | o | changeset: 31:621d83e11f67
268 | o | changeset: 31:621d83e11f67
268 | |\ \ parent: 21:d42a756af44d
269 | |\ \ parent: 21:d42a756af44d
269 | | | | parent: 30:6e11cd4b648f
270 | | | | parent: 30:6e11cd4b648f
270 | | | | user: test
271 | | | | user: test
271 | | | | date: Thu Jan 01 00:00:31 1970 +0000
272 | | | | date: Thu Jan 01 00:00:31 1970 +0000
272 | | | | summary: (31) expand
273 | | | | summary: (31) expand
273 | | | |
274 | | | |
274 | | o | changeset: 30:6e11cd4b648f
275 | | o | changeset: 30:6e11cd4b648f
275 | | |\ \ parent: 28:44ecd0b9ae99
276 | | |\ \ parent: 28:44ecd0b9ae99
276 | | | | | parent: 29:cd9bb2be7593
277 | | | | | parent: 29:cd9bb2be7593
277 | | | | | user: test
278 | | | | | user: test
278 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
279 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
279 | | | | | summary: (30) expand
280 | | | | | summary: (30) expand
280 | | | | |
281 | | | | |
281 | | | o | changeset: 29:cd9bb2be7593
282 | | | o | changeset: 29:cd9bb2be7593
282 | | | | | parent: 0:e6eb3150255d
283 | | | | | parent: 0:e6eb3150255d
283 | | | | | user: test
284 | | | | | user: test
284 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
285 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
285 | | | | | summary: (29) regular commit
286 | | | | | summary: (29) regular commit
286 | | | | |
287 | | | | |
287 | | o | | changeset: 28:44ecd0b9ae99
288 | | o | | changeset: 28:44ecd0b9ae99
288 | | |\ \ \ parent: 1:6db2ef61d156
289 | | |\ \ \ parent: 1:6db2ef61d156
289 | | | | | | parent: 26:7f25b6c2f0b9
290 | | | | | | parent: 26:7f25b6c2f0b9
290 | | | | | | user: test
291 | | | | | | user: test
291 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
292 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
292 | | | | | | summary: (28) merge zero known
293 | | | | | | summary: (28) merge zero known
293 | | | | | |
294 | | | | | |
294 o | | | | | changeset: 27:886ed638191b
295 o | | | | | changeset: 27:886ed638191b
295 |/ / / / / parent: 21:d42a756af44d
296 |/ / / / / parent: 21:d42a756af44d
296 | | | | | user: test
297 | | | | | user: test
297 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
298 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
298 | | | | | summary: (27) collapse
299 | | | | | summary: (27) collapse
299 | | | | |
300 | | | | |
300 | | o---+ changeset: 26:7f25b6c2f0b9
301 | | o---+ changeset: 26:7f25b6c2f0b9
301 | | | | | parent: 18:1aa84d96232a
302 | | | | | parent: 18:1aa84d96232a
302 | | | | | parent: 25:91da8ed57247
303 | | | | | parent: 25:91da8ed57247
303 | | | | | user: test
304 | | | | | user: test
304 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
305 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
305 | | | | | summary: (26) merge one known; far right
306 | | | | | summary: (26) merge one known; far right
306 | | | | |
307 | | | | |
307 +---o | | changeset: 25:91da8ed57247
308 +---o | | changeset: 25:91da8ed57247
308 | | | | | parent: 21:d42a756af44d
309 | | | | | parent: 21:d42a756af44d
309 | | | | | parent: 24:a9c19a3d96b7
310 | | | | | parent: 24:a9c19a3d96b7
310 | | | | | user: test
311 | | | | | user: test
311 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
312 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
312 | | | | | summary: (25) merge one known; far left
313 | | | | | summary: (25) merge one known; far left
313 | | | | |
314 | | | | |
314 | | o | | changeset: 24:a9c19a3d96b7
315 | | o | | changeset: 24:a9c19a3d96b7
315 | | |\| | parent: 0:e6eb3150255d
316 | | |\| | parent: 0:e6eb3150255d
316 | | | | | parent: 23:a01cddf0766d
317 | | | | | parent: 23:a01cddf0766d
317 | | | | | user: test
318 | | | | | user: test
318 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
319 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
319 | | | | | summary: (24) merge one known; immediate right
320 | | | | | summary: (24) merge one known; immediate right
320 | | | | |
321 | | | | |
321 | | o | | changeset: 23:a01cddf0766d
322 | | o | | changeset: 23:a01cddf0766d
322 | |/| | | parent: 1:6db2ef61d156
323 | |/| | | parent: 1:6db2ef61d156
323 | | | | | parent: 22:e0d9cccacb5d
324 | | | | | parent: 22:e0d9cccacb5d
324 | | | | | user: test
325 | | | | | user: test
325 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
326 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
326 | | | | | summary: (23) merge one known; immediate left
327 | | | | | summary: (23) merge one known; immediate left
327 | | | | |
328 | | | | |
328 +---o---+ changeset: 22:e0d9cccacb5d
329 +---o---+ changeset: 22:e0d9cccacb5d
329 | | | | parent: 18:1aa84d96232a
330 | | | | parent: 18:1aa84d96232a
330 | | / / parent: 21:d42a756af44d
331 | | / / parent: 21:d42a756af44d
331 | | | | user: test
332 | | | | user: test
332 | | | | date: Thu Jan 01 00:00:22 1970 +0000
333 | | | | date: Thu Jan 01 00:00:22 1970 +0000
333 | | | | summary: (22) merge two known; one far left, one far right
334 | | | | summary: (22) merge two known; one far left, one far right
334 | | | |
335 | | | |
335 o | | | changeset: 21:d42a756af44d
336 o | | | changeset: 21:d42a756af44d
336 |\ \ \ \ parent: 19:31ddc2c1573b
337 |\ \ \ \ parent: 19:31ddc2c1573b
337 | | | | | parent: 20:d30ed6450e32
338 | | | | | parent: 20:d30ed6450e32
338 | | | | | user: test
339 | | | | | user: test
339 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
340 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
340 | | | | | summary: (21) expand
341 | | | | | summary: (21) expand
341 | | | | |
342 | | | | |
342 | o---+-+ changeset: 20:d30ed6450e32
343 | o---+-+ changeset: 20:d30ed6450e32
343 | | | | parent: 0:e6eb3150255d
344 | | | | parent: 0:e6eb3150255d
344 | / / / parent: 18:1aa84d96232a
345 | / / / parent: 18:1aa84d96232a
345 | | | | user: test
346 | | | | user: test
346 | | | | date: Thu Jan 01 00:00:20 1970 +0000
347 | | | | date: Thu Jan 01 00:00:20 1970 +0000
347 | | | | summary: (20) merge two known; two far right
348 | | | | summary: (20) merge two known; two far right
348 | | | |
349 | | | |
349 o | | | changeset: 19:31ddc2c1573b
350 o | | | changeset: 19:31ddc2c1573b
350 |\ \ \ \ parent: 15:1dda3f72782d
351 |\ \ \ \ parent: 15:1dda3f72782d
351 | | | | | parent: 17:44765d7c06e0
352 | | | | | parent: 17:44765d7c06e0
352 | | | | | user: test
353 | | | | | user: test
353 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
354 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
354 | | | | | summary: (19) expand
355 | | | | | summary: (19) expand
355 | | | | |
356 | | | | |
356 +---+---o changeset: 18:1aa84d96232a
357 +---+---o changeset: 18:1aa84d96232a
357 | | | | parent: 1:6db2ef61d156
358 | | | | parent: 1:6db2ef61d156
358 | | | | parent: 15:1dda3f72782d
359 | | | | parent: 15:1dda3f72782d
359 | | | | user: test
360 | | | | user: test
360 | | | | date: Thu Jan 01 00:00:18 1970 +0000
361 | | | | date: Thu Jan 01 00:00:18 1970 +0000
361 | | | | summary: (18) merge two known; two far left
362 | | | | summary: (18) merge two known; two far left
362 | | | |
363 | | | |
363 | o | | changeset: 17:44765d7c06e0
364 | o | | changeset: 17:44765d7c06e0
364 | |\ \ \ parent: 12:86b91144a6e9
365 | |\ \ \ parent: 12:86b91144a6e9
365 | | | | | parent: 16:3677d192927d
366 | | | | | parent: 16:3677d192927d
366 | | | | | user: test
367 | | | | | user: test
367 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
368 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
368 | | | | | summary: (17) expand
369 | | | | | summary: (17) expand
369 | | | | |
370 | | | | |
370 | | o---+ changeset: 16:3677d192927d
371 | | o---+ changeset: 16:3677d192927d
371 | | | | | parent: 0:e6eb3150255d
372 | | | | | parent: 0:e6eb3150255d
372 | | |/ / parent: 1:6db2ef61d156
373 | | |/ / parent: 1:6db2ef61d156
373 | | | | user: test
374 | | | | user: test
374 | | | | date: Thu Jan 01 00:00:16 1970 +0000
375 | | | | date: Thu Jan 01 00:00:16 1970 +0000
375 | | | | summary: (16) merge two known; one immediate right, one near right
376 | | | | summary: (16) merge two known; one immediate right, one near right
376 | | | |
377 | | | |
377 o | | | changeset: 15:1dda3f72782d
378 o | | | changeset: 15:1dda3f72782d
378 |\ \ \ \ parent: 13:22d8966a97e3
379 |\ \ \ \ parent: 13:22d8966a97e3
379 | | | | | parent: 14:8eac370358ef
380 | | | | | parent: 14:8eac370358ef
380 | | | | | user: test
381 | | | | | user: test
381 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
382 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
382 | | | | | summary: (15) expand
383 | | | | | summary: (15) expand
383 | | | | |
384 | | | | |
384 | o-----+ changeset: 14:8eac370358ef
385 | o-----+ changeset: 14:8eac370358ef
385 | | | | | parent: 0:e6eb3150255d
386 | | | | | parent: 0:e6eb3150255d
386 | |/ / / parent: 12:86b91144a6e9
387 | |/ / / parent: 12:86b91144a6e9
387 | | | | user: test
388 | | | | user: test
388 | | | | date: Thu Jan 01 00:00:14 1970 +0000
389 | | | | date: Thu Jan 01 00:00:14 1970 +0000
389 | | | | summary: (14) merge two known; one immediate right, one far right
390 | | | | summary: (14) merge two known; one immediate right, one far right
390 | | | |
391 | | | |
391 o | | | changeset: 13:22d8966a97e3
392 o | | | changeset: 13:22d8966a97e3
392 |\ \ \ \ parent: 9:7010c0af0a35
393 |\ \ \ \ parent: 9:7010c0af0a35
393 | | | | | parent: 11:832d76e6bdf2
394 | | | | | parent: 11:832d76e6bdf2
394 | | | | | user: test
395 | | | | | user: test
395 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
396 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
396 | | | | | summary: (13) expand
397 | | | | | summary: (13) expand
397 | | | | |
398 | | | | |
398 +---o | | changeset: 12:86b91144a6e9
399 +---o | | changeset: 12:86b91144a6e9
399 | | |/ / parent: 1:6db2ef61d156
400 | | |/ / parent: 1:6db2ef61d156
400 | | | | parent: 9:7010c0af0a35
401 | | | | parent: 9:7010c0af0a35
401 | | | | user: test
402 | | | | user: test
402 | | | | date: Thu Jan 01 00:00:12 1970 +0000
403 | | | | date: Thu Jan 01 00:00:12 1970 +0000
403 | | | | summary: (12) merge two known; one immediate right, one far left
404 | | | | summary: (12) merge two known; one immediate right, one far left
404 | | | |
405 | | | |
405 | o | | changeset: 11:832d76e6bdf2
406 | o | | changeset: 11:832d76e6bdf2
406 | |\ \ \ parent: 6:b105a072e251
407 | |\ \ \ parent: 6:b105a072e251
407 | | | | | parent: 10:74c64d036d72
408 | | | | | parent: 10:74c64d036d72
408 | | | | | user: test
409 | | | | | user: test
409 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
410 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
410 | | | | | summary: (11) expand
411 | | | | | summary: (11) expand
411 | | | | |
412 | | | | |
412 | | o---+ changeset: 10:74c64d036d72
413 | | o---+ changeset: 10:74c64d036d72
413 | | | | | parent: 0:e6eb3150255d
414 | | | | | parent: 0:e6eb3150255d
414 | |/ / / parent: 6:b105a072e251
415 | |/ / / parent: 6:b105a072e251
415 | | | | user: test
416 | | | | user: test
416 | | | | date: Thu Jan 01 00:00:10 1970 +0000
417 | | | | date: Thu Jan 01 00:00:10 1970 +0000
417 | | | | summary: (10) merge two known; one immediate left, one near right
418 | | | | summary: (10) merge two known; one immediate left, one near right
418 | | | |
419 | | | |
419 o | | | changeset: 9:7010c0af0a35
420 o | | | changeset: 9:7010c0af0a35
420 |\ \ \ \ parent: 7:b632bb1b1224
421 |\ \ \ \ parent: 7:b632bb1b1224
421 | | | | | parent: 8:7a0b11f71937
422 | | | | | parent: 8:7a0b11f71937
422 | | | | | user: test
423 | | | | | user: test
423 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
424 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
424 | | | | | summary: (9) expand
425 | | | | | summary: (9) expand
425 | | | | |
426 | | | | |
426 | o-----+ changeset: 8:7a0b11f71937
427 | o-----+ changeset: 8:7a0b11f71937
427 | | | | | parent: 0:e6eb3150255d
428 | | | | | parent: 0:e6eb3150255d
428 |/ / / / parent: 7:b632bb1b1224
429 |/ / / / parent: 7:b632bb1b1224
429 | | | | user: test
430 | | | | user: test
430 | | | | date: Thu Jan 01 00:00:08 1970 +0000
431 | | | | date: Thu Jan 01 00:00:08 1970 +0000
431 | | | | summary: (8) merge two known; one immediate left, one far right
432 | | | | summary: (8) merge two known; one immediate left, one far right
432 | | | |
433 | | | |
433 o | | | changeset: 7:b632bb1b1224
434 o | | | changeset: 7:b632bb1b1224
434 |\ \ \ \ parent: 2:3d9a33b8d1e1
435 |\ \ \ \ parent: 2:3d9a33b8d1e1
435 | | | | | parent: 5:4409d547b708
436 | | | | | parent: 5:4409d547b708
436 | | | | | user: test
437 | | | | | user: test
437 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
438 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
438 | | | | | summary: (7) expand
439 | | | | | summary: (7) expand
439 | | | | |
440 | | | | |
440 +---o | | changeset: 6:b105a072e251
441 +---o | | changeset: 6:b105a072e251
441 | |/ / / parent: 2:3d9a33b8d1e1
442 | |/ / / parent: 2:3d9a33b8d1e1
442 | | | | parent: 5:4409d547b708
443 | | | | parent: 5:4409d547b708
443 | | | | user: test
444 | | | | user: test
444 | | | | date: Thu Jan 01 00:00:06 1970 +0000
445 | | | | date: Thu Jan 01 00:00:06 1970 +0000
445 | | | | summary: (6) merge two known; one immediate left, one far left
446 | | | | summary: (6) merge two known; one immediate left, one far left
446 | | | |
447 | | | |
447 | o | | changeset: 5:4409d547b708
448 | o | | changeset: 5:4409d547b708
448 | |\ \ \ parent: 3:27eef8ed80b4
449 | |\ \ \ parent: 3:27eef8ed80b4
449 | | | | | parent: 4:26a8bac39d9f
450 | | | | | parent: 4:26a8bac39d9f
450 | | | | | user: test
451 | | | | | user: test
451 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
452 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
452 | | | | | summary: (5) expand
453 | | | | | summary: (5) expand
453 | | | | |
454 | | | | |
454 | | o | | changeset: 4:26a8bac39d9f
455 | | o | | changeset: 4:26a8bac39d9f
455 | |/|/ / parent: 1:6db2ef61d156
456 | |/|/ / parent: 1:6db2ef61d156
456 | | | | parent: 3:27eef8ed80b4
457 | | | | parent: 3:27eef8ed80b4
457 | | | | user: test
458 | | | | user: test
458 | | | | date: Thu Jan 01 00:00:04 1970 +0000
459 | | | | date: Thu Jan 01 00:00:04 1970 +0000
459 | | | | summary: (4) merge two known; one immediate left, one immediate right
460 | | | | summary: (4) merge two known; one immediate left, one immediate right
460 | | | |
461 | | | |
461 | o | | changeset: 3:27eef8ed80b4
462 | o | | changeset: 3:27eef8ed80b4
462 |/ / / user: test
463 |/ / / user: test
463 | | | date: Thu Jan 01 00:00:03 1970 +0000
464 | | | date: Thu Jan 01 00:00:03 1970 +0000
464 | | | summary: (3) collapse
465 | | | summary: (3) collapse
465 | | |
466 | | |
466 o | | changeset: 2:3d9a33b8d1e1
467 o | | changeset: 2:3d9a33b8d1e1
467 |/ / user: test
468 |/ / user: test
468 | | date: Thu Jan 01 00:00:02 1970 +0000
469 | | date: Thu Jan 01 00:00:02 1970 +0000
469 | | summary: (2) collapse
470 | | summary: (2) collapse
470 | |
471 | |
471 o | changeset: 1:6db2ef61d156
472 o | changeset: 1:6db2ef61d156
472 |/ user: test
473 |/ user: test
473 | date: Thu Jan 01 00:00:01 1970 +0000
474 | date: Thu Jan 01 00:00:01 1970 +0000
474 | summary: (1) collapse
475 | summary: (1) collapse
475 |
476 |
476 o changeset: 0:e6eb3150255d
477 o changeset: 0:e6eb3150255d
477 user: test
478 user: test
478 date: Thu Jan 01 00:00:00 1970 +0000
479 date: Thu Jan 01 00:00:00 1970 +0000
479 summary: (0) root
480 summary: (0) root
480
481
481
482
482 File glog:
483 File glog:
483 $ hg log -G a
484 $ hg log -G a
484 @ changeset: 34:fea3ac5810e0
485 @ changeset: 34:fea3ac5810e0
485 | tag: tip
486 | tag: tip
486 | parent: 32:d06dffa21a31
487 | parent: 32:d06dffa21a31
487 | user: test
488 | user: test
488 | date: Thu Jan 01 00:00:34 1970 +0000
489 | date: Thu Jan 01 00:00:34 1970 +0000
489 | summary: (34) head
490 | summary: (34) head
490 |
491 |
491 | o changeset: 33:68608f5145f9
492 | o changeset: 33:68608f5145f9
492 | | parent: 18:1aa84d96232a
493 | | parent: 18:1aa84d96232a
493 | | user: test
494 | | user: test
494 | | date: Thu Jan 01 00:00:33 1970 +0000
495 | | date: Thu Jan 01 00:00:33 1970 +0000
495 | | summary: (33) head
496 | | summary: (33) head
496 | |
497 | |
497 o | changeset: 32:d06dffa21a31
498 o | changeset: 32:d06dffa21a31
498 |\ \ parent: 27:886ed638191b
499 |\ \ parent: 27:886ed638191b
499 | | | parent: 31:621d83e11f67
500 | | | parent: 31:621d83e11f67
500 | | | user: test
501 | | | user: test
501 | | | date: Thu Jan 01 00:00:32 1970 +0000
502 | | | date: Thu Jan 01 00:00:32 1970 +0000
502 | | | summary: (32) expand
503 | | | summary: (32) expand
503 | | |
504 | | |
504 | o | changeset: 31:621d83e11f67
505 | o | changeset: 31:621d83e11f67
505 | |\ \ parent: 21:d42a756af44d
506 | |\ \ parent: 21:d42a756af44d
506 | | | | parent: 30:6e11cd4b648f
507 | | | | parent: 30:6e11cd4b648f
507 | | | | user: test
508 | | | | user: test
508 | | | | date: Thu Jan 01 00:00:31 1970 +0000
509 | | | | date: Thu Jan 01 00:00:31 1970 +0000
509 | | | | summary: (31) expand
510 | | | | summary: (31) expand
510 | | | |
511 | | | |
511 | | o | changeset: 30:6e11cd4b648f
512 | | o | changeset: 30:6e11cd4b648f
512 | | |\ \ parent: 28:44ecd0b9ae99
513 | | |\ \ parent: 28:44ecd0b9ae99
513 | | | | | parent: 29:cd9bb2be7593
514 | | | | | parent: 29:cd9bb2be7593
514 | | | | | user: test
515 | | | | | user: test
515 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
516 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
516 | | | | | summary: (30) expand
517 | | | | | summary: (30) expand
517 | | | | |
518 | | | | |
518 | | | o | changeset: 29:cd9bb2be7593
519 | | | o | changeset: 29:cd9bb2be7593
519 | | | | | parent: 0:e6eb3150255d
520 | | | | | parent: 0:e6eb3150255d
520 | | | | | user: test
521 | | | | | user: test
521 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
522 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
522 | | | | | summary: (29) regular commit
523 | | | | | summary: (29) regular commit
523 | | | | |
524 | | | | |
524 | | o | | changeset: 28:44ecd0b9ae99
525 | | o | | changeset: 28:44ecd0b9ae99
525 | | |\ \ \ parent: 1:6db2ef61d156
526 | | |\ \ \ parent: 1:6db2ef61d156
526 | | | | | | parent: 26:7f25b6c2f0b9
527 | | | | | | parent: 26:7f25b6c2f0b9
527 | | | | | | user: test
528 | | | | | | user: test
528 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
529 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
529 | | | | | | summary: (28) merge zero known
530 | | | | | | summary: (28) merge zero known
530 | | | | | |
531 | | | | | |
531 o | | | | | changeset: 27:886ed638191b
532 o | | | | | changeset: 27:886ed638191b
532 |/ / / / / parent: 21:d42a756af44d
533 |/ / / / / parent: 21:d42a756af44d
533 | | | | | user: test
534 | | | | | user: test
534 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
535 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
535 | | | | | summary: (27) collapse
536 | | | | | summary: (27) collapse
536 | | | | |
537 | | | | |
537 | | o---+ changeset: 26:7f25b6c2f0b9
538 | | o---+ changeset: 26:7f25b6c2f0b9
538 | | | | | parent: 18:1aa84d96232a
539 | | | | | parent: 18:1aa84d96232a
539 | | | | | parent: 25:91da8ed57247
540 | | | | | parent: 25:91da8ed57247
540 | | | | | user: test
541 | | | | | user: test
541 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
542 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
542 | | | | | summary: (26) merge one known; far right
543 | | | | | summary: (26) merge one known; far right
543 | | | | |
544 | | | | |
544 +---o | | changeset: 25:91da8ed57247
545 +---o | | changeset: 25:91da8ed57247
545 | | | | | parent: 21:d42a756af44d
546 | | | | | parent: 21:d42a756af44d
546 | | | | | parent: 24:a9c19a3d96b7
547 | | | | | parent: 24:a9c19a3d96b7
547 | | | | | user: test
548 | | | | | user: test
548 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
549 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
549 | | | | | summary: (25) merge one known; far left
550 | | | | | summary: (25) merge one known; far left
550 | | | | |
551 | | | | |
551 | | o | | changeset: 24:a9c19a3d96b7
552 | | o | | changeset: 24:a9c19a3d96b7
552 | | |\| | parent: 0:e6eb3150255d
553 | | |\| | parent: 0:e6eb3150255d
553 | | | | | parent: 23:a01cddf0766d
554 | | | | | parent: 23:a01cddf0766d
554 | | | | | user: test
555 | | | | | user: test
555 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
556 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
556 | | | | | summary: (24) merge one known; immediate right
557 | | | | | summary: (24) merge one known; immediate right
557 | | | | |
558 | | | | |
558 | | o | | changeset: 23:a01cddf0766d
559 | | o | | changeset: 23:a01cddf0766d
559 | |/| | | parent: 1:6db2ef61d156
560 | |/| | | parent: 1:6db2ef61d156
560 | | | | | parent: 22:e0d9cccacb5d
561 | | | | | parent: 22:e0d9cccacb5d
561 | | | | | user: test
562 | | | | | user: test
562 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
563 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
563 | | | | | summary: (23) merge one known; immediate left
564 | | | | | summary: (23) merge one known; immediate left
564 | | | | |
565 | | | | |
565 +---o---+ changeset: 22:e0d9cccacb5d
566 +---o---+ changeset: 22:e0d9cccacb5d
566 | | | | parent: 18:1aa84d96232a
567 | | | | parent: 18:1aa84d96232a
567 | | / / parent: 21:d42a756af44d
568 | | / / parent: 21:d42a756af44d
568 | | | | user: test
569 | | | | user: test
569 | | | | date: Thu Jan 01 00:00:22 1970 +0000
570 | | | | date: Thu Jan 01 00:00:22 1970 +0000
570 | | | | summary: (22) merge two known; one far left, one far right
571 | | | | summary: (22) merge two known; one far left, one far right
571 | | | |
572 | | | |
572 o | | | changeset: 21:d42a756af44d
573 o | | | changeset: 21:d42a756af44d
573 |\ \ \ \ parent: 19:31ddc2c1573b
574 |\ \ \ \ parent: 19:31ddc2c1573b
574 | | | | | parent: 20:d30ed6450e32
575 | | | | | parent: 20:d30ed6450e32
575 | | | | | user: test
576 | | | | | user: test
576 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
577 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
577 | | | | | summary: (21) expand
578 | | | | | summary: (21) expand
578 | | | | |
579 | | | | |
579 | o---+-+ changeset: 20:d30ed6450e32
580 | o---+-+ changeset: 20:d30ed6450e32
580 | | | | parent: 0:e6eb3150255d
581 | | | | parent: 0:e6eb3150255d
581 | / / / parent: 18:1aa84d96232a
582 | / / / parent: 18:1aa84d96232a
582 | | | | user: test
583 | | | | user: test
583 | | | | date: Thu Jan 01 00:00:20 1970 +0000
584 | | | | date: Thu Jan 01 00:00:20 1970 +0000
584 | | | | summary: (20) merge two known; two far right
585 | | | | summary: (20) merge two known; two far right
585 | | | |
586 | | | |
586 o | | | changeset: 19:31ddc2c1573b
587 o | | | changeset: 19:31ddc2c1573b
587 |\ \ \ \ parent: 15:1dda3f72782d
588 |\ \ \ \ parent: 15:1dda3f72782d
588 | | | | | parent: 17:44765d7c06e0
589 | | | | | parent: 17:44765d7c06e0
589 | | | | | user: test
590 | | | | | user: test
590 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
591 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
591 | | | | | summary: (19) expand
592 | | | | | summary: (19) expand
592 | | | | |
593 | | | | |
593 +---+---o changeset: 18:1aa84d96232a
594 +---+---o changeset: 18:1aa84d96232a
594 | | | | parent: 1:6db2ef61d156
595 | | | | parent: 1:6db2ef61d156
595 | | | | parent: 15:1dda3f72782d
596 | | | | parent: 15:1dda3f72782d
596 | | | | user: test
597 | | | | user: test
597 | | | | date: Thu Jan 01 00:00:18 1970 +0000
598 | | | | date: Thu Jan 01 00:00:18 1970 +0000
598 | | | | summary: (18) merge two known; two far left
599 | | | | summary: (18) merge two known; two far left
599 | | | |
600 | | | |
600 | o | | changeset: 17:44765d7c06e0
601 | o | | changeset: 17:44765d7c06e0
601 | |\ \ \ parent: 12:86b91144a6e9
602 | |\ \ \ parent: 12:86b91144a6e9
602 | | | | | parent: 16:3677d192927d
603 | | | | | parent: 16:3677d192927d
603 | | | | | user: test
604 | | | | | user: test
604 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
605 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
605 | | | | | summary: (17) expand
606 | | | | | summary: (17) expand
606 | | | | |
607 | | | | |
607 | | o---+ changeset: 16:3677d192927d
608 | | o---+ changeset: 16:3677d192927d
608 | | | | | parent: 0:e6eb3150255d
609 | | | | | parent: 0:e6eb3150255d
609 | | |/ / parent: 1:6db2ef61d156
610 | | |/ / parent: 1:6db2ef61d156
610 | | | | user: test
611 | | | | user: test
611 | | | | date: Thu Jan 01 00:00:16 1970 +0000
612 | | | | date: Thu Jan 01 00:00:16 1970 +0000
612 | | | | summary: (16) merge two known; one immediate right, one near right
613 | | | | summary: (16) merge two known; one immediate right, one near right
613 | | | |
614 | | | |
614 o | | | changeset: 15:1dda3f72782d
615 o | | | changeset: 15:1dda3f72782d
615 |\ \ \ \ parent: 13:22d8966a97e3
616 |\ \ \ \ parent: 13:22d8966a97e3
616 | | | | | parent: 14:8eac370358ef
617 | | | | | parent: 14:8eac370358ef
617 | | | | | user: test
618 | | | | | user: test
618 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
619 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
619 | | | | | summary: (15) expand
620 | | | | | summary: (15) expand
620 | | | | |
621 | | | | |
621 | o-----+ changeset: 14:8eac370358ef
622 | o-----+ changeset: 14:8eac370358ef
622 | | | | | parent: 0:e6eb3150255d
623 | | | | | parent: 0:e6eb3150255d
623 | |/ / / parent: 12:86b91144a6e9
624 | |/ / / parent: 12:86b91144a6e9
624 | | | | user: test
625 | | | | user: test
625 | | | | date: Thu Jan 01 00:00:14 1970 +0000
626 | | | | date: Thu Jan 01 00:00:14 1970 +0000
626 | | | | summary: (14) merge two known; one immediate right, one far right
627 | | | | summary: (14) merge two known; one immediate right, one far right
627 | | | |
628 | | | |
628 o | | | changeset: 13:22d8966a97e3
629 o | | | changeset: 13:22d8966a97e3
629 |\ \ \ \ parent: 9:7010c0af0a35
630 |\ \ \ \ parent: 9:7010c0af0a35
630 | | | | | parent: 11:832d76e6bdf2
631 | | | | | parent: 11:832d76e6bdf2
631 | | | | | user: test
632 | | | | | user: test
632 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
633 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
633 | | | | | summary: (13) expand
634 | | | | | summary: (13) expand
634 | | | | |
635 | | | | |
635 +---o | | changeset: 12:86b91144a6e9
636 +---o | | changeset: 12:86b91144a6e9
636 | | |/ / parent: 1:6db2ef61d156
637 | | |/ / parent: 1:6db2ef61d156
637 | | | | parent: 9:7010c0af0a35
638 | | | | parent: 9:7010c0af0a35
638 | | | | user: test
639 | | | | user: test
639 | | | | date: Thu Jan 01 00:00:12 1970 +0000
640 | | | | date: Thu Jan 01 00:00:12 1970 +0000
640 | | | | summary: (12) merge two known; one immediate right, one far left
641 | | | | summary: (12) merge two known; one immediate right, one far left
641 | | | |
642 | | | |
642 | o | | changeset: 11:832d76e6bdf2
643 | o | | changeset: 11:832d76e6bdf2
643 | |\ \ \ parent: 6:b105a072e251
644 | |\ \ \ parent: 6:b105a072e251
644 | | | | | parent: 10:74c64d036d72
645 | | | | | parent: 10:74c64d036d72
645 | | | | | user: test
646 | | | | | user: test
646 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
647 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
647 | | | | | summary: (11) expand
648 | | | | | summary: (11) expand
648 | | | | |
649 | | | | |
649 | | o---+ changeset: 10:74c64d036d72
650 | | o---+ changeset: 10:74c64d036d72
650 | | | | | parent: 0:e6eb3150255d
651 | | | | | parent: 0:e6eb3150255d
651 | |/ / / parent: 6:b105a072e251
652 | |/ / / parent: 6:b105a072e251
652 | | | | user: test
653 | | | | user: test
653 | | | | date: Thu Jan 01 00:00:10 1970 +0000
654 | | | | date: Thu Jan 01 00:00:10 1970 +0000
654 | | | | summary: (10) merge two known; one immediate left, one near right
655 | | | | summary: (10) merge two known; one immediate left, one near right
655 | | | |
656 | | | |
656 o | | | changeset: 9:7010c0af0a35
657 o | | | changeset: 9:7010c0af0a35
657 |\ \ \ \ parent: 7:b632bb1b1224
658 |\ \ \ \ parent: 7:b632bb1b1224
658 | | | | | parent: 8:7a0b11f71937
659 | | | | | parent: 8:7a0b11f71937
659 | | | | | user: test
660 | | | | | user: test
660 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
661 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
661 | | | | | summary: (9) expand
662 | | | | | summary: (9) expand
662 | | | | |
663 | | | | |
663 | o-----+ changeset: 8:7a0b11f71937
664 | o-----+ changeset: 8:7a0b11f71937
664 | | | | | parent: 0:e6eb3150255d
665 | | | | | parent: 0:e6eb3150255d
665 |/ / / / parent: 7:b632bb1b1224
666 |/ / / / parent: 7:b632bb1b1224
666 | | | | user: test
667 | | | | user: test
667 | | | | date: Thu Jan 01 00:00:08 1970 +0000
668 | | | | date: Thu Jan 01 00:00:08 1970 +0000
668 | | | | summary: (8) merge two known; one immediate left, one far right
669 | | | | summary: (8) merge two known; one immediate left, one far right
669 | | | |
670 | | | |
670 o | | | changeset: 7:b632bb1b1224
671 o | | | changeset: 7:b632bb1b1224
671 |\ \ \ \ parent: 2:3d9a33b8d1e1
672 |\ \ \ \ parent: 2:3d9a33b8d1e1
672 | | | | | parent: 5:4409d547b708
673 | | | | | parent: 5:4409d547b708
673 | | | | | user: test
674 | | | | | user: test
674 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
675 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
675 | | | | | summary: (7) expand
676 | | | | | summary: (7) expand
676 | | | | |
677 | | | | |
677 +---o | | changeset: 6:b105a072e251
678 +---o | | changeset: 6:b105a072e251
678 | |/ / / parent: 2:3d9a33b8d1e1
679 | |/ / / parent: 2:3d9a33b8d1e1
679 | | | | parent: 5:4409d547b708
680 | | | | parent: 5:4409d547b708
680 | | | | user: test
681 | | | | user: test
681 | | | | date: Thu Jan 01 00:00:06 1970 +0000
682 | | | | date: Thu Jan 01 00:00:06 1970 +0000
682 | | | | summary: (6) merge two known; one immediate left, one far left
683 | | | | summary: (6) merge two known; one immediate left, one far left
683 | | | |
684 | | | |
684 | o | | changeset: 5:4409d547b708
685 | o | | changeset: 5:4409d547b708
685 | |\ \ \ parent: 3:27eef8ed80b4
686 | |\ \ \ parent: 3:27eef8ed80b4
686 | | | | | parent: 4:26a8bac39d9f
687 | | | | | parent: 4:26a8bac39d9f
687 | | | | | user: test
688 | | | | | user: test
688 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
689 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
689 | | | | | summary: (5) expand
690 | | | | | summary: (5) expand
690 | | | | |
691 | | | | |
691 | | o | | changeset: 4:26a8bac39d9f
692 | | o | | changeset: 4:26a8bac39d9f
692 | |/|/ / parent: 1:6db2ef61d156
693 | |/|/ / parent: 1:6db2ef61d156
693 | | | | parent: 3:27eef8ed80b4
694 | | | | parent: 3:27eef8ed80b4
694 | | | | user: test
695 | | | | user: test
695 | | | | date: Thu Jan 01 00:00:04 1970 +0000
696 | | | | date: Thu Jan 01 00:00:04 1970 +0000
696 | | | | summary: (4) merge two known; one immediate left, one immediate right
697 | | | | summary: (4) merge two known; one immediate left, one immediate right
697 | | | |
698 | | | |
698 | o | | changeset: 3:27eef8ed80b4
699 | o | | changeset: 3:27eef8ed80b4
699 |/ / / user: test
700 |/ / / user: test
700 | | | date: Thu Jan 01 00:00:03 1970 +0000
701 | | | date: Thu Jan 01 00:00:03 1970 +0000
701 | | | summary: (3) collapse
702 | | | summary: (3) collapse
702 | | |
703 | | |
703 o | | changeset: 2:3d9a33b8d1e1
704 o | | changeset: 2:3d9a33b8d1e1
704 |/ / user: test
705 |/ / user: test
705 | | date: Thu Jan 01 00:00:02 1970 +0000
706 | | date: Thu Jan 01 00:00:02 1970 +0000
706 | | summary: (2) collapse
707 | | summary: (2) collapse
707 | |
708 | |
708 o | changeset: 1:6db2ef61d156
709 o | changeset: 1:6db2ef61d156
709 |/ user: test
710 |/ user: test
710 | date: Thu Jan 01 00:00:01 1970 +0000
711 | date: Thu Jan 01 00:00:01 1970 +0000
711 | summary: (1) collapse
712 | summary: (1) collapse
712 |
713 |
713 o changeset: 0:e6eb3150255d
714 o changeset: 0:e6eb3150255d
714 user: test
715 user: test
715 date: Thu Jan 01 00:00:00 1970 +0000
716 date: Thu Jan 01 00:00:00 1970 +0000
716 summary: (0) root
717 summary: (0) root
717
718
718
719
719 File glog per revset:
720 File glog per revset:
720
721
721 $ hg log -G -r 'file("a")'
722 $ hg log -G -r 'file("a")'
722 @ changeset: 34:fea3ac5810e0
723 @ changeset: 34:fea3ac5810e0
723 | tag: tip
724 | tag: tip
724 | parent: 32:d06dffa21a31
725 | parent: 32:d06dffa21a31
725 | user: test
726 | user: test
726 | date: Thu Jan 01 00:00:34 1970 +0000
727 | date: Thu Jan 01 00:00:34 1970 +0000
727 | summary: (34) head
728 | summary: (34) head
728 |
729 |
729 | o changeset: 33:68608f5145f9
730 | o changeset: 33:68608f5145f9
730 | | parent: 18:1aa84d96232a
731 | | parent: 18:1aa84d96232a
731 | | user: test
732 | | user: test
732 | | date: Thu Jan 01 00:00:33 1970 +0000
733 | | date: Thu Jan 01 00:00:33 1970 +0000
733 | | summary: (33) head
734 | | summary: (33) head
734 | |
735 | |
735 o | changeset: 32:d06dffa21a31
736 o | changeset: 32:d06dffa21a31
736 |\ \ parent: 27:886ed638191b
737 |\ \ parent: 27:886ed638191b
737 | | | parent: 31:621d83e11f67
738 | | | parent: 31:621d83e11f67
738 | | | user: test
739 | | | user: test
739 | | | date: Thu Jan 01 00:00:32 1970 +0000
740 | | | date: Thu Jan 01 00:00:32 1970 +0000
740 | | | summary: (32) expand
741 | | | summary: (32) expand
741 | | |
742 | | |
742 | o | changeset: 31:621d83e11f67
743 | o | changeset: 31:621d83e11f67
743 | |\ \ parent: 21:d42a756af44d
744 | |\ \ parent: 21:d42a756af44d
744 | | | | parent: 30:6e11cd4b648f
745 | | | | parent: 30:6e11cd4b648f
745 | | | | user: test
746 | | | | user: test
746 | | | | date: Thu Jan 01 00:00:31 1970 +0000
747 | | | | date: Thu Jan 01 00:00:31 1970 +0000
747 | | | | summary: (31) expand
748 | | | | summary: (31) expand
748 | | | |
749 | | | |
749 | | o | changeset: 30:6e11cd4b648f
750 | | o | changeset: 30:6e11cd4b648f
750 | | |\ \ parent: 28:44ecd0b9ae99
751 | | |\ \ parent: 28:44ecd0b9ae99
751 | | | | | parent: 29:cd9bb2be7593
752 | | | | | parent: 29:cd9bb2be7593
752 | | | | | user: test
753 | | | | | user: test
753 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
754 | | | | | date: Thu Jan 01 00:00:30 1970 +0000
754 | | | | | summary: (30) expand
755 | | | | | summary: (30) expand
755 | | | | |
756 | | | | |
756 | | | o | changeset: 29:cd9bb2be7593
757 | | | o | changeset: 29:cd9bb2be7593
757 | | | | | parent: 0:e6eb3150255d
758 | | | | | parent: 0:e6eb3150255d
758 | | | | | user: test
759 | | | | | user: test
759 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
760 | | | | | date: Thu Jan 01 00:00:29 1970 +0000
760 | | | | | summary: (29) regular commit
761 | | | | | summary: (29) regular commit
761 | | | | |
762 | | | | |
762 | | o | | changeset: 28:44ecd0b9ae99
763 | | o | | changeset: 28:44ecd0b9ae99
763 | | |\ \ \ parent: 1:6db2ef61d156
764 | | |\ \ \ parent: 1:6db2ef61d156
764 | | | | | | parent: 26:7f25b6c2f0b9
765 | | | | | | parent: 26:7f25b6c2f0b9
765 | | | | | | user: test
766 | | | | | | user: test
766 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
767 | | | | | | date: Thu Jan 01 00:00:28 1970 +0000
767 | | | | | | summary: (28) merge zero known
768 | | | | | | summary: (28) merge zero known
768 | | | | | |
769 | | | | | |
769 o | | | | | changeset: 27:886ed638191b
770 o | | | | | changeset: 27:886ed638191b
770 |/ / / / / parent: 21:d42a756af44d
771 |/ / / / / parent: 21:d42a756af44d
771 | | | | | user: test
772 | | | | | user: test
772 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
773 | | | | | date: Thu Jan 01 00:00:27 1970 +0000
773 | | | | | summary: (27) collapse
774 | | | | | summary: (27) collapse
774 | | | | |
775 | | | | |
775 | | o---+ changeset: 26:7f25b6c2f0b9
776 | | o---+ changeset: 26:7f25b6c2f0b9
776 | | | | | parent: 18:1aa84d96232a
777 | | | | | parent: 18:1aa84d96232a
777 | | | | | parent: 25:91da8ed57247
778 | | | | | parent: 25:91da8ed57247
778 | | | | | user: test
779 | | | | | user: test
779 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
780 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
780 | | | | | summary: (26) merge one known; far right
781 | | | | | summary: (26) merge one known; far right
781 | | | | |
782 | | | | |
782 +---o | | changeset: 25:91da8ed57247
783 +---o | | changeset: 25:91da8ed57247
783 | | | | | parent: 21:d42a756af44d
784 | | | | | parent: 21:d42a756af44d
784 | | | | | parent: 24:a9c19a3d96b7
785 | | | | | parent: 24:a9c19a3d96b7
785 | | | | | user: test
786 | | | | | user: test
786 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
787 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
787 | | | | | summary: (25) merge one known; far left
788 | | | | | summary: (25) merge one known; far left
788 | | | | |
789 | | | | |
789 | | o | | changeset: 24:a9c19a3d96b7
790 | | o | | changeset: 24:a9c19a3d96b7
790 | | |\| | parent: 0:e6eb3150255d
791 | | |\| | parent: 0:e6eb3150255d
791 | | | | | parent: 23:a01cddf0766d
792 | | | | | parent: 23:a01cddf0766d
792 | | | | | user: test
793 | | | | | user: test
793 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
794 | | | | | date: Thu Jan 01 00:00:24 1970 +0000
794 | | | | | summary: (24) merge one known; immediate right
795 | | | | | summary: (24) merge one known; immediate right
795 | | | | |
796 | | | | |
796 | | o | | changeset: 23:a01cddf0766d
797 | | o | | changeset: 23:a01cddf0766d
797 | |/| | | parent: 1:6db2ef61d156
798 | |/| | | parent: 1:6db2ef61d156
798 | | | | | parent: 22:e0d9cccacb5d
799 | | | | | parent: 22:e0d9cccacb5d
799 | | | | | user: test
800 | | | | | user: test
800 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
801 | | | | | date: Thu Jan 01 00:00:23 1970 +0000
801 | | | | | summary: (23) merge one known; immediate left
802 | | | | | summary: (23) merge one known; immediate left
802 | | | | |
803 | | | | |
803 +---o---+ changeset: 22:e0d9cccacb5d
804 +---o---+ changeset: 22:e0d9cccacb5d
804 | | | | parent: 18:1aa84d96232a
805 | | | | parent: 18:1aa84d96232a
805 | | / / parent: 21:d42a756af44d
806 | | / / parent: 21:d42a756af44d
806 | | | | user: test
807 | | | | user: test
807 | | | | date: Thu Jan 01 00:00:22 1970 +0000
808 | | | | date: Thu Jan 01 00:00:22 1970 +0000
808 | | | | summary: (22) merge two known; one far left, one far right
809 | | | | summary: (22) merge two known; one far left, one far right
809 | | | |
810 | | | |
810 o | | | changeset: 21:d42a756af44d
811 o | | | changeset: 21:d42a756af44d
811 |\ \ \ \ parent: 19:31ddc2c1573b
812 |\ \ \ \ parent: 19:31ddc2c1573b
812 | | | | | parent: 20:d30ed6450e32
813 | | | | | parent: 20:d30ed6450e32
813 | | | | | user: test
814 | | | | | user: test
814 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
815 | | | | | date: Thu Jan 01 00:00:21 1970 +0000
815 | | | | | summary: (21) expand
816 | | | | | summary: (21) expand
816 | | | | |
817 | | | | |
817 | o---+-+ changeset: 20:d30ed6450e32
818 | o---+-+ changeset: 20:d30ed6450e32
818 | | | | parent: 0:e6eb3150255d
819 | | | | parent: 0:e6eb3150255d
819 | / / / parent: 18:1aa84d96232a
820 | / / / parent: 18:1aa84d96232a
820 | | | | user: test
821 | | | | user: test
821 | | | | date: Thu Jan 01 00:00:20 1970 +0000
822 | | | | date: Thu Jan 01 00:00:20 1970 +0000
822 | | | | summary: (20) merge two known; two far right
823 | | | | summary: (20) merge two known; two far right
823 | | | |
824 | | | |
824 o | | | changeset: 19:31ddc2c1573b
825 o | | | changeset: 19:31ddc2c1573b
825 |\ \ \ \ parent: 15:1dda3f72782d
826 |\ \ \ \ parent: 15:1dda3f72782d
826 | | | | | parent: 17:44765d7c06e0
827 | | | | | parent: 17:44765d7c06e0
827 | | | | | user: test
828 | | | | | user: test
828 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
829 | | | | | date: Thu Jan 01 00:00:19 1970 +0000
829 | | | | | summary: (19) expand
830 | | | | | summary: (19) expand
830 | | | | |
831 | | | | |
831 +---+---o changeset: 18:1aa84d96232a
832 +---+---o changeset: 18:1aa84d96232a
832 | | | | parent: 1:6db2ef61d156
833 | | | | parent: 1:6db2ef61d156
833 | | | | parent: 15:1dda3f72782d
834 | | | | parent: 15:1dda3f72782d
834 | | | | user: test
835 | | | | user: test
835 | | | | date: Thu Jan 01 00:00:18 1970 +0000
836 | | | | date: Thu Jan 01 00:00:18 1970 +0000
836 | | | | summary: (18) merge two known; two far left
837 | | | | summary: (18) merge two known; two far left
837 | | | |
838 | | | |
838 | o | | changeset: 17:44765d7c06e0
839 | o | | changeset: 17:44765d7c06e0
839 | |\ \ \ parent: 12:86b91144a6e9
840 | |\ \ \ parent: 12:86b91144a6e9
840 | | | | | parent: 16:3677d192927d
841 | | | | | parent: 16:3677d192927d
841 | | | | | user: test
842 | | | | | user: test
842 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
843 | | | | | date: Thu Jan 01 00:00:17 1970 +0000
843 | | | | | summary: (17) expand
844 | | | | | summary: (17) expand
844 | | | | |
845 | | | | |
845 | | o---+ changeset: 16:3677d192927d
846 | | o---+ changeset: 16:3677d192927d
846 | | | | | parent: 0:e6eb3150255d
847 | | | | | parent: 0:e6eb3150255d
847 | | |/ / parent: 1:6db2ef61d156
848 | | |/ / parent: 1:6db2ef61d156
848 | | | | user: test
849 | | | | user: test
849 | | | | date: Thu Jan 01 00:00:16 1970 +0000
850 | | | | date: Thu Jan 01 00:00:16 1970 +0000
850 | | | | summary: (16) merge two known; one immediate right, one near right
851 | | | | summary: (16) merge two known; one immediate right, one near right
851 | | | |
852 | | | |
852 o | | | changeset: 15:1dda3f72782d
853 o | | | changeset: 15:1dda3f72782d
853 |\ \ \ \ parent: 13:22d8966a97e3
854 |\ \ \ \ parent: 13:22d8966a97e3
854 | | | | | parent: 14:8eac370358ef
855 | | | | | parent: 14:8eac370358ef
855 | | | | | user: test
856 | | | | | user: test
856 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
857 | | | | | date: Thu Jan 01 00:00:15 1970 +0000
857 | | | | | summary: (15) expand
858 | | | | | summary: (15) expand
858 | | | | |
859 | | | | |
859 | o-----+ changeset: 14:8eac370358ef
860 | o-----+ changeset: 14:8eac370358ef
860 | | | | | parent: 0:e6eb3150255d
861 | | | | | parent: 0:e6eb3150255d
861 | |/ / / parent: 12:86b91144a6e9
862 | |/ / / parent: 12:86b91144a6e9
862 | | | | user: test
863 | | | | user: test
863 | | | | date: Thu Jan 01 00:00:14 1970 +0000
864 | | | | date: Thu Jan 01 00:00:14 1970 +0000
864 | | | | summary: (14) merge two known; one immediate right, one far right
865 | | | | summary: (14) merge two known; one immediate right, one far right
865 | | | |
866 | | | |
866 o | | | changeset: 13:22d8966a97e3
867 o | | | changeset: 13:22d8966a97e3
867 |\ \ \ \ parent: 9:7010c0af0a35
868 |\ \ \ \ parent: 9:7010c0af0a35
868 | | | | | parent: 11:832d76e6bdf2
869 | | | | | parent: 11:832d76e6bdf2
869 | | | | | user: test
870 | | | | | user: test
870 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
871 | | | | | date: Thu Jan 01 00:00:13 1970 +0000
871 | | | | | summary: (13) expand
872 | | | | | summary: (13) expand
872 | | | | |
873 | | | | |
873 +---o | | changeset: 12:86b91144a6e9
874 +---o | | changeset: 12:86b91144a6e9
874 | | |/ / parent: 1:6db2ef61d156
875 | | |/ / parent: 1:6db2ef61d156
875 | | | | parent: 9:7010c0af0a35
876 | | | | parent: 9:7010c0af0a35
876 | | | | user: test
877 | | | | user: test
877 | | | | date: Thu Jan 01 00:00:12 1970 +0000
878 | | | | date: Thu Jan 01 00:00:12 1970 +0000
878 | | | | summary: (12) merge two known; one immediate right, one far left
879 | | | | summary: (12) merge two known; one immediate right, one far left
879 | | | |
880 | | | |
880 | o | | changeset: 11:832d76e6bdf2
881 | o | | changeset: 11:832d76e6bdf2
881 | |\ \ \ parent: 6:b105a072e251
882 | |\ \ \ parent: 6:b105a072e251
882 | | | | | parent: 10:74c64d036d72
883 | | | | | parent: 10:74c64d036d72
883 | | | | | user: test
884 | | | | | user: test
884 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
885 | | | | | date: Thu Jan 01 00:00:11 1970 +0000
885 | | | | | summary: (11) expand
886 | | | | | summary: (11) expand
886 | | | | |
887 | | | | |
887 | | o---+ changeset: 10:74c64d036d72
888 | | o---+ changeset: 10:74c64d036d72
888 | | | | | parent: 0:e6eb3150255d
889 | | | | | parent: 0:e6eb3150255d
889 | |/ / / parent: 6:b105a072e251
890 | |/ / / parent: 6:b105a072e251
890 | | | | user: test
891 | | | | user: test
891 | | | | date: Thu Jan 01 00:00:10 1970 +0000
892 | | | | date: Thu Jan 01 00:00:10 1970 +0000
892 | | | | summary: (10) merge two known; one immediate left, one near right
893 | | | | summary: (10) merge two known; one immediate left, one near right
893 | | | |
894 | | | |
894 o | | | changeset: 9:7010c0af0a35
895 o | | | changeset: 9:7010c0af0a35
895 |\ \ \ \ parent: 7:b632bb1b1224
896 |\ \ \ \ parent: 7:b632bb1b1224
896 | | | | | parent: 8:7a0b11f71937
897 | | | | | parent: 8:7a0b11f71937
897 | | | | | user: test
898 | | | | | user: test
898 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
899 | | | | | date: Thu Jan 01 00:00:09 1970 +0000
899 | | | | | summary: (9) expand
900 | | | | | summary: (9) expand
900 | | | | |
901 | | | | |
901 | o-----+ changeset: 8:7a0b11f71937
902 | o-----+ changeset: 8:7a0b11f71937
902 | | | | | parent: 0:e6eb3150255d
903 | | | | | parent: 0:e6eb3150255d
903 |/ / / / parent: 7:b632bb1b1224
904 |/ / / / parent: 7:b632bb1b1224
904 | | | | user: test
905 | | | | user: test
905 | | | | date: Thu Jan 01 00:00:08 1970 +0000
906 | | | | date: Thu Jan 01 00:00:08 1970 +0000
906 | | | | summary: (8) merge two known; one immediate left, one far right
907 | | | | summary: (8) merge two known; one immediate left, one far right
907 | | | |
908 | | | |
908 o | | | changeset: 7:b632bb1b1224
909 o | | | changeset: 7:b632bb1b1224
909 |\ \ \ \ parent: 2:3d9a33b8d1e1
910 |\ \ \ \ parent: 2:3d9a33b8d1e1
910 | | | | | parent: 5:4409d547b708
911 | | | | | parent: 5:4409d547b708
911 | | | | | user: test
912 | | | | | user: test
912 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
913 | | | | | date: Thu Jan 01 00:00:07 1970 +0000
913 | | | | | summary: (7) expand
914 | | | | | summary: (7) expand
914 | | | | |
915 | | | | |
915 +---o | | changeset: 6:b105a072e251
916 +---o | | changeset: 6:b105a072e251
916 | |/ / / parent: 2:3d9a33b8d1e1
917 | |/ / / parent: 2:3d9a33b8d1e1
917 | | | | parent: 5:4409d547b708
918 | | | | parent: 5:4409d547b708
918 | | | | user: test
919 | | | | user: test
919 | | | | date: Thu Jan 01 00:00:06 1970 +0000
920 | | | | date: Thu Jan 01 00:00:06 1970 +0000
920 | | | | summary: (6) merge two known; one immediate left, one far left
921 | | | | summary: (6) merge two known; one immediate left, one far left
921 | | | |
922 | | | |
922 | o | | changeset: 5:4409d547b708
923 | o | | changeset: 5:4409d547b708
923 | |\ \ \ parent: 3:27eef8ed80b4
924 | |\ \ \ parent: 3:27eef8ed80b4
924 | | | | | parent: 4:26a8bac39d9f
925 | | | | | parent: 4:26a8bac39d9f
925 | | | | | user: test
926 | | | | | user: test
926 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
927 | | | | | date: Thu Jan 01 00:00:05 1970 +0000
927 | | | | | summary: (5) expand
928 | | | | | summary: (5) expand
928 | | | | |
929 | | | | |
929 | | o | | changeset: 4:26a8bac39d9f
930 | | o | | changeset: 4:26a8bac39d9f
930 | |/|/ / parent: 1:6db2ef61d156
931 | |/|/ / parent: 1:6db2ef61d156
931 | | | | parent: 3:27eef8ed80b4
932 | | | | parent: 3:27eef8ed80b4
932 | | | | user: test
933 | | | | user: test
933 | | | | date: Thu Jan 01 00:00:04 1970 +0000
934 | | | | date: Thu Jan 01 00:00:04 1970 +0000
934 | | | | summary: (4) merge two known; one immediate left, one immediate right
935 | | | | summary: (4) merge two known; one immediate left, one immediate right
935 | | | |
936 | | | |
936 | o | | changeset: 3:27eef8ed80b4
937 | o | | changeset: 3:27eef8ed80b4
937 |/ / / user: test
938 |/ / / user: test
938 | | | date: Thu Jan 01 00:00:03 1970 +0000
939 | | | date: Thu Jan 01 00:00:03 1970 +0000
939 | | | summary: (3) collapse
940 | | | summary: (3) collapse
940 | | |
941 | | |
941 o | | changeset: 2:3d9a33b8d1e1
942 o | | changeset: 2:3d9a33b8d1e1
942 |/ / user: test
943 |/ / user: test
943 | | date: Thu Jan 01 00:00:02 1970 +0000
944 | | date: Thu Jan 01 00:00:02 1970 +0000
944 | | summary: (2) collapse
945 | | summary: (2) collapse
945 | |
946 | |
946 o | changeset: 1:6db2ef61d156
947 o | changeset: 1:6db2ef61d156
947 |/ user: test
948 |/ user: test
948 | date: Thu Jan 01 00:00:01 1970 +0000
949 | date: Thu Jan 01 00:00:01 1970 +0000
949 | summary: (1) collapse
950 | summary: (1) collapse
950 |
951 |
951 o changeset: 0:e6eb3150255d
952 o changeset: 0:e6eb3150255d
952 user: test
953 user: test
953 date: Thu Jan 01 00:00:00 1970 +0000
954 date: Thu Jan 01 00:00:00 1970 +0000
954 summary: (0) root
955 summary: (0) root
955
956
956
957
957
958
958 File glog per revset (only merges):
959 File glog per revset (only merges):
959
960
960 $ hg log -G -r 'file("a")' -m
961 $ hg log -G -r 'file("a")' -m
961 o changeset: 32:d06dffa21a31
962 o changeset: 32:d06dffa21a31
962 |\ parent: 27:886ed638191b
963 |\ parent: 27:886ed638191b
963 | : parent: 31:621d83e11f67
964 | : parent: 31:621d83e11f67
964 | : user: test
965 | : user: test
965 | : date: Thu Jan 01 00:00:32 1970 +0000
966 | : date: Thu Jan 01 00:00:32 1970 +0000
966 | : summary: (32) expand
967 | : summary: (32) expand
967 | :
968 | :
968 o : changeset: 31:621d83e11f67
969 o : changeset: 31:621d83e11f67
969 |\: parent: 21:d42a756af44d
970 |\: parent: 21:d42a756af44d
970 | : parent: 30:6e11cd4b648f
971 | : parent: 30:6e11cd4b648f
971 | : user: test
972 | : user: test
972 | : date: Thu Jan 01 00:00:31 1970 +0000
973 | : date: Thu Jan 01 00:00:31 1970 +0000
973 | : summary: (31) expand
974 | : summary: (31) expand
974 | :
975 | :
975 o : changeset: 30:6e11cd4b648f
976 o : changeset: 30:6e11cd4b648f
976 |\ \ parent: 28:44ecd0b9ae99
977 |\ \ parent: 28:44ecd0b9ae99
977 | ~ : parent: 29:cd9bb2be7593
978 | ~ : parent: 29:cd9bb2be7593
978 | : user: test
979 | : user: test
979 | : date: Thu Jan 01 00:00:30 1970 +0000
980 | : date: Thu Jan 01 00:00:30 1970 +0000
980 | : summary: (30) expand
981 | : summary: (30) expand
981 | /
982 | /
982 o : changeset: 28:44ecd0b9ae99
983 o : changeset: 28:44ecd0b9ae99
983 |\ \ parent: 1:6db2ef61d156
984 |\ \ parent: 1:6db2ef61d156
984 | ~ : parent: 26:7f25b6c2f0b9
985 | ~ : parent: 26:7f25b6c2f0b9
985 | : user: test
986 | : user: test
986 | : date: Thu Jan 01 00:00:28 1970 +0000
987 | : date: Thu Jan 01 00:00:28 1970 +0000
987 | : summary: (28) merge zero known
988 | : summary: (28) merge zero known
988 | /
989 | /
989 o : changeset: 26:7f25b6c2f0b9
990 o : changeset: 26:7f25b6c2f0b9
990 |\ \ parent: 18:1aa84d96232a
991 |\ \ parent: 18:1aa84d96232a
991 | | : parent: 25:91da8ed57247
992 | | : parent: 25:91da8ed57247
992 | | : user: test
993 | | : user: test
993 | | : date: Thu Jan 01 00:00:26 1970 +0000
994 | | : date: Thu Jan 01 00:00:26 1970 +0000
994 | | : summary: (26) merge one known; far right
995 | | : summary: (26) merge one known; far right
995 | | :
996 | | :
996 | o : changeset: 25:91da8ed57247
997 | o : changeset: 25:91da8ed57247
997 | |\: parent: 21:d42a756af44d
998 | |\: parent: 21:d42a756af44d
998 | | : parent: 24:a9c19a3d96b7
999 | | : parent: 24:a9c19a3d96b7
999 | | : user: test
1000 | | : user: test
1000 | | : date: Thu Jan 01 00:00:25 1970 +0000
1001 | | : date: Thu Jan 01 00:00:25 1970 +0000
1001 | | : summary: (25) merge one known; far left
1002 | | : summary: (25) merge one known; far left
1002 | | :
1003 | | :
1003 | o : changeset: 24:a9c19a3d96b7
1004 | o : changeset: 24:a9c19a3d96b7
1004 | |\ \ parent: 0:e6eb3150255d
1005 | |\ \ parent: 0:e6eb3150255d
1005 | | ~ : parent: 23:a01cddf0766d
1006 | | ~ : parent: 23:a01cddf0766d
1006 | | : user: test
1007 | | : user: test
1007 | | : date: Thu Jan 01 00:00:24 1970 +0000
1008 | | : date: Thu Jan 01 00:00:24 1970 +0000
1008 | | : summary: (24) merge one known; immediate right
1009 | | : summary: (24) merge one known; immediate right
1009 | | /
1010 | | /
1010 | o : changeset: 23:a01cddf0766d
1011 | o : changeset: 23:a01cddf0766d
1011 | |\ \ parent: 1:6db2ef61d156
1012 | |\ \ parent: 1:6db2ef61d156
1012 | | ~ : parent: 22:e0d9cccacb5d
1013 | | ~ : parent: 22:e0d9cccacb5d
1013 | | : user: test
1014 | | : user: test
1014 | | : date: Thu Jan 01 00:00:23 1970 +0000
1015 | | : date: Thu Jan 01 00:00:23 1970 +0000
1015 | | : summary: (23) merge one known; immediate left
1016 | | : summary: (23) merge one known; immediate left
1016 | | /
1017 | | /
1017 | o : changeset: 22:e0d9cccacb5d
1018 | o : changeset: 22:e0d9cccacb5d
1018 |/:/ parent: 18:1aa84d96232a
1019 |/:/ parent: 18:1aa84d96232a
1019 | : parent: 21:d42a756af44d
1020 | : parent: 21:d42a756af44d
1020 | : user: test
1021 | : user: test
1021 | : date: Thu Jan 01 00:00:22 1970 +0000
1022 | : date: Thu Jan 01 00:00:22 1970 +0000
1022 | : summary: (22) merge two known; one far left, one far right
1023 | : summary: (22) merge two known; one far left, one far right
1023 | :
1024 | :
1024 | o changeset: 21:d42a756af44d
1025 | o changeset: 21:d42a756af44d
1025 | |\ parent: 19:31ddc2c1573b
1026 | |\ parent: 19:31ddc2c1573b
1026 | | | parent: 20:d30ed6450e32
1027 | | | parent: 20:d30ed6450e32
1027 | | | user: test
1028 | | | user: test
1028 | | | date: Thu Jan 01 00:00:21 1970 +0000
1029 | | | date: Thu Jan 01 00:00:21 1970 +0000
1029 | | | summary: (21) expand
1030 | | | summary: (21) expand
1030 | | |
1031 | | |
1031 +---o changeset: 20:d30ed6450e32
1032 +---o changeset: 20:d30ed6450e32
1032 | | | parent: 0:e6eb3150255d
1033 | | | parent: 0:e6eb3150255d
1033 | | ~ parent: 18:1aa84d96232a
1034 | | ~ parent: 18:1aa84d96232a
1034 | | user: test
1035 | | user: test
1035 | | date: Thu Jan 01 00:00:20 1970 +0000
1036 | | date: Thu Jan 01 00:00:20 1970 +0000
1036 | | summary: (20) merge two known; two far right
1037 | | summary: (20) merge two known; two far right
1037 | |
1038 | |
1038 | o changeset: 19:31ddc2c1573b
1039 | o changeset: 19:31ddc2c1573b
1039 | |\ parent: 15:1dda3f72782d
1040 | |\ parent: 15:1dda3f72782d
1040 | | | parent: 17:44765d7c06e0
1041 | | | parent: 17:44765d7c06e0
1041 | | | user: test
1042 | | | user: test
1042 | | | date: Thu Jan 01 00:00:19 1970 +0000
1043 | | | date: Thu Jan 01 00:00:19 1970 +0000
1043 | | | summary: (19) expand
1044 | | | summary: (19) expand
1044 | | |
1045 | | |
1045 o | | changeset: 18:1aa84d96232a
1046 o | | changeset: 18:1aa84d96232a
1046 |\| | parent: 1:6db2ef61d156
1047 |\| | parent: 1:6db2ef61d156
1047 ~ | | parent: 15:1dda3f72782d
1048 ~ | | parent: 15:1dda3f72782d
1048 | | user: test
1049 | | user: test
1049 | | date: Thu Jan 01 00:00:18 1970 +0000
1050 | | date: Thu Jan 01 00:00:18 1970 +0000
1050 | | summary: (18) merge two known; two far left
1051 | | summary: (18) merge two known; two far left
1051 / /
1052 / /
1052 | o changeset: 17:44765d7c06e0
1053 | o changeset: 17:44765d7c06e0
1053 | |\ parent: 12:86b91144a6e9
1054 | |\ parent: 12:86b91144a6e9
1054 | | | parent: 16:3677d192927d
1055 | | | parent: 16:3677d192927d
1055 | | | user: test
1056 | | | user: test
1056 | | | date: Thu Jan 01 00:00:17 1970 +0000
1057 | | | date: Thu Jan 01 00:00:17 1970 +0000
1057 | | | summary: (17) expand
1058 | | | summary: (17) expand
1058 | | |
1059 | | |
1059 | | o changeset: 16:3677d192927d
1060 | | o changeset: 16:3677d192927d
1060 | | |\ parent: 0:e6eb3150255d
1061 | | |\ parent: 0:e6eb3150255d
1061 | | ~ ~ parent: 1:6db2ef61d156
1062 | | ~ ~ parent: 1:6db2ef61d156
1062 | | user: test
1063 | | user: test
1063 | | date: Thu Jan 01 00:00:16 1970 +0000
1064 | | date: Thu Jan 01 00:00:16 1970 +0000
1064 | | summary: (16) merge two known; one immediate right, one near right
1065 | | summary: (16) merge two known; one immediate right, one near right
1065 | |
1066 | |
1066 o | changeset: 15:1dda3f72782d
1067 o | changeset: 15:1dda3f72782d
1067 |\ \ parent: 13:22d8966a97e3
1068 |\ \ parent: 13:22d8966a97e3
1068 | | | parent: 14:8eac370358ef
1069 | | | parent: 14:8eac370358ef
1069 | | | user: test
1070 | | | user: test
1070 | | | date: Thu Jan 01 00:00:15 1970 +0000
1071 | | | date: Thu Jan 01 00:00:15 1970 +0000
1071 | | | summary: (15) expand
1072 | | | summary: (15) expand
1072 | | |
1073 | | |
1073 | o | changeset: 14:8eac370358ef
1074 | o | changeset: 14:8eac370358ef
1074 | |\| parent: 0:e6eb3150255d
1075 | |\| parent: 0:e6eb3150255d
1075 | ~ | parent: 12:86b91144a6e9
1076 | ~ | parent: 12:86b91144a6e9
1076 | | user: test
1077 | | user: test
1077 | | date: Thu Jan 01 00:00:14 1970 +0000
1078 | | date: Thu Jan 01 00:00:14 1970 +0000
1078 | | summary: (14) merge two known; one immediate right, one far right
1079 | | summary: (14) merge two known; one immediate right, one far right
1079 | /
1080 | /
1080 o | changeset: 13:22d8966a97e3
1081 o | changeset: 13:22d8966a97e3
1081 |\ \ parent: 9:7010c0af0a35
1082 |\ \ parent: 9:7010c0af0a35
1082 | | | parent: 11:832d76e6bdf2
1083 | | | parent: 11:832d76e6bdf2
1083 | | | user: test
1084 | | | user: test
1084 | | | date: Thu Jan 01 00:00:13 1970 +0000
1085 | | | date: Thu Jan 01 00:00:13 1970 +0000
1085 | | | summary: (13) expand
1086 | | | summary: (13) expand
1086 | | |
1087 | | |
1087 +---o changeset: 12:86b91144a6e9
1088 +---o changeset: 12:86b91144a6e9
1088 | | | parent: 1:6db2ef61d156
1089 | | | parent: 1:6db2ef61d156
1089 | | ~ parent: 9:7010c0af0a35
1090 | | ~ parent: 9:7010c0af0a35
1090 | | user: test
1091 | | user: test
1091 | | date: Thu Jan 01 00:00:12 1970 +0000
1092 | | date: Thu Jan 01 00:00:12 1970 +0000
1092 | | summary: (12) merge two known; one immediate right, one far left
1093 | | summary: (12) merge two known; one immediate right, one far left
1093 | |
1094 | |
1094 | o changeset: 11:832d76e6bdf2
1095 | o changeset: 11:832d76e6bdf2
1095 | |\ parent: 6:b105a072e251
1096 | |\ parent: 6:b105a072e251
1096 | | | parent: 10:74c64d036d72
1097 | | | parent: 10:74c64d036d72
1097 | | | user: test
1098 | | | user: test
1098 | | | date: Thu Jan 01 00:00:11 1970 +0000
1099 | | | date: Thu Jan 01 00:00:11 1970 +0000
1099 | | | summary: (11) expand
1100 | | | summary: (11) expand
1100 | | |
1101 | | |
1101 | | o changeset: 10:74c64d036d72
1102 | | o changeset: 10:74c64d036d72
1102 | |/| parent: 0:e6eb3150255d
1103 | |/| parent: 0:e6eb3150255d
1103 | | ~ parent: 6:b105a072e251
1104 | | ~ parent: 6:b105a072e251
1104 | | user: test
1105 | | user: test
1105 | | date: Thu Jan 01 00:00:10 1970 +0000
1106 | | date: Thu Jan 01 00:00:10 1970 +0000
1106 | | summary: (10) merge two known; one immediate left, one near right
1107 | | summary: (10) merge two known; one immediate left, one near right
1107 | |
1108 | |
1108 o | changeset: 9:7010c0af0a35
1109 o | changeset: 9:7010c0af0a35
1109 |\ \ parent: 7:b632bb1b1224
1110 |\ \ parent: 7:b632bb1b1224
1110 | | | parent: 8:7a0b11f71937
1111 | | | parent: 8:7a0b11f71937
1111 | | | user: test
1112 | | | user: test
1112 | | | date: Thu Jan 01 00:00:09 1970 +0000
1113 | | | date: Thu Jan 01 00:00:09 1970 +0000
1113 | | | summary: (9) expand
1114 | | | summary: (9) expand
1114 | | |
1115 | | |
1115 | o | changeset: 8:7a0b11f71937
1116 | o | changeset: 8:7a0b11f71937
1116 |/| | parent: 0:e6eb3150255d
1117 |/| | parent: 0:e6eb3150255d
1117 | ~ | parent: 7:b632bb1b1224
1118 | ~ | parent: 7:b632bb1b1224
1118 | | user: test
1119 | | user: test
1119 | | date: Thu Jan 01 00:00:08 1970 +0000
1120 | | date: Thu Jan 01 00:00:08 1970 +0000
1120 | | summary: (8) merge two known; one immediate left, one far right
1121 | | summary: (8) merge two known; one immediate left, one far right
1121 | /
1122 | /
1122 o | changeset: 7:b632bb1b1224
1123 o | changeset: 7:b632bb1b1224
1123 |\ \ parent: 2:3d9a33b8d1e1
1124 |\ \ parent: 2:3d9a33b8d1e1
1124 | ~ | parent: 5:4409d547b708
1125 | ~ | parent: 5:4409d547b708
1125 | | user: test
1126 | | user: test
1126 | | date: Thu Jan 01 00:00:07 1970 +0000
1127 | | date: Thu Jan 01 00:00:07 1970 +0000
1127 | | summary: (7) expand
1128 | | summary: (7) expand
1128 | /
1129 | /
1129 | o changeset: 6:b105a072e251
1130 | o changeset: 6:b105a072e251
1130 |/| parent: 2:3d9a33b8d1e1
1131 |/| parent: 2:3d9a33b8d1e1
1131 | ~ parent: 5:4409d547b708
1132 | ~ parent: 5:4409d547b708
1132 | user: test
1133 | user: test
1133 | date: Thu Jan 01 00:00:06 1970 +0000
1134 | date: Thu Jan 01 00:00:06 1970 +0000
1134 | summary: (6) merge two known; one immediate left, one far left
1135 | summary: (6) merge two known; one immediate left, one far left
1135 |
1136 |
1136 o changeset: 5:4409d547b708
1137 o changeset: 5:4409d547b708
1137 |\ parent: 3:27eef8ed80b4
1138 |\ parent: 3:27eef8ed80b4
1138 | ~ parent: 4:26a8bac39d9f
1139 | ~ parent: 4:26a8bac39d9f
1139 | user: test
1140 | user: test
1140 | date: Thu Jan 01 00:00:05 1970 +0000
1141 | date: Thu Jan 01 00:00:05 1970 +0000
1141 | summary: (5) expand
1142 | summary: (5) expand
1142 |
1143 |
1143 o changeset: 4:26a8bac39d9f
1144 o changeset: 4:26a8bac39d9f
1144 |\ parent: 1:6db2ef61d156
1145 |\ parent: 1:6db2ef61d156
1145 ~ ~ parent: 3:27eef8ed80b4
1146 ~ ~ parent: 3:27eef8ed80b4
1146 user: test
1147 user: test
1147 date: Thu Jan 01 00:00:04 1970 +0000
1148 date: Thu Jan 01 00:00:04 1970 +0000
1148 summary: (4) merge two known; one immediate left, one immediate right
1149 summary: (4) merge two known; one immediate left, one immediate right
1149
1150
1150
1151
1151
1152
1152 Empty revision range - display nothing:
1153 Empty revision range - display nothing:
1153 $ hg log -G -r 1..0
1154 $ hg log -G -r 1..0
1154
1155
1155 $ cd ..
1156 $ cd ..
1156
1157
1157 #if no-outer-repo
1158 #if no-outer-repo
1158
1159
1159 From outer space:
1160 From outer space:
1160 $ hg log -G -l1 repo
1161 $ hg log -G -l1 repo
1161 @ changeset: 34:fea3ac5810e0
1162 @ changeset: 34:fea3ac5810e0
1162 | tag: tip
1163 | tag: tip
1163 ~ parent: 32:d06dffa21a31
1164 ~ parent: 32:d06dffa21a31
1164 user: test
1165 user: test
1165 date: Thu Jan 01 00:00:34 1970 +0000
1166 date: Thu Jan 01 00:00:34 1970 +0000
1166 summary: (34) head
1167 summary: (34) head
1167
1168
1168 $ hg log -G -l1 repo/a
1169 $ hg log -G -l1 repo/a
1169 @ changeset: 34:fea3ac5810e0
1170 @ changeset: 34:fea3ac5810e0
1170 | tag: tip
1171 | tag: tip
1171 ~ parent: 32:d06dffa21a31
1172 ~ parent: 32:d06dffa21a31
1172 user: test
1173 user: test
1173 date: Thu Jan 01 00:00:34 1970 +0000
1174 date: Thu Jan 01 00:00:34 1970 +0000
1174 summary: (34) head
1175 summary: (34) head
1175
1176
1176 $ hg log -G -l1 repo/missing
1177 $ hg log -G -l1 repo/missing
1177
1178
1178 #endif
1179 #endif
1179
1180
1180 File log with revs != cset revs:
1181 File log with revs != cset revs:
1181 $ hg init flog
1182 $ hg init flog
1182 $ cd flog
1183 $ cd flog
1183 $ echo one >one
1184 $ echo one >one
1184 $ hg add one
1185 $ hg add one
1185 $ hg commit -mone
1186 $ hg commit -mone
1186 $ echo two >two
1187 $ echo two >two
1187 $ hg add two
1188 $ hg add two
1188 $ hg commit -mtwo
1189 $ hg commit -mtwo
1189 $ echo more >two
1190 $ echo more >two
1190 $ hg commit -mmore
1191 $ hg commit -mmore
1191 $ hg log -G two
1192 $ hg log -G two
1192 @ changeset: 2:12c28321755b
1193 @ changeset: 2:12c28321755b
1193 | tag: tip
1194 | tag: tip
1194 | user: test
1195 | user: test
1195 | date: Thu Jan 01 00:00:00 1970 +0000
1196 | date: Thu Jan 01 00:00:00 1970 +0000
1196 | summary: more
1197 | summary: more
1197 |
1198 |
1198 o changeset: 1:5ac72c0599bf
1199 o changeset: 1:5ac72c0599bf
1199 | user: test
1200 | user: test
1200 ~ date: Thu Jan 01 00:00:00 1970 +0000
1201 ~ date: Thu Jan 01 00:00:00 1970 +0000
1201 summary: two
1202 summary: two
1202
1203
1203
1204
1204 Issue1896: File log with explicit style
1205 Issue1896: File log with explicit style
1205 $ hg log -G --style=default one
1206 $ hg log -G --style=default one
1206 o changeset: 0:3d578b4a1f53
1207 o changeset: 0:3d578b4a1f53
1207 user: test
1208 user: test
1208 date: Thu Jan 01 00:00:00 1970 +0000
1209 date: Thu Jan 01 00:00:00 1970 +0000
1209 summary: one
1210 summary: one
1210
1211
1211 Issue2395: glog --style header and footer
1212 Issue2395: glog --style header and footer
1212 $ hg log -G --style=xml one
1213 $ hg log -G --style=xml one
1213 <?xml version="1.0"?>
1214 <?xml version="1.0"?>
1214 <log>
1215 <log>
1215 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1216 o <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
1216 <author email="test">test</author>
1217 <author email="test">test</author>
1217 <date>1970-01-01T00:00:00+00:00</date>
1218 <date>1970-01-01T00:00:00+00:00</date>
1218 <msg xml:space="preserve">one</msg>
1219 <msg xml:space="preserve">one</msg>
1219 </logentry>
1220 </logentry>
1220 </log>
1221 </log>
1221
1222
1222 $ cd ..
1223 $ cd ..
1223
1224
1224 Incoming and outgoing:
1225 Incoming and outgoing:
1225
1226
1226 $ hg clone -U -r31 repo repo2
1227 $ hg clone -U -r31 repo repo2
1227 adding changesets
1228 adding changesets
1228 adding manifests
1229 adding manifests
1229 adding file changes
1230 adding file changes
1230 added 31 changesets with 31 changes to 1 files
1231 added 31 changesets with 31 changes to 1 files
1231 new changesets e6eb3150255d:621d83e11f67
1232 new changesets e6eb3150255d:621d83e11f67
1232 $ cd repo2
1233 $ cd repo2
1233
1234
1234 $ hg incoming --graph ../repo
1235 $ hg incoming --graph ../repo
1235 comparing with ../repo
1236 comparing with ../repo
1236 searching for changes
1237 searching for changes
1237 o changeset: 34:fea3ac5810e0
1238 o changeset: 34:fea3ac5810e0
1238 | tag: tip
1239 | tag: tip
1239 | parent: 32:d06dffa21a31
1240 | parent: 32:d06dffa21a31
1240 | user: test
1241 | user: test
1241 | date: Thu Jan 01 00:00:34 1970 +0000
1242 | date: Thu Jan 01 00:00:34 1970 +0000
1242 | summary: (34) head
1243 | summary: (34) head
1243 |
1244 |
1244 | o changeset: 33:68608f5145f9
1245 | o changeset: 33:68608f5145f9
1245 | parent: 18:1aa84d96232a
1246 | parent: 18:1aa84d96232a
1246 | user: test
1247 | user: test
1247 | date: Thu Jan 01 00:00:33 1970 +0000
1248 | date: Thu Jan 01 00:00:33 1970 +0000
1248 | summary: (33) head
1249 | summary: (33) head
1249 |
1250 |
1250 o changeset: 32:d06dffa21a31
1251 o changeset: 32:d06dffa21a31
1251 | parent: 27:886ed638191b
1252 | parent: 27:886ed638191b
1252 | parent: 31:621d83e11f67
1253 | parent: 31:621d83e11f67
1253 | user: test
1254 | user: test
1254 | date: Thu Jan 01 00:00:32 1970 +0000
1255 | date: Thu Jan 01 00:00:32 1970 +0000
1255 | summary: (32) expand
1256 | summary: (32) expand
1256 |
1257 |
1257 o changeset: 27:886ed638191b
1258 o changeset: 27:886ed638191b
1258 parent: 21:d42a756af44d
1259 parent: 21:d42a756af44d
1259 user: test
1260 user: test
1260 date: Thu Jan 01 00:00:27 1970 +0000
1261 date: Thu Jan 01 00:00:27 1970 +0000
1261 summary: (27) collapse
1262 summary: (27) collapse
1262
1263
1263 $ cd ..
1264 $ cd ..
1264
1265
1265 $ hg -R repo outgoing --graph repo2
1266 $ hg -R repo outgoing --graph repo2
1266 comparing with repo2
1267 comparing with repo2
1267 searching for changes
1268 searching for changes
1268 @ changeset: 34:fea3ac5810e0
1269 @ changeset: 34:fea3ac5810e0
1269 | tag: tip
1270 | tag: tip
1270 | parent: 32:d06dffa21a31
1271 | parent: 32:d06dffa21a31
1271 | user: test
1272 | user: test
1272 | date: Thu Jan 01 00:00:34 1970 +0000
1273 | date: Thu Jan 01 00:00:34 1970 +0000
1273 | summary: (34) head
1274 | summary: (34) head
1274 |
1275 |
1275 | o changeset: 33:68608f5145f9
1276 | o changeset: 33:68608f5145f9
1276 | parent: 18:1aa84d96232a
1277 | parent: 18:1aa84d96232a
1277 | user: test
1278 | user: test
1278 | date: Thu Jan 01 00:00:33 1970 +0000
1279 | date: Thu Jan 01 00:00:33 1970 +0000
1279 | summary: (33) head
1280 | summary: (33) head
1280 |
1281 |
1281 o changeset: 32:d06dffa21a31
1282 o changeset: 32:d06dffa21a31
1282 | parent: 27:886ed638191b
1283 | parent: 27:886ed638191b
1283 | parent: 31:621d83e11f67
1284 | parent: 31:621d83e11f67
1284 | user: test
1285 | user: test
1285 | date: Thu Jan 01 00:00:32 1970 +0000
1286 | date: Thu Jan 01 00:00:32 1970 +0000
1286 | summary: (32) expand
1287 | summary: (32) expand
1287 |
1288 |
1288 o changeset: 27:886ed638191b
1289 o changeset: 27:886ed638191b
1289 parent: 21:d42a756af44d
1290 parent: 21:d42a756af44d
1290 user: test
1291 user: test
1291 date: Thu Jan 01 00:00:27 1970 +0000
1292 date: Thu Jan 01 00:00:27 1970 +0000
1292 summary: (27) collapse
1293 summary: (27) collapse
1293
1294
1294
1295
1295 File + limit with revs != cset revs:
1296 File + limit with revs != cset revs:
1296 $ cd repo
1297 $ cd repo
1297 $ touch b
1298 $ touch b
1298 $ hg ci -Aqm0
1299 $ hg ci -Aqm0
1299 $ hg log -G -l2 a
1300 $ hg log -G -l2 a
1300 o changeset: 34:fea3ac5810e0
1301 o changeset: 34:fea3ac5810e0
1301 | parent: 32:d06dffa21a31
1302 | parent: 32:d06dffa21a31
1302 ~ user: test
1303 ~ user: test
1303 date: Thu Jan 01 00:00:34 1970 +0000
1304 date: Thu Jan 01 00:00:34 1970 +0000
1304 summary: (34) head
1305 summary: (34) head
1305
1306
1306 o changeset: 33:68608f5145f9
1307 o changeset: 33:68608f5145f9
1307 | parent: 18:1aa84d96232a
1308 | parent: 18:1aa84d96232a
1308 ~ user: test
1309 ~ user: test
1309 date: Thu Jan 01 00:00:33 1970 +0000
1310 date: Thu Jan 01 00:00:33 1970 +0000
1310 summary: (33) head
1311 summary: (33) head
1311
1312
1312
1313
1313 File + limit + -ra:b, (b - a) < limit:
1314 File + limit + -ra:b, (b - a) < limit:
1314 $ hg log -G -l3000 -r32:tip a
1315 $ hg log -G -l3000 -r32:tip a
1315 o changeset: 34:fea3ac5810e0
1316 o changeset: 34:fea3ac5810e0
1316 | parent: 32:d06dffa21a31
1317 | parent: 32:d06dffa21a31
1317 | user: test
1318 | user: test
1318 | date: Thu Jan 01 00:00:34 1970 +0000
1319 | date: Thu Jan 01 00:00:34 1970 +0000
1319 | summary: (34) head
1320 | summary: (34) head
1320 |
1321 |
1321 | o changeset: 33:68608f5145f9
1322 | o changeset: 33:68608f5145f9
1322 | | parent: 18:1aa84d96232a
1323 | | parent: 18:1aa84d96232a
1323 | ~ user: test
1324 | ~ user: test
1324 | date: Thu Jan 01 00:00:33 1970 +0000
1325 | date: Thu Jan 01 00:00:33 1970 +0000
1325 | summary: (33) head
1326 | summary: (33) head
1326 |
1327 |
1327 o changeset: 32:d06dffa21a31
1328 o changeset: 32:d06dffa21a31
1328 |\ parent: 27:886ed638191b
1329 |\ parent: 27:886ed638191b
1329 ~ ~ parent: 31:621d83e11f67
1330 ~ ~ parent: 31:621d83e11f67
1330 user: test
1331 user: test
1331 date: Thu Jan 01 00:00:32 1970 +0000
1332 date: Thu Jan 01 00:00:32 1970 +0000
1332 summary: (32) expand
1333 summary: (32) expand
1333
1334
1334
1335
1335 Point out a common and an uncommon unshown parent
1336 Point out a common and an uncommon unshown parent
1336
1337
1337 $ hg log -G -r 'rev(8) or rev(9)'
1338 $ hg log -G -r 'rev(8) or rev(9)'
1338 o changeset: 9:7010c0af0a35
1339 o changeset: 9:7010c0af0a35
1339 |\ parent: 7:b632bb1b1224
1340 |\ parent: 7:b632bb1b1224
1340 | ~ parent: 8:7a0b11f71937
1341 | ~ parent: 8:7a0b11f71937
1341 | user: test
1342 | user: test
1342 | date: Thu Jan 01 00:00:09 1970 +0000
1343 | date: Thu Jan 01 00:00:09 1970 +0000
1343 | summary: (9) expand
1344 | summary: (9) expand
1344 |
1345 |
1345 o changeset: 8:7a0b11f71937
1346 o changeset: 8:7a0b11f71937
1346 |\ parent: 0:e6eb3150255d
1347 |\ parent: 0:e6eb3150255d
1347 ~ ~ parent: 7:b632bb1b1224
1348 ~ ~ parent: 7:b632bb1b1224
1348 user: test
1349 user: test
1349 date: Thu Jan 01 00:00:08 1970 +0000
1350 date: Thu Jan 01 00:00:08 1970 +0000
1350 summary: (8) merge two known; one immediate left, one far right
1351 summary: (8) merge two known; one immediate left, one far right
1351
1352
1352
1353
1353 File + limit + -ra:b, b < tip:
1354 File + limit + -ra:b, b < tip:
1354
1355
1355 $ hg log -G -l1 -r32:34 a
1356 $ hg log -G -l1 -r32:34 a
1356 o changeset: 34:fea3ac5810e0
1357 o changeset: 34:fea3ac5810e0
1357 | parent: 32:d06dffa21a31
1358 | parent: 32:d06dffa21a31
1358 ~ user: test
1359 ~ user: test
1359 date: Thu Jan 01 00:00:34 1970 +0000
1360 date: Thu Jan 01 00:00:34 1970 +0000
1360 summary: (34) head
1361 summary: (34) head
1361
1362
1362
1363
1363 file(File) + limit + -ra:b, b < tip:
1364 file(File) + limit + -ra:b, b < tip:
1364
1365
1365 $ hg log -G -l1 -r32:34 -r 'file("a")'
1366 $ hg log -G -l1 -r32:34 -r 'file("a")'
1366 o changeset: 34:fea3ac5810e0
1367 o changeset: 34:fea3ac5810e0
1367 | parent: 32:d06dffa21a31
1368 | parent: 32:d06dffa21a31
1368 ~ user: test
1369 ~ user: test
1369 date: Thu Jan 01 00:00:34 1970 +0000
1370 date: Thu Jan 01 00:00:34 1970 +0000
1370 summary: (34) head
1371 summary: (34) head
1371
1372
1372
1373
1373 limit(file(File) and a::b), b < tip:
1374 limit(file(File) and a::b), b < tip:
1374
1375
1375 $ hg log -G -r 'limit(file("a") and 32::34, 1)'
1376 $ hg log -G -r 'limit(file("a") and 32::34, 1)'
1376 o changeset: 32:d06dffa21a31
1377 o changeset: 32:d06dffa21a31
1377 |\ parent: 27:886ed638191b
1378 |\ parent: 27:886ed638191b
1378 ~ ~ parent: 31:621d83e11f67
1379 ~ ~ parent: 31:621d83e11f67
1379 user: test
1380 user: test
1380 date: Thu Jan 01 00:00:32 1970 +0000
1381 date: Thu Jan 01 00:00:32 1970 +0000
1381 summary: (32) expand
1382 summary: (32) expand
1382
1383
1383
1384
1384 File + limit + -ra:b, b < tip:
1385 File + limit + -ra:b, b < tip:
1385
1386
1386 $ hg log -G -r 'limit(file("a") and 34::32, 1)'
1387 $ hg log -G -r 'limit(file("a") and 34::32, 1)'
1387
1388
1388 File + limit + -ra:b, b < tip, (b - a) < limit:
1389 File + limit + -ra:b, b < tip, (b - a) < limit:
1389
1390
1390 $ hg log -G -l10 -r33:34 a
1391 $ hg log -G -l10 -r33:34 a
1391 o changeset: 34:fea3ac5810e0
1392 o changeset: 34:fea3ac5810e0
1392 | parent: 32:d06dffa21a31
1393 | parent: 32:d06dffa21a31
1393 ~ user: test
1394 ~ user: test
1394 date: Thu Jan 01 00:00:34 1970 +0000
1395 date: Thu Jan 01 00:00:34 1970 +0000
1395 summary: (34) head
1396 summary: (34) head
1396
1397
1397 o changeset: 33:68608f5145f9
1398 o changeset: 33:68608f5145f9
1398 | parent: 18:1aa84d96232a
1399 | parent: 18:1aa84d96232a
1399 ~ user: test
1400 ~ user: test
1400 date: Thu Jan 01 00:00:33 1970 +0000
1401 date: Thu Jan 01 00:00:33 1970 +0000
1401 summary: (33) head
1402 summary: (33) head
1402
1403
1403
1404
1404 Do not crash or produce strange graphs if history is buggy
1405 Do not crash or produce strange graphs if history is buggy
1405
1406
1406 $ hg branch branch
1407 $ hg branch branch
1407 marked working directory as branch branch
1408 marked working directory as branch branch
1408 (branches are permanent and global, did you want a bookmark?)
1409 (branches are permanent and global, did you want a bookmark?)
1409 $ commit 36 "buggy merge: identical parents" 35 35
1410 $ commit 36 "buggy merge: identical parents" 35 35
1410 $ hg log -G -l5
1411 $ hg log -G -l5
1411 @ changeset: 36:08a19a744424
1412 @ changeset: 36:08a19a744424
1412 | branch: branch
1413 | branch: branch
1413 | tag: tip
1414 | tag: tip
1414 | parent: 35:9159c3644c5e
1415 | parent: 35:9159c3644c5e
1415 | parent: 35:9159c3644c5e
1416 | parent: 35:9159c3644c5e
1416 | user: test
1417 | user: test
1417 | date: Thu Jan 01 00:00:36 1970 +0000
1418 | date: Thu Jan 01 00:00:36 1970 +0000
1418 | summary: (36) buggy merge: identical parents
1419 | summary: (36) buggy merge: identical parents
1419 |
1420 |
1420 o changeset: 35:9159c3644c5e
1421 o changeset: 35:9159c3644c5e
1421 | user: test
1422 | user: test
1422 | date: Thu Jan 01 00:00:00 1970 +0000
1423 | date: Thu Jan 01 00:00:00 1970 +0000
1423 | summary: 0
1424 | summary: 0
1424 |
1425 |
1425 o changeset: 34:fea3ac5810e0
1426 o changeset: 34:fea3ac5810e0
1426 | parent: 32:d06dffa21a31
1427 | parent: 32:d06dffa21a31
1427 | user: test
1428 | user: test
1428 | date: Thu Jan 01 00:00:34 1970 +0000
1429 | date: Thu Jan 01 00:00:34 1970 +0000
1429 | summary: (34) head
1430 | summary: (34) head
1430 |
1431 |
1431 | o changeset: 33:68608f5145f9
1432 | o changeset: 33:68608f5145f9
1432 | | parent: 18:1aa84d96232a
1433 | | parent: 18:1aa84d96232a
1433 | ~ user: test
1434 | ~ user: test
1434 | date: Thu Jan 01 00:00:33 1970 +0000
1435 | date: Thu Jan 01 00:00:33 1970 +0000
1435 | summary: (33) head
1436 | summary: (33) head
1436 |
1437 |
1437 o changeset: 32:d06dffa21a31
1438 o changeset: 32:d06dffa21a31
1438 |\ parent: 27:886ed638191b
1439 |\ parent: 27:886ed638191b
1439 ~ ~ parent: 31:621d83e11f67
1440 ~ ~ parent: 31:621d83e11f67
1440 user: test
1441 user: test
1441 date: Thu Jan 01 00:00:32 1970 +0000
1442 date: Thu Jan 01 00:00:32 1970 +0000
1442 summary: (32) expand
1443 summary: (32) expand
1443
1444
1444
1445
1445 Test log -G options
1446 Test log -G options
1446
1447
1447 $ testlog() {
1448 $ testlog() {
1448 > hg log -G --print-revset "$@"
1449 > hg log -G --print-revset "$@"
1449 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1450 > hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
1450 > | sed 's/.*nodetag/nodetag/' > log.nodes
1451 > | sed 's/.*nodetag/nodetag/' > log.nodes
1451 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1452 > hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
1452 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1453 > | sed 's/.*nodetag/nodetag/' > glog.nodes
1453 > (cmp log.nodes glog.nodes || diff -u log.nodes glog.nodes) \
1454 > (cmp log.nodes glog.nodes || diff -u log.nodes glog.nodes) \
1454 > | grep '^[-+@ ]' || :
1455 > | grep '^[-+@ ]' || :
1455 > }
1456 > }
1456
1457
1457 glog always reorders nodes which explains the difference with log
1458 glog always reorders nodes which explains the difference with log
1458
1459
1459 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1460 $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
1460 ['27', '25', '21', '34', '32', '31']
1461 ['27', '25', '21', '34', '32', '31']
1461 []
1462 []
1462 <baseset- [21, 25, 27, 31, 32, 34]>
1463 <baseset- [21, 25, 27, 31, 32, 34]>
1463 --- log.nodes * (glob)
1464 --- log.nodes * (glob)
1464 +++ glog.nodes * (glob)
1465 +++ glog.nodes * (glob)
1465 @@ -1,6 +1,6 @@
1466 @@ -1,6 +1,6 @@
1466 -nodetag 27
1467 -nodetag 27
1467 -nodetag 25
1468 -nodetag 25
1468 -nodetag 21
1469 -nodetag 21
1469 nodetag 34
1470 nodetag 34
1470 nodetag 32
1471 nodetag 32
1471 nodetag 31
1472 nodetag 31
1472 +nodetag 27
1473 +nodetag 27
1473 +nodetag 25
1474 +nodetag 25
1474 +nodetag 21
1475 +nodetag 21
1475 $ testlog -u test -u not-a-user
1476 $ testlog -u test -u not-a-user
1476 []
1477 []
1477 (or
1478 (or
1478 (list
1479 (list
1479 (func
1480 (func
1480 (symbol 'user')
1481 (symbol 'user')
1481 (string 'test'))
1482 (string 'test'))
1482 (func
1483 (func
1483 (symbol 'user')
1484 (symbol 'user')
1484 (string 'not-a-user'))))
1485 (string 'not-a-user'))))
1485 <filteredset
1486 <filteredset
1486 <spanset- 0:37>,
1487 <spanset- 0:37>,
1487 <addset
1488 <addset
1488 <filteredset
1489 <filteredset
1489 <fullreposet+ 0:37>,
1490 <fullreposet+ 0:37>,
1490 <user 'test'>>,
1491 <user 'test'>>,
1491 <filteredset
1492 <filteredset
1492 <fullreposet+ 0:37>,
1493 <fullreposet+ 0:37>,
1493 <user 'not-a-user'>>>>
1494 <user 'not-a-user'>>>>
1494 $ testlog -b not-a-branch
1495 $ testlog -b not-a-branch
1495 abort: unknown revision 'not-a-branch'!
1496 abort: unknown revision 'not-a-branch'!
1496 abort: unknown revision 'not-a-branch'!
1497 abort: unknown revision 'not-a-branch'!
1497 abort: unknown revision 'not-a-branch'!
1498 abort: unknown revision 'not-a-branch'!
1498 $ testlog -b 35 -b 36 --only-branch branch
1499 $ testlog -b 35 -b 36 --only-branch branch
1499 []
1500 []
1500 (or
1501 (or
1501 (list
1502 (list
1502 (func
1503 (func
1503 (symbol 'branch')
1504 (symbol 'branch')
1504 (string 'default'))
1505 (string 'default'))
1505 (or
1506 (or
1506 (list
1507 (list
1507 (func
1508 (func
1508 (symbol 'branch')
1509 (symbol 'branch')
1509 (string 'branch'))
1510 (string 'branch'))
1510 (func
1511 (func
1511 (symbol 'branch')
1512 (symbol 'branch')
1512 (string 'branch'))))))
1513 (string 'branch'))))))
1513 <filteredset
1514 <filteredset
1514 <spanset- 0:37>,
1515 <spanset- 0:37>,
1515 <addset
1516 <addset
1516 <filteredset
1517 <filteredset
1517 <fullreposet+ 0:37>,
1518 <fullreposet+ 0:37>,
1518 <branch 'default'>>,
1519 <branch 'default'>>,
1519 <addset
1520 <addset
1520 <filteredset
1521 <filteredset
1521 <fullreposet+ 0:37>,
1522 <fullreposet+ 0:37>,
1522 <branch 'branch'>>,
1523 <branch 'branch'>>,
1523 <filteredset
1524 <filteredset
1524 <fullreposet+ 0:37>,
1525 <fullreposet+ 0:37>,
1525 <branch 'branch'>>>>>
1526 <branch 'branch'>>>>>
1526 $ testlog -k expand -k merge
1527 $ testlog -k expand -k merge
1527 []
1528 []
1528 (or
1529 (or
1529 (list
1530 (list
1530 (func
1531 (func
1531 (symbol 'keyword')
1532 (symbol 'keyword')
1532 (string 'expand'))
1533 (string 'expand'))
1533 (func
1534 (func
1534 (symbol 'keyword')
1535 (symbol 'keyword')
1535 (string 'merge'))))
1536 (string 'merge'))))
1536 <filteredset
1537 <filteredset
1537 <spanset- 0:37>,
1538 <spanset- 0:37>,
1538 <addset
1539 <addset
1539 <filteredset
1540 <filteredset
1540 <fullreposet+ 0:37>,
1541 <fullreposet+ 0:37>,
1541 <keyword 'expand'>>,
1542 <keyword 'expand'>>,
1542 <filteredset
1543 <filteredset
1543 <fullreposet+ 0:37>,
1544 <fullreposet+ 0:37>,
1544 <keyword 'merge'>>>>
1545 <keyword 'merge'>>>>
1545 $ testlog --only-merges
1546 $ testlog --only-merges
1546 []
1547 []
1547 (func
1548 (func
1548 (symbol 'merge')
1549 (symbol 'merge')
1549 None)
1550 None)
1550 <filteredset
1551 <filteredset
1551 <spanset- 0:37>,
1552 <spanset- 0:37>,
1552 <merge>>
1553 <merge>>
1553 $ testlog --no-merges
1554 $ testlog --no-merges
1554 []
1555 []
1555 (not
1556 (not
1556 (func
1557 (func
1557 (symbol 'merge')
1558 (symbol 'merge')
1558 None))
1559 None))
1559 <filteredset
1560 <filteredset
1560 <spanset- 0:37>,
1561 <spanset- 0:37>,
1561 <not
1562 <not
1562 <filteredset
1563 <filteredset
1563 <spanset- 0:37>,
1564 <spanset- 0:37>,
1564 <merge>>>>
1565 <merge>>>>
1565 $ testlog --date '2 0 to 4 0'
1566 $ testlog --date '2 0 to 4 0'
1566 []
1567 []
1567 (func
1568 (func
1568 (symbol 'date')
1569 (symbol 'date')
1569 (string '2 0 to 4 0'))
1570 (string '2 0 to 4 0'))
1570 <filteredset
1571 <filteredset
1571 <spanset- 0:37>,
1572 <spanset- 0:37>,
1572 <date '2 0 to 4 0'>>
1573 <date '2 0 to 4 0'>>
1573 $ hg log -G -d 'brace ) in a date'
1574 $ hg log -G -d 'brace ) in a date'
1574 hg: parse error: invalid date: 'brace ) in a date'
1575 hg: parse error: invalid date: 'brace ) in a date'
1575 [255]
1576 [255]
1576 $ testlog --prune 31 --prune 32
1577 $ testlog --prune 31 --prune 32
1577 []
1578 []
1578 (not
1579 (not
1579 (or
1580 (or
1580 (list
1581 (list
1581 (func
1582 (func
1582 (symbol 'ancestors')
1583 (symbol 'ancestors')
1583 (string '31'))
1584 (string '31'))
1584 (func
1585 (func
1585 (symbol 'ancestors')
1586 (symbol 'ancestors')
1586 (string '32')))))
1587 (string '32')))))
1587 <filteredset
1588 <filteredset
1588 <spanset- 0:37>,
1589 <spanset- 0:37>,
1589 <not
1590 <not
1590 <addset
1591 <addset
1591 <filteredset
1592 <filteredset
1592 <spanset- 0:37>,
1593 <spanset- 0:37>,
1593 <generatorsetdesc+>>,
1594 <generatorsetdesc+>>,
1594 <filteredset
1595 <filteredset
1595 <spanset- 0:37>,
1596 <spanset- 0:37>,
1596 <generatorsetdesc+>>>>>
1597 <generatorsetdesc+>>>>>
1597
1598
1598 Dedicated repo for --follow and paths filtering. The g is crafted to
1599 Dedicated repo for --follow and paths filtering. The g is crafted to
1599 have 2 filelog topological heads in a linear changeset graph.
1600 have 2 filelog topological heads in a linear changeset graph.
1600
1601
1601 $ cd ..
1602 $ cd ..
1602 $ hg init follow
1603 $ hg init follow
1603 $ cd follow
1604 $ cd follow
1604 $ testlog --follow
1605 $ testlog --follow
1605 []
1606 []
1606 []
1607 []
1607 <baseset []>
1608 <baseset []>
1608 $ testlog -rnull
1609 $ testlog -rnull
1609 ['null']
1610 ['null']
1610 []
1611 []
1611 <baseset [-1]>
1612 <baseset [-1]>
1612 $ echo a > a
1613 $ echo a > a
1613 $ echo aa > aa
1614 $ echo aa > aa
1614 $ echo f > f
1615 $ echo f > f
1615 $ hg ci -Am "add a" a aa f
1616 $ hg ci -Am "add a" a aa f
1616 $ hg cp a b
1617 $ hg cp a b
1617 $ hg cp f g
1618 $ hg cp f g
1618 $ hg ci -m "copy a b"
1619 $ hg ci -m "copy a b"
1619 $ mkdir dir
1620 $ mkdir dir
1620 $ hg mv b dir
1621 $ hg mv b dir
1621 $ echo g >> g
1622 $ echo g >> g
1622 $ echo f >> f
1623 $ echo f >> f
1623 $ hg ci -m "mv b dir/b"
1624 $ hg ci -m "mv b dir/b"
1624 $ hg mv a b
1625 $ hg mv a b
1625 $ hg cp -f f g
1626 $ hg cp -f f g
1626 $ echo a > d
1627 $ echo a > d
1627 $ hg add d
1628 $ hg add d
1628 $ hg ci -m "mv a b; add d"
1629 $ hg ci -m "mv a b; add d"
1629 $ hg mv dir/b e
1630 $ hg mv dir/b e
1630 $ hg ci -m "mv dir/b e"
1631 $ hg ci -m "mv dir/b e"
1631 $ hg log -G --template '({rev}) {desc|firstline}\n'
1632 $ hg log -G --template '({rev}) {desc|firstline}\n'
1632 @ (4) mv dir/b e
1633 @ (4) mv dir/b e
1633 |
1634 |
1634 o (3) mv a b; add d
1635 o (3) mv a b; add d
1635 |
1636 |
1636 o (2) mv b dir/b
1637 o (2) mv b dir/b
1637 |
1638 |
1638 o (1) copy a b
1639 o (1) copy a b
1639 |
1640 |
1640 o (0) add a
1641 o (0) add a
1641
1642
1642
1643
1643 $ testlog a
1644 $ testlog a
1644 []
1645 []
1645 (func
1646 (func
1646 (symbol 'filelog')
1647 (symbol 'filelog')
1647 (string 'a'))
1648 (string 'a'))
1648 <filteredset
1649 <filteredset
1649 <spanset- 0:5>, set([0])>
1650 <spanset- 0:5>, set([0])>
1650 $ testlog a b
1651 $ testlog a b
1651 []
1652 []
1652 (or
1653 (or
1653 (list
1654 (list
1654 (func
1655 (func
1655 (symbol 'filelog')
1656 (symbol 'filelog')
1656 (string 'a'))
1657 (string 'a'))
1657 (func
1658 (func
1658 (symbol 'filelog')
1659 (symbol 'filelog')
1659 (string 'b'))))
1660 (string 'b'))))
1660 <filteredset
1661 <filteredset
1661 <spanset- 0:5>,
1662 <spanset- 0:5>,
1662 <addset
1663 <addset
1663 <baseset+ [0]>,
1664 <baseset+ [0]>,
1664 <baseset+ [1]>>>
1665 <baseset+ [1]>>>
1665
1666
1666 Test falling back to slow path for non-existing files
1667 Test falling back to slow path for non-existing files
1667
1668
1668 $ testlog a c
1669 $ testlog a c
1669 []
1670 []
1670 (func
1671 (func
1671 (symbol '_matchfiles')
1672 (symbol '_matchfiles')
1672 (list
1673 (list
1673 (string 'r:')
1674 (string 'r:')
1674 (string 'd:relpath')
1675 (string 'd:relpath')
1675 (string 'p:a')
1676 (string 'p:a')
1676 (string 'p:c')))
1677 (string 'p:c')))
1677 <filteredset
1678 <filteredset
1678 <spanset- 0:5>,
1679 <spanset- 0:5>,
1679 <matchfiles patterns=['a', 'c'], include=[] exclude=[], default='relpath', rev=2147483647>>
1680 <matchfiles patterns=['a', 'c'], include=[] exclude=[], default='relpath', rev=2147483647>>
1680
1681
1681 Test multiple --include/--exclude/paths
1682 Test multiple --include/--exclude/paths
1682
1683
1683 $ testlog --include a --include e --exclude b --exclude e a e
1684 $ testlog --include a --include e --exclude b --exclude e a e
1684 []
1685 []
1685 (func
1686 (func
1686 (symbol '_matchfiles')
1687 (symbol '_matchfiles')
1687 (list
1688 (list
1688 (string 'r:')
1689 (string 'r:')
1689 (string 'd:relpath')
1690 (string 'd:relpath')
1690 (string 'p:a')
1691 (string 'p:a')
1691 (string 'p:e')
1692 (string 'p:e')
1692 (string 'i:a')
1693 (string 'i:a')
1693 (string 'i:e')
1694 (string 'i:e')
1694 (string 'x:b')
1695 (string 'x:b')
1695 (string 'x:e')))
1696 (string 'x:e')))
1696 <filteredset
1697 <filteredset
1697 <spanset- 0:5>,
1698 <spanset- 0:5>,
1698 <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=2147483647>>
1699 <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=2147483647>>
1699
1700
1700 Test glob expansion of pats
1701 Test glob expansion of pats
1701
1702
1702 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1703 $ expandglobs=`$PYTHON -c "import mercurial.util; \
1703 > print(mercurial.util.expandglobs and 'true' or 'false')"`
1704 > print(mercurial.util.expandglobs and 'true' or 'false')"`
1704 $ if [ $expandglobs = "true" ]; then
1705 $ if [ $expandglobs = "true" ]; then
1705 > testlog 'a*';
1706 > testlog 'a*';
1706 > else
1707 > else
1707 > testlog a*;
1708 > testlog a*;
1708 > fi;
1709 > fi;
1709 []
1710 []
1710 (func
1711 (func
1711 (symbol 'filelog')
1712 (symbol 'filelog')
1712 (string 'aa'))
1713 (string 'aa'))
1713 <filteredset
1714 <filteredset
1714 <spanset- 0:5>, set([0])>
1715 <spanset- 0:5>, set([0])>
1715
1716
1716 Test --follow on a non-existent directory
1717 Test --follow on a non-existent directory
1717
1718
1718 $ testlog -f dir
1719 $ testlog -f dir
1719 abort: cannot follow file not in parent revision: "dir"
1720 abort: cannot follow file not in parent revision: "dir"
1720 abort: cannot follow file not in parent revision: "dir"
1721 abort: cannot follow file not in parent revision: "dir"
1721 abort: cannot follow file not in parent revision: "dir"
1722 abort: cannot follow file not in parent revision: "dir"
1722
1723
1723 Test --follow on a directory
1724 Test --follow on a directory
1724
1725
1725 $ hg up -q '.^'
1726 $ hg up -q '.^'
1726 $ testlog -f dir
1727 $ testlog -f dir
1727 []
1728 []
1728 (func
1729 (func
1729 (symbol '_matchfiles')
1730 (symbol '_matchfiles')
1730 (list
1731 (list
1731 (string 'r:')
1732 (string 'r:')
1732 (string 'd:relpath')
1733 (string 'd:relpath')
1733 (string 'p:dir')))
1734 (string 'p:dir')))
1734 <filteredset
1735 <filteredset
1735 <generatorsetdesc->,
1736 <generatorsetdesc->,
1736 <matchfiles patterns=['dir'], include=[] exclude=[], default='relpath', rev=2147483647>>
1737 <matchfiles patterns=['dir'], include=[] exclude=[], default='relpath', rev=2147483647>>
1737 $ hg up -q tip
1738 $ hg up -q tip
1738
1739
1739 Test --follow on file not in parent revision
1740 Test --follow on file not in parent revision
1740
1741
1741 $ testlog -f a
1742 $ testlog -f a
1742 abort: cannot follow file not in parent revision: "a"
1743 abort: cannot follow file not in parent revision: "a"
1743 abort: cannot follow file not in parent revision: "a"
1744 abort: cannot follow file not in parent revision: "a"
1744 abort: cannot follow file not in parent revision: "a"
1745 abort: cannot follow file not in parent revision: "a"
1745
1746
1746 Test --follow and patterns
1747 Test --follow and patterns
1747
1748
1748 $ testlog -f 'glob:*'
1749 $ testlog -f 'glob:*'
1749 []
1750 []
1750 (func
1751 (func
1751 (symbol '_matchfiles')
1752 (symbol '_matchfiles')
1752 (list
1753 (list
1753 (string 'r:')
1754 (string 'r:')
1754 (string 'd:relpath')
1755 (string 'd:relpath')
1755 (string 'p:glob:*')))
1756 (string 'p:glob:*')))
1756 <filteredset
1757 <filteredset
1757 <generatorsetdesc->,
1758 <generatorsetdesc->,
1758 <matchfiles patterns=['glob:*'], include=[] exclude=[], default='relpath', rev=2147483647>>
1759 <matchfiles patterns=['glob:*'], include=[] exclude=[], default='relpath', rev=2147483647>>
1759
1760
1760 Test --follow on a single rename
1761 Test --follow on a single rename
1761
1762
1762 $ hg up -q 2
1763 $ hg up -q 2
1763 $ testlog -f a
1764 $ testlog -f a
1764 []
1765 []
1765 []
1766 []
1766 <generatorsetdesc->
1767 <generatorsetdesc->
1767
1768
1768 Test --follow and multiple renames
1769 Test --follow and multiple renames
1769
1770
1770 $ hg up -q tip
1771 $ hg up -q tip
1771 $ testlog -f e
1772 $ testlog -f e
1772 []
1773 []
1773 []
1774 []
1774 <generatorsetdesc->
1775 <generatorsetdesc->
1775
1776
1776 Test --follow and multiple filelog heads
1777 Test --follow and multiple filelog heads
1777
1778
1778 $ hg up -q 2
1779 $ hg up -q 2
1779 $ testlog -f g
1780 $ testlog -f g
1780 []
1781 []
1781 []
1782 []
1782 <generatorsetdesc->
1783 <generatorsetdesc->
1783 $ cat log.nodes
1784 $ cat log.nodes
1784 nodetag 2
1785 nodetag 2
1785 nodetag 1
1786 nodetag 1
1786 nodetag 0
1787 nodetag 0
1787 $ hg up -q tip
1788 $ hg up -q tip
1788 $ testlog -f g
1789 $ testlog -f g
1789 []
1790 []
1790 []
1791 []
1791 <generatorsetdesc->
1792 <generatorsetdesc->
1792 $ cat log.nodes
1793 $ cat log.nodes
1793 nodetag 3
1794 nodetag 3
1794 nodetag 2
1795 nodetag 2
1795 nodetag 0
1796 nodetag 0
1796
1797
1797 Test --follow and multiple files
1798 Test --follow and multiple files
1798
1799
1799 $ testlog -f g e
1800 $ testlog -f g e
1800 []
1801 []
1801 []
1802 []
1802 <generatorsetdesc->
1803 <generatorsetdesc->
1803 $ cat log.nodes
1804 $ cat log.nodes
1804 nodetag 4
1805 nodetag 4
1805 nodetag 3
1806 nodetag 3
1806 nodetag 2
1807 nodetag 2
1807 nodetag 1
1808 nodetag 1
1808 nodetag 0
1809 nodetag 0
1809
1810
1810 Test --follow null parent
1811 Test --follow null parent
1811
1812
1812 $ hg up -q null
1813 $ hg up -q null
1813 $ testlog -f
1814 $ testlog -f
1814 []
1815 []
1815 []
1816 []
1816 <baseset []>
1817 <baseset []>
1817
1818
1818 Test --follow-first
1819 Test --follow-first
1819
1820
1820 $ hg up -q 3
1821 $ hg up -q 3
1821 $ echo ee > e
1822 $ echo ee > e
1822 $ hg ci -Am "add another e" e
1823 $ hg ci -Am "add another e" e
1823 created new head
1824 created new head
1824 $ hg merge --tool internal:other 4
1825 $ hg merge --tool internal:other 4
1825 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1826 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
1826 (branch merge, don't forget to commit)
1827 (branch merge, don't forget to commit)
1827 $ echo merge > e
1828 $ echo merge > e
1828 $ hg ci -m "merge 5 and 4"
1829 $ hg ci -m "merge 5 and 4"
1829 $ testlog --follow-first
1830 $ testlog --follow-first
1830 []
1831 []
1831 []
1832 []
1832 <generatorsetdesc->
1833 <generatorsetdesc->
1833
1834
1834 Cannot compare with log --follow-first FILE as it never worked
1835 Cannot compare with log --follow-first FILE as it never worked
1835
1836
1836 $ hg log -G --print-revset --follow-first e
1837 $ hg log -G --print-revset --follow-first e
1837 []
1838 []
1838 []
1839 []
1839 <generatorsetdesc->
1840 <generatorsetdesc->
1840 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1841 $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
1841 @ 6 merge 5 and 4
1842 @ 6 merge 5 and 4
1842 |\
1843 |\
1843 | ~
1844 | ~
1844 o 5 add another e
1845 o 5 add another e
1845 |
1846 |
1846 ~
1847 ~
1847
1848
1848 Test --copies
1849 Test --copies
1849
1850
1850 $ hg log -G --copies --template "{rev} {desc|firstline} \
1851 $ hg log -G --copies --template "{rev} {desc|firstline} \
1851 > copies: {file_copies_switch}\n"
1852 > copies: {file_copies_switch}\n"
1852 @ 6 merge 5 and 4 copies:
1853 @ 6 merge 5 and 4 copies:
1853 |\
1854 |\
1854 | o 5 add another e copies:
1855 | o 5 add another e copies:
1855 | |
1856 | |
1856 o | 4 mv dir/b e copies: e (dir/b)
1857 o | 4 mv dir/b e copies: e (dir/b)
1857 |/
1858 |/
1858 o 3 mv a b; add d copies: b (a)g (f)
1859 o 3 mv a b; add d copies: b (a)g (f)
1859 |
1860 |
1860 o 2 mv b dir/b copies: dir/b (b)
1861 o 2 mv b dir/b copies: dir/b (b)
1861 |
1862 |
1862 o 1 copy a b copies: b (a)g (f)
1863 o 1 copy a b copies: b (a)g (f)
1863 |
1864 |
1864 o 0 add a copies:
1865 o 0 add a copies:
1865
1866
1866 Test "set:..." and parent revision
1867 Test "set:..." and parent revision
1867
1868
1868 $ hg up -q 4
1869 $ hg up -q 4
1869 $ testlog "set:copied()"
1870 $ testlog "set:copied()"
1870 []
1871 []
1871 (func
1872 (func
1872 (symbol '_matchfiles')
1873 (symbol '_matchfiles')
1873 (list
1874 (list
1874 (string 'r:')
1875 (string 'r:')
1875 (string 'd:relpath')
1876 (string 'd:relpath')
1876 (string 'p:set:copied()')))
1877 (string 'p:set:copied()')))
1877 <filteredset
1878 <filteredset
1878 <spanset- 0:7>,
1879 <spanset- 0:7>,
1879 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=2147483647>>
1880 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=2147483647>>
1880 $ testlog --include "set:copied()"
1881 $ testlog --include "set:copied()"
1881 []
1882 []
1882 (func
1883 (func
1883 (symbol '_matchfiles')
1884 (symbol '_matchfiles')
1884 (list
1885 (list
1885 (string 'r:')
1886 (string 'r:')
1886 (string 'd:relpath')
1887 (string 'd:relpath')
1887 (string 'i:set:copied()')))
1888 (string 'i:set:copied()')))
1888 <filteredset
1889 <filteredset
1889 <spanset- 0:7>,
1890 <spanset- 0:7>,
1890 <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=2147483647>>
1891 <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=2147483647>>
1891 $ testlog -r "sort(file('set:copied()'), -rev)"
1892 $ testlog -r "sort(file('set:copied()'), -rev)"
1892 ["sort(file('set:copied()'), -rev)"]
1893 ["sort(file('set:copied()'), -rev)"]
1893 []
1894 []
1894 <filteredset
1895 <filteredset
1895 <fullreposet- 0:7>,
1896 <fullreposet- 0:7>,
1896 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='glob', rev=None>>
1897 <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='glob', rev=None>>
1897
1898
1898 Test --removed
1899 Test --removed
1899
1900
1900 $ testlog --removed
1901 $ testlog --removed
1901 []
1902 []
1902 []
1903 []
1903 <spanset- 0:7>
1904 <spanset- 0:7>
1904 $ testlog --removed a
1905 $ testlog --removed a
1905 []
1906 []
1906 (func
1907 (func
1907 (symbol '_matchfiles')
1908 (symbol '_matchfiles')
1908 (list
1909 (list
1909 (string 'r:')
1910 (string 'r:')
1910 (string 'd:relpath')
1911 (string 'd:relpath')
1911 (string 'p:a')))
1912 (string 'p:a')))
1912 <filteredset
1913 <filteredset
1913 <spanset- 0:7>,
1914 <spanset- 0:7>,
1914 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1915 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1915 $ testlog --removed --follow a
1916 $ testlog --removed --follow a
1916 []
1917 []
1917 (func
1918 (func
1918 (symbol '_matchfiles')
1919 (symbol '_matchfiles')
1919 (list
1920 (list
1920 (string 'r:')
1921 (string 'r:')
1921 (string 'd:relpath')
1922 (string 'd:relpath')
1922 (string 'p:a')))
1923 (string 'p:a')))
1923 <filteredset
1924 <filteredset
1924 <generatorsetdesc->,
1925 <generatorsetdesc->,
1925 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1926 <matchfiles patterns=['a'], include=[] exclude=[], default='relpath', rev=2147483647>>
1926
1927
1927 Test --patch and --stat with --follow and --follow-first
1928 Test --patch and --stat with --follow and --follow-first
1928
1929
1929 $ hg up -q 3
1930 $ hg up -q 3
1930 $ hg log -G --git --patch b
1931 $ hg log -G --git --patch b
1931 o changeset: 1:216d4c92cf98
1932 o changeset: 1:216d4c92cf98
1932 | user: test
1933 | user: test
1933 ~ date: Thu Jan 01 00:00:00 1970 +0000
1934 ~ date: Thu Jan 01 00:00:00 1970 +0000
1934 summary: copy a b
1935 summary: copy a b
1935
1936
1936 diff --git a/a b/b
1937 diff --git a/a b/b
1937 copy from a
1938 copy from a
1938 copy to b
1939 copy to b
1939
1940
1940
1941
1941 $ hg log -G --git --stat b
1942 $ hg log -G --git --stat b
1942 o changeset: 1:216d4c92cf98
1943 o changeset: 1:216d4c92cf98
1943 | user: test
1944 | user: test
1944 ~ date: Thu Jan 01 00:00:00 1970 +0000
1945 ~ date: Thu Jan 01 00:00:00 1970 +0000
1945 summary: copy a b
1946 summary: copy a b
1946
1947
1947 b | 0
1948 b | 0
1948 1 files changed, 0 insertions(+), 0 deletions(-)
1949 1 files changed, 0 insertions(+), 0 deletions(-)
1949
1950
1950
1951
1951 $ hg log -G --git --patch --follow b
1952 $ hg log -G --git --patch --follow b
1952 o changeset: 1:216d4c92cf98
1953 o changeset: 1:216d4c92cf98
1953 | user: test
1954 | user: test
1954 | date: Thu Jan 01 00:00:00 1970 +0000
1955 | date: Thu Jan 01 00:00:00 1970 +0000
1955 | summary: copy a b
1956 | summary: copy a b
1956 |
1957 |
1957 | diff --git a/a b/b
1958 | diff --git a/a b/b
1958 | copy from a
1959 | copy from a
1959 | copy to b
1960 | copy to b
1960 |
1961 |
1961 o changeset: 0:f8035bb17114
1962 o changeset: 0:f8035bb17114
1962 user: test
1963 user: test
1963 date: Thu Jan 01 00:00:00 1970 +0000
1964 date: Thu Jan 01 00:00:00 1970 +0000
1964 summary: add a
1965 summary: add a
1965
1966
1966 diff --git a/a b/a
1967 diff --git a/a b/a
1967 new file mode 100644
1968 new file mode 100644
1968 --- /dev/null
1969 --- /dev/null
1969 +++ b/a
1970 +++ b/a
1970 @@ -0,0 +1,1 @@
1971 @@ -0,0 +1,1 @@
1971 +a
1972 +a
1972
1973
1973
1974
1974 $ hg log -G --git --stat --follow b
1975 $ hg log -G --git --stat --follow b
1975 o changeset: 1:216d4c92cf98
1976 o changeset: 1:216d4c92cf98
1976 | user: test
1977 | user: test
1977 | date: Thu Jan 01 00:00:00 1970 +0000
1978 | date: Thu Jan 01 00:00:00 1970 +0000
1978 | summary: copy a b
1979 | summary: copy a b
1979 |
1980 |
1980 | b | 0
1981 | b | 0
1981 | 1 files changed, 0 insertions(+), 0 deletions(-)
1982 | 1 files changed, 0 insertions(+), 0 deletions(-)
1982 |
1983 |
1983 o changeset: 0:f8035bb17114
1984 o changeset: 0:f8035bb17114
1984 user: test
1985 user: test
1985 date: Thu Jan 01 00:00:00 1970 +0000
1986 date: Thu Jan 01 00:00:00 1970 +0000
1986 summary: add a
1987 summary: add a
1987
1988
1988 a | 1 +
1989 a | 1 +
1989 1 files changed, 1 insertions(+), 0 deletions(-)
1990 1 files changed, 1 insertions(+), 0 deletions(-)
1990
1991
1991
1992
1992 $ hg up -q 6
1993 $ hg up -q 6
1993 $ hg log -G --git --patch --follow-first e
1994 $ hg log -G --git --patch --follow-first e
1994 @ changeset: 6:fc281d8ff18d
1995 @ changeset: 6:fc281d8ff18d
1995 |\ tag: tip
1996 |\ tag: tip
1996 | ~ parent: 5:99b31f1c2782
1997 | ~ parent: 5:99b31f1c2782
1997 | parent: 4:17d952250a9d
1998 | parent: 4:17d952250a9d
1998 | user: test
1999 | user: test
1999 | date: Thu Jan 01 00:00:00 1970 +0000
2000 | date: Thu Jan 01 00:00:00 1970 +0000
2000 | summary: merge 5 and 4
2001 | summary: merge 5 and 4
2001 |
2002 |
2002 | diff --git a/e b/e
2003 | diff --git a/e b/e
2003 | --- a/e
2004 | --- a/e
2004 | +++ b/e
2005 | +++ b/e
2005 | @@ -1,1 +1,1 @@
2006 | @@ -1,1 +1,1 @@
2006 | -ee
2007 | -ee
2007 | +merge
2008 | +merge
2008 |
2009 |
2009 o changeset: 5:99b31f1c2782
2010 o changeset: 5:99b31f1c2782
2010 | parent: 3:5918b8d165d1
2011 | parent: 3:5918b8d165d1
2011 ~ user: test
2012 ~ user: test
2012 date: Thu Jan 01 00:00:00 1970 +0000
2013 date: Thu Jan 01 00:00:00 1970 +0000
2013 summary: add another e
2014 summary: add another e
2014
2015
2015 diff --git a/e b/e
2016 diff --git a/e b/e
2016 new file mode 100644
2017 new file mode 100644
2017 --- /dev/null
2018 --- /dev/null
2018 +++ b/e
2019 +++ b/e
2019 @@ -0,0 +1,1 @@
2020 @@ -0,0 +1,1 @@
2020 +ee
2021 +ee
2021
2022
2022
2023
2023 Test old-style --rev
2024 Test old-style --rev
2024
2025
2025 $ hg tag 'foo-bar'
2026 $ hg tag 'foo-bar'
2026 $ testlog -r 'foo-bar'
2027 $ testlog -r 'foo-bar'
2027 ['foo-bar']
2028 ['foo-bar']
2028 []
2029 []
2029 <baseset [6]>
2030 <baseset [6]>
2030
2031
2031 Test --follow and forward --rev
2032 Test --follow and forward --rev
2032
2033
2033 $ hg up -q 6
2034 $ hg up -q 6
2034 $ echo g > g
2035 $ echo g > g
2035 $ hg ci -Am 'add g' g
2036 $ hg ci -Am 'add g' g
2036 created new head
2037 created new head
2037 $ hg up -q 2
2038 $ hg up -q 2
2038 $ hg log -G --template "{rev} {desc|firstline}\n"
2039 $ hg log -G --template "{rev} {desc|firstline}\n"
2039 o 8 add g
2040 o 8 add g
2040 |
2041 |
2041 | o 7 Added tag foo-bar for changeset fc281d8ff18d
2042 | o 7 Added tag foo-bar for changeset fc281d8ff18d
2042 |/
2043 |/
2043 o 6 merge 5 and 4
2044 o 6 merge 5 and 4
2044 |\
2045 |\
2045 | o 5 add another e
2046 | o 5 add another e
2046 | |
2047 | |
2047 o | 4 mv dir/b e
2048 o | 4 mv dir/b e
2048 |/
2049 |/
2049 o 3 mv a b; add d
2050 o 3 mv a b; add d
2050 |
2051 |
2051 @ 2 mv b dir/b
2052 @ 2 mv b dir/b
2052 |
2053 |
2053 o 1 copy a b
2054 o 1 copy a b
2054 |
2055 |
2055 o 0 add a
2056 o 0 add a
2056
2057
2057 $ hg archive -r 7 archive
2058 $ hg archive -r 7 archive
2058 $ grep changessincelatesttag archive/.hg_archival.txt
2059 $ grep changessincelatesttag archive/.hg_archival.txt
2059 changessincelatesttag: 1
2060 changessincelatesttag: 1
2060 $ rm -r archive
2061 $ rm -r archive
2061
2062
2062 changessincelatesttag with no prior tag
2063 changessincelatesttag with no prior tag
2063 $ hg archive -r 4 archive
2064 $ hg archive -r 4 archive
2064 $ grep changessincelatesttag archive/.hg_archival.txt
2065 $ grep changessincelatesttag archive/.hg_archival.txt
2065 changessincelatesttag: 5
2066 changessincelatesttag: 5
2066
2067
2067 $ hg export 'all()'
2068 $ hg export 'all()'
2068 # HG changeset patch
2069 # HG changeset patch
2069 # User test
2070 # User test
2070 # Date 0 0
2071 # Date 0 0
2071 # Thu Jan 01 00:00:00 1970 +0000
2072 # Thu Jan 01 00:00:00 1970 +0000
2072 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2073 # Node ID f8035bb17114da16215af3436ec5222428ace8ee
2073 # Parent 0000000000000000000000000000000000000000
2074 # Parent 0000000000000000000000000000000000000000
2074 add a
2075 add a
2075
2076
2076 diff -r 000000000000 -r f8035bb17114 a
2077 diff -r 000000000000 -r f8035bb17114 a
2077 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2078 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2078 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2079 +++ b/a Thu Jan 01 00:00:00 1970 +0000
2079 @@ -0,0 +1,1 @@
2080 @@ -0,0 +1,1 @@
2080 +a
2081 +a
2081 diff -r 000000000000 -r f8035bb17114 aa
2082 diff -r 000000000000 -r f8035bb17114 aa
2082 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2083 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2083 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2084 +++ b/aa Thu Jan 01 00:00:00 1970 +0000
2084 @@ -0,0 +1,1 @@
2085 @@ -0,0 +1,1 @@
2085 +aa
2086 +aa
2086 diff -r 000000000000 -r f8035bb17114 f
2087 diff -r 000000000000 -r f8035bb17114 f
2087 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2088 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2088 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2089 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2089 @@ -0,0 +1,1 @@
2090 @@ -0,0 +1,1 @@
2090 +f
2091 +f
2091 # HG changeset patch
2092 # HG changeset patch
2092 # User test
2093 # User test
2093 # Date 0 0
2094 # Date 0 0
2094 # Thu Jan 01 00:00:00 1970 +0000
2095 # Thu Jan 01 00:00:00 1970 +0000
2095 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2096 # Node ID 216d4c92cf98ff2b4641d508b76b529f3d424c92
2096 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2097 # Parent f8035bb17114da16215af3436ec5222428ace8ee
2097 copy a b
2098 copy a b
2098
2099
2099 diff -r f8035bb17114 -r 216d4c92cf98 b
2100 diff -r f8035bb17114 -r 216d4c92cf98 b
2100 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2101 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2102 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2102 @@ -0,0 +1,1 @@
2103 @@ -0,0 +1,1 @@
2103 +a
2104 +a
2104 diff -r f8035bb17114 -r 216d4c92cf98 g
2105 diff -r f8035bb17114 -r 216d4c92cf98 g
2105 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2106 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2106 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2107 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2107 @@ -0,0 +1,1 @@
2108 @@ -0,0 +1,1 @@
2108 +f
2109 +f
2109 # HG changeset patch
2110 # HG changeset patch
2110 # User test
2111 # User test
2111 # Date 0 0
2112 # Date 0 0
2112 # Thu Jan 01 00:00:00 1970 +0000
2113 # Thu Jan 01 00:00:00 1970 +0000
2113 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2114 # Node ID bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2114 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2115 # Parent 216d4c92cf98ff2b4641d508b76b529f3d424c92
2115 mv b dir/b
2116 mv b dir/b
2116
2117
2117 diff -r 216d4c92cf98 -r bb573313a9e8 b
2118 diff -r 216d4c92cf98 -r bb573313a9e8 b
2118 --- a/b Thu Jan 01 00:00:00 1970 +0000
2119 --- a/b Thu Jan 01 00:00:00 1970 +0000
2119 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2120 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2120 @@ -1,1 +0,0 @@
2121 @@ -1,1 +0,0 @@
2121 -a
2122 -a
2122 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2123 diff -r 216d4c92cf98 -r bb573313a9e8 dir/b
2123 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2124 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2124 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2125 +++ b/dir/b Thu Jan 01 00:00:00 1970 +0000
2125 @@ -0,0 +1,1 @@
2126 @@ -0,0 +1,1 @@
2126 +a
2127 +a
2127 diff -r 216d4c92cf98 -r bb573313a9e8 f
2128 diff -r 216d4c92cf98 -r bb573313a9e8 f
2128 --- a/f Thu Jan 01 00:00:00 1970 +0000
2129 --- a/f Thu Jan 01 00:00:00 1970 +0000
2129 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2130 +++ b/f Thu Jan 01 00:00:00 1970 +0000
2130 @@ -1,1 +1,2 @@
2131 @@ -1,1 +1,2 @@
2131 f
2132 f
2132 +f
2133 +f
2133 diff -r 216d4c92cf98 -r bb573313a9e8 g
2134 diff -r 216d4c92cf98 -r bb573313a9e8 g
2134 --- a/g Thu Jan 01 00:00:00 1970 +0000
2135 --- a/g Thu Jan 01 00:00:00 1970 +0000
2135 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2136 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2136 @@ -1,1 +1,2 @@
2137 @@ -1,1 +1,2 @@
2137 f
2138 f
2138 +g
2139 +g
2139 # HG changeset patch
2140 # HG changeset patch
2140 # User test
2141 # User test
2141 # Date 0 0
2142 # Date 0 0
2142 # Thu Jan 01 00:00:00 1970 +0000
2143 # Thu Jan 01 00:00:00 1970 +0000
2143 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2144 # Node ID 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2144 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2145 # Parent bb573313a9e8349099b6ea2b2fb1fc7f424446f3
2145 mv a b; add d
2146 mv a b; add d
2146
2147
2147 diff -r bb573313a9e8 -r 5918b8d165d1 a
2148 diff -r bb573313a9e8 -r 5918b8d165d1 a
2148 --- a/a Thu Jan 01 00:00:00 1970 +0000
2149 --- a/a Thu Jan 01 00:00:00 1970 +0000
2149 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2150 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2150 @@ -1,1 +0,0 @@
2151 @@ -1,1 +0,0 @@
2151 -a
2152 -a
2152 diff -r bb573313a9e8 -r 5918b8d165d1 b
2153 diff -r bb573313a9e8 -r 5918b8d165d1 b
2153 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2154 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2154 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2155 +++ b/b Thu Jan 01 00:00:00 1970 +0000
2155 @@ -0,0 +1,1 @@
2156 @@ -0,0 +1,1 @@
2156 +a
2157 +a
2157 diff -r bb573313a9e8 -r 5918b8d165d1 d
2158 diff -r bb573313a9e8 -r 5918b8d165d1 d
2158 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2159 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2159 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2160 +++ b/d Thu Jan 01 00:00:00 1970 +0000
2160 @@ -0,0 +1,1 @@
2161 @@ -0,0 +1,1 @@
2161 +a
2162 +a
2162 diff -r bb573313a9e8 -r 5918b8d165d1 g
2163 diff -r bb573313a9e8 -r 5918b8d165d1 g
2163 --- a/g Thu Jan 01 00:00:00 1970 +0000
2164 --- a/g Thu Jan 01 00:00:00 1970 +0000
2164 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2165 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2165 @@ -1,2 +1,2 @@
2166 @@ -1,2 +1,2 @@
2166 f
2167 f
2167 -g
2168 -g
2168 +f
2169 +f
2169 # HG changeset patch
2170 # HG changeset patch
2170 # User test
2171 # User test
2171 # Date 0 0
2172 # Date 0 0
2172 # Thu Jan 01 00:00:00 1970 +0000
2173 # Thu Jan 01 00:00:00 1970 +0000
2173 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2174 # Node ID 17d952250a9d03cc3dc77b199ab60e959b9b0260
2174 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2175 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2175 mv dir/b e
2176 mv dir/b e
2176
2177
2177 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2178 diff -r 5918b8d165d1 -r 17d952250a9d dir/b
2178 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2179 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2179 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2180 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2180 @@ -1,1 +0,0 @@
2181 @@ -1,1 +0,0 @@
2181 -a
2182 -a
2182 diff -r 5918b8d165d1 -r 17d952250a9d e
2183 diff -r 5918b8d165d1 -r 17d952250a9d e
2183 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2184 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2184 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2185 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2185 @@ -0,0 +1,1 @@
2186 @@ -0,0 +1,1 @@
2186 +a
2187 +a
2187 # HG changeset patch
2188 # HG changeset patch
2188 # User test
2189 # User test
2189 # Date 0 0
2190 # Date 0 0
2190 # Thu Jan 01 00:00:00 1970 +0000
2191 # Thu Jan 01 00:00:00 1970 +0000
2191 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2192 # Node ID 99b31f1c2782e2deb1723cef08930f70fc84b37b
2192 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2193 # Parent 5918b8d165d1364e78a66d02e66caa0133c5d1ed
2193 add another e
2194 add another e
2194
2195
2195 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2196 diff -r 5918b8d165d1 -r 99b31f1c2782 e
2196 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2197 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2197 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2198 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2198 @@ -0,0 +1,1 @@
2199 @@ -0,0 +1,1 @@
2199 +ee
2200 +ee
2200 # HG changeset patch
2201 # HG changeset patch
2201 # User test
2202 # User test
2202 # Date 0 0
2203 # Date 0 0
2203 # Thu Jan 01 00:00:00 1970 +0000
2204 # Thu Jan 01 00:00:00 1970 +0000
2204 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2205 # Node ID fc281d8ff18d999ad6497b3d27390bcd695dcc73
2205 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2206 # Parent 99b31f1c2782e2deb1723cef08930f70fc84b37b
2206 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2207 # Parent 17d952250a9d03cc3dc77b199ab60e959b9b0260
2207 merge 5 and 4
2208 merge 5 and 4
2208
2209
2209 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2210 diff -r 99b31f1c2782 -r fc281d8ff18d dir/b
2210 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2211 --- a/dir/b Thu Jan 01 00:00:00 1970 +0000
2211 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2212 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2212 @@ -1,1 +0,0 @@
2213 @@ -1,1 +0,0 @@
2213 -a
2214 -a
2214 diff -r 99b31f1c2782 -r fc281d8ff18d e
2215 diff -r 99b31f1c2782 -r fc281d8ff18d e
2215 --- a/e Thu Jan 01 00:00:00 1970 +0000
2216 --- a/e Thu Jan 01 00:00:00 1970 +0000
2216 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2217 +++ b/e Thu Jan 01 00:00:00 1970 +0000
2217 @@ -1,1 +1,1 @@
2218 @@ -1,1 +1,1 @@
2218 -ee
2219 -ee
2219 +merge
2220 +merge
2220 # HG changeset patch
2221 # HG changeset patch
2221 # User test
2222 # User test
2222 # Date 0 0
2223 # Date 0 0
2223 # Thu Jan 01 00:00:00 1970 +0000
2224 # Thu Jan 01 00:00:00 1970 +0000
2224 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2225 # Node ID 02dbb8e276b8ab7abfd07cab50c901647e75c2dd
2225 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2226 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2226 Added tag foo-bar for changeset fc281d8ff18d
2227 Added tag foo-bar for changeset fc281d8ff18d
2227
2228
2228 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2229 diff -r fc281d8ff18d -r 02dbb8e276b8 .hgtags
2229 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2230 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2230 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2231 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2231 @@ -0,0 +1,1 @@
2232 @@ -0,0 +1,1 @@
2232 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2233 +fc281d8ff18d999ad6497b3d27390bcd695dcc73 foo-bar
2233 # HG changeset patch
2234 # HG changeset patch
2234 # User test
2235 # User test
2235 # Date 0 0
2236 # Date 0 0
2236 # Thu Jan 01 00:00:00 1970 +0000
2237 # Thu Jan 01 00:00:00 1970 +0000
2237 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2238 # Node ID 24c2e826ddebf80f9dcd60b856bdb8e6715c5449
2238 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2239 # Parent fc281d8ff18d999ad6497b3d27390bcd695dcc73
2239 add g
2240 add g
2240
2241
2241 diff -r fc281d8ff18d -r 24c2e826ddeb g
2242 diff -r fc281d8ff18d -r 24c2e826ddeb g
2242 --- a/g Thu Jan 01 00:00:00 1970 +0000
2243 --- a/g Thu Jan 01 00:00:00 1970 +0000
2243 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2244 +++ b/g Thu Jan 01 00:00:00 1970 +0000
2244 @@ -1,2 +1,1 @@
2245 @@ -1,2 +1,1 @@
2245 -f
2246 -f
2246 -f
2247 -f
2247 +g
2248 +g
2248 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2249 $ testlog --follow -r6 -r8 -r5 -r7 -r4
2249 ['6', '8', '5', '7', '4']
2250 ['6', '8', '5', '7', '4']
2250 []
2251 []
2251 <generatorsetdesc->
2252 <generatorsetdesc->
2252
2253
2253 Test --follow-first and forward --rev
2254 Test --follow-first and forward --rev
2254
2255
2255 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2256 $ testlog --follow-first -r6 -r8 -r5 -r7 -r4
2256 ['6', '8', '5', '7', '4']
2257 ['6', '8', '5', '7', '4']
2257 []
2258 []
2258 <generatorsetdesc->
2259 <generatorsetdesc->
2259
2260
2260 Test --follow and backward --rev
2261 Test --follow and backward --rev
2261
2262
2262 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2263 $ testlog --follow -r6 -r5 -r7 -r8 -r4
2263 ['6', '5', '7', '8', '4']
2264 ['6', '5', '7', '8', '4']
2264 []
2265 []
2265 <generatorsetdesc->
2266 <generatorsetdesc->
2266
2267
2267 Test --follow-first and backward --rev
2268 Test --follow-first and backward --rev
2268
2269
2269 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2270 $ testlog --follow-first -r6 -r5 -r7 -r8 -r4
2270 ['6', '5', '7', '8', '4']
2271 ['6', '5', '7', '8', '4']
2271 []
2272 []
2272 <generatorsetdesc->
2273 <generatorsetdesc->
2273
2274
2274 Test --follow with --rev of graphlog extension
2275 Test --follow with --rev of graphlog extension
2275
2276
2276 $ hg --config extensions.graphlog= glog -qfr1
2277 $ hg --config extensions.graphlog= glog -qfr1
2277 o 1:216d4c92cf98
2278 o 1:216d4c92cf98
2278 |
2279 |
2279 o 0:f8035bb17114
2280 o 0:f8035bb17114
2280
2281
2281
2282
2282 Test subdir
2283 Test subdir
2283
2284
2284 $ hg up -q 3
2285 $ hg up -q 3
2285 $ cd dir
2286 $ cd dir
2286 $ testlog .
2287 $ testlog .
2287 []
2288 []
2288 (func
2289 (func
2289 (symbol '_matchfiles')
2290 (symbol '_matchfiles')
2290 (list
2291 (list
2291 (string 'r:')
2292 (string 'r:')
2292 (string 'd:relpath')
2293 (string 'd:relpath')
2293 (string 'p:.')))
2294 (string 'p:.')))
2294 <filteredset
2295 <filteredset
2295 <spanset- 0:9>,
2296 <spanset- 0:9>,
2296 <matchfiles patterns=['.'], include=[] exclude=[], default='relpath', rev=2147483647>>
2297 <matchfiles patterns=['.'], include=[] exclude=[], default='relpath', rev=2147483647>>
2297 $ testlog ../b
2298 $ testlog ../b
2298 []
2299 []
2299 (func
2300 (func
2300 (symbol 'filelog')
2301 (symbol 'filelog')
2301 (string '../b'))
2302 (string '../b'))
2302 <filteredset
2303 <filteredset
2303 <spanset- 0:9>, set([1])>
2304 <spanset- 0:9>, set([1])>
2304 $ testlog -f ../b
2305 $ testlog -f ../b
2305 []
2306 []
2306 []
2307 []
2307 <generatorsetdesc->
2308 <generatorsetdesc->
2308 $ cd ..
2309 $ cd ..
2309
2310
2310 Test --hidden
2311 Test --hidden
2311 (enable obsolete)
2312 (enable obsolete)
2312
2313
2313 $ cat >> $HGRCPATH << EOF
2314 $ cat >> $HGRCPATH << EOF
2314 > [experimental]
2315 > [experimental]
2315 > evolution.createmarkers=True
2316 > evolution.createmarkers=True
2316 > EOF
2317 > EOF
2317
2318
2318 $ hg debugobsolete `hg id --debug -i -r 8`
2319 $ hg debugobsolete `hg id --debug -i -r 8`
2319 obsoleted 1 changesets
2320 obsoleted 1 changesets
2320 $ testlog
2321 $ testlog
2321 []
2322 []
2322 []
2323 []
2323 <spanset- 0:9>
2324 <spanset- 0:9>
2324 $ testlog --hidden
2325 $ testlog --hidden
2325 []
2326 []
2326 []
2327 []
2327 <spanset- 0:9>
2328 <spanset- 0:9>
2328 $ hg log -G --template '{rev} {desc}\n'
2329 $ hg log -G --template '{rev} {desc}\n'
2329 o 7 Added tag foo-bar for changeset fc281d8ff18d
2330 o 7 Added tag foo-bar for changeset fc281d8ff18d
2330 |
2331 |
2331 o 6 merge 5 and 4
2332 o 6 merge 5 and 4
2332 |\
2333 |\
2333 | o 5 add another e
2334 | o 5 add another e
2334 | |
2335 | |
2335 o | 4 mv dir/b e
2336 o | 4 mv dir/b e
2336 |/
2337 |/
2337 @ 3 mv a b; add d
2338 @ 3 mv a b; add d
2338 |
2339 |
2339 o 2 mv b dir/b
2340 o 2 mv b dir/b
2340 |
2341 |
2341 o 1 copy a b
2342 o 1 copy a b
2342 |
2343 |
2343 o 0 add a
2344 o 0 add a
2344
2345
2345
2346
2346 A template without trailing newline should do something sane
2347 A template without trailing newline should do something sane
2347
2348
2348 $ hg log -G -r ::2 --template '{rev} {desc}'
2349 $ hg log -G -r ::2 --template '{rev} {desc}'
2349 o 2 mv b dir/b
2350 o 2 mv b dir/b
2350 |
2351 |
2351 o 1 copy a b
2352 o 1 copy a b
2352 |
2353 |
2353 o 0 add a
2354 o 0 add a
2354
2355
2355
2356
2356 Extra newlines must be preserved
2357 Extra newlines must be preserved
2357
2358
2358 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2359 $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
2359 o
2360 o
2360 | 2 mv b dir/b
2361 | 2 mv b dir/b
2361 |
2362 |
2362 o
2363 o
2363 | 1 copy a b
2364 | 1 copy a b
2364 |
2365 |
2365 o
2366 o
2366 0 add a
2367 0 add a
2367
2368
2368
2369
2369 The almost-empty template should do something sane too ...
2370 The almost-empty template should do something sane too ...
2370
2371
2371 $ hg log -G -r ::2 --template '\n'
2372 $ hg log -G -r ::2 --template '\n'
2372 o
2373 o
2373 |
2374 |
2374 o
2375 o
2375 |
2376 |
2376 o
2377 o
2377
2378
2378
2379
2379 issue3772
2380 issue3772
2380
2381
2381 $ hg log -G -r :null
2382 $ hg log -G -r :null
2382 o changeset: 0:f8035bb17114
2383 o changeset: 0:f8035bb17114
2383 | user: test
2384 | user: test
2384 | date: Thu Jan 01 00:00:00 1970 +0000
2385 | date: Thu Jan 01 00:00:00 1970 +0000
2385 | summary: add a
2386 | summary: add a
2386 |
2387 |
2387 o changeset: -1:000000000000
2388 o changeset: -1:000000000000
2388 user:
2389 user:
2389 date: Thu Jan 01 00:00:00 1970 +0000
2390 date: Thu Jan 01 00:00:00 1970 +0000
2390
2391
2391 $ hg log -G -r null:null
2392 $ hg log -G -r null:null
2392 o changeset: -1:000000000000
2393 o changeset: -1:000000000000
2393 user:
2394 user:
2394 date: Thu Jan 01 00:00:00 1970 +0000
2395 date: Thu Jan 01 00:00:00 1970 +0000
2395
2396
2396
2397
2397 should not draw line down to null due to the magic of fullreposet
2398 should not draw line down to null due to the magic of fullreposet
2398
2399
2399 $ hg log -G -r 'all()' | tail -6
2400 $ hg log -G -r 'all()' | tail -6
2400 |
2401 |
2401 o changeset: 0:f8035bb17114
2402 o changeset: 0:f8035bb17114
2402 user: test
2403 user: test
2403 date: Thu Jan 01 00:00:00 1970 +0000
2404 date: Thu Jan 01 00:00:00 1970 +0000
2404 summary: add a
2405 summary: add a
2405
2406
2406
2407
2407 $ hg log -G -r 'branch(default)' | tail -6
2408 $ hg log -G -r 'branch(default)' | tail -6
2408 |
2409 |
2409 o changeset: 0:f8035bb17114
2410 o changeset: 0:f8035bb17114
2410 user: test
2411 user: test
2411 date: Thu Jan 01 00:00:00 1970 +0000
2412 date: Thu Jan 01 00:00:00 1970 +0000
2412 summary: add a
2413 summary: add a
2413
2414
2414
2415
2415 working-directory revision
2416 working-directory revision
2416
2417
2417 $ hg log -G -qr '. + wdir()'
2418 $ hg log -G -qr '. + wdir()'
2418 o 2147483647:ffffffffffff
2419 o 2147483647:ffffffffffff
2419 |
2420 |
2420 @ 3:5918b8d165d1
2421 @ 3:5918b8d165d1
2421 |
2422 |
2422 ~
2423 ~
2423
2424
2424 node template with changesetprinter:
2425 node template with changesetprinter:
2425
2426
2426 $ hg log -Gqr 5:7 --config ui.graphnodetemplate='"{rev}"'
2427 $ hg log -Gqr 5:7 --config ui.graphnodetemplate='"{rev}"'
2427 7 7:02dbb8e276b8
2428 7 7:02dbb8e276b8
2428 |
2429 |
2429 6 6:fc281d8ff18d
2430 6 6:fc281d8ff18d
2430 |\
2431 |\
2431 | ~
2432 | ~
2432 5 5:99b31f1c2782
2433 5 5:99b31f1c2782
2433 |
2434 |
2434 ~
2435 ~
2435
2436
2436 node template with changesettemplater (shared cache variable):
2437 node template with changesettemplater (shared cache variable):
2437
2438
2438 $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \
2439 $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \
2439 > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}'
2440 > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}'
2440 o 7 foo-bar+1
2441 o 7 foo-bar+1
2441 |
2442 |
2442 # 6 foo-bar+0
2443 # 6 foo-bar+0
2443 |\
2444 |\
2444 | ~
2445 | ~
2445 o 5 null+5
2446 o 5 null+5
2446 |
2447 |
2447 ~
2448 ~
2448
2449
2449 label() should just work in node template:
2450 label() should just work in node template:
2450
2451
2451 $ hg log -Gqr 7 --config extensions.color= --color=debug \
2452 $ hg log -Gqr 7 --config extensions.color= --color=debug \
2452 > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}'
2453 > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}'
2453 [branch.default|7] [log.node|7:02dbb8e276b8]
2454 [branch.default|7] [log.node|7:02dbb8e276b8]
2454 |
2455 |
2455 ~
2456 ~
2456
2457
2457 $ cd ..
2458 $ cd ..
2458
2459
2459 change graph edge styling
2460 change graph edge styling
2460
2461
2461 $ cd repo
2462 $ cd repo
2462 $ cat << EOF >> $HGRCPATH
2463 $ cat << EOF >> $HGRCPATH
2463 > [experimental]
2464 > [experimental]
2464 > graphstyle.parent = |
2465 > graphstyle.parent = |
2465 > graphstyle.grandparent = :
2466 > graphstyle.grandparent = :
2466 > graphstyle.missing =
2467 > graphstyle.missing =
2467 > EOF
2468 > EOF
2468 $ hg log -G -r 'file("a")' -m
2469 $ hg log -G -r 'file("a")' -m
2469 @ changeset: 36:08a19a744424
2470 @ changeset: 36:08a19a744424
2470 : branch: branch
2471 : branch: branch
2471 : tag: tip
2472 : tag: tip
2472 : parent: 35:9159c3644c5e
2473 : parent: 35:9159c3644c5e
2473 : parent: 35:9159c3644c5e
2474 : parent: 35:9159c3644c5e
2474 : user: test
2475 : user: test
2475 : date: Thu Jan 01 00:00:36 1970 +0000
2476 : date: Thu Jan 01 00:00:36 1970 +0000
2476 : summary: (36) buggy merge: identical parents
2477 : summary: (36) buggy merge: identical parents
2477 :
2478 :
2478 o changeset: 32:d06dffa21a31
2479 o changeset: 32:d06dffa21a31
2479 |\ parent: 27:886ed638191b
2480 |\ parent: 27:886ed638191b
2480 | : parent: 31:621d83e11f67
2481 | : parent: 31:621d83e11f67
2481 | : user: test
2482 | : user: test
2482 | : date: Thu Jan 01 00:00:32 1970 +0000
2483 | : date: Thu Jan 01 00:00:32 1970 +0000
2483 | : summary: (32) expand
2484 | : summary: (32) expand
2484 | :
2485 | :
2485 o : changeset: 31:621d83e11f67
2486 o : changeset: 31:621d83e11f67
2486 |\: parent: 21:d42a756af44d
2487 |\: parent: 21:d42a756af44d
2487 | : parent: 30:6e11cd4b648f
2488 | : parent: 30:6e11cd4b648f
2488 | : user: test
2489 | : user: test
2489 | : date: Thu Jan 01 00:00:31 1970 +0000
2490 | : date: Thu Jan 01 00:00:31 1970 +0000
2490 | : summary: (31) expand
2491 | : summary: (31) expand
2491 | :
2492 | :
2492 o : changeset: 30:6e11cd4b648f
2493 o : changeset: 30:6e11cd4b648f
2493 |\ \ parent: 28:44ecd0b9ae99
2494 |\ \ parent: 28:44ecd0b9ae99
2494 | ~ : parent: 29:cd9bb2be7593
2495 | ~ : parent: 29:cd9bb2be7593
2495 | : user: test
2496 | : user: test
2496 | : date: Thu Jan 01 00:00:30 1970 +0000
2497 | : date: Thu Jan 01 00:00:30 1970 +0000
2497 | : summary: (30) expand
2498 | : summary: (30) expand
2498 | /
2499 | /
2499 o : changeset: 28:44ecd0b9ae99
2500 o : changeset: 28:44ecd0b9ae99
2500 |\ \ parent: 1:6db2ef61d156
2501 |\ \ parent: 1:6db2ef61d156
2501 | ~ : parent: 26:7f25b6c2f0b9
2502 | ~ : parent: 26:7f25b6c2f0b9
2502 | : user: test
2503 | : user: test
2503 | : date: Thu Jan 01 00:00:28 1970 +0000
2504 | : date: Thu Jan 01 00:00:28 1970 +0000
2504 | : summary: (28) merge zero known
2505 | : summary: (28) merge zero known
2505 | /
2506 | /
2506 o : changeset: 26:7f25b6c2f0b9
2507 o : changeset: 26:7f25b6c2f0b9
2507 |\ \ parent: 18:1aa84d96232a
2508 |\ \ parent: 18:1aa84d96232a
2508 | | : parent: 25:91da8ed57247
2509 | | : parent: 25:91da8ed57247
2509 | | : user: test
2510 | | : user: test
2510 | | : date: Thu Jan 01 00:00:26 1970 +0000
2511 | | : date: Thu Jan 01 00:00:26 1970 +0000
2511 | | : summary: (26) merge one known; far right
2512 | | : summary: (26) merge one known; far right
2512 | | :
2513 | | :
2513 | o : changeset: 25:91da8ed57247
2514 | o : changeset: 25:91da8ed57247
2514 | |\: parent: 21:d42a756af44d
2515 | |\: parent: 21:d42a756af44d
2515 | | : parent: 24:a9c19a3d96b7
2516 | | : parent: 24:a9c19a3d96b7
2516 | | : user: test
2517 | | : user: test
2517 | | : date: Thu Jan 01 00:00:25 1970 +0000
2518 | | : date: Thu Jan 01 00:00:25 1970 +0000
2518 | | : summary: (25) merge one known; far left
2519 | | : summary: (25) merge one known; far left
2519 | | :
2520 | | :
2520 | o : changeset: 24:a9c19a3d96b7
2521 | o : changeset: 24:a9c19a3d96b7
2521 | |\ \ parent: 0:e6eb3150255d
2522 | |\ \ parent: 0:e6eb3150255d
2522 | | ~ : parent: 23:a01cddf0766d
2523 | | ~ : parent: 23:a01cddf0766d
2523 | | : user: test
2524 | | : user: test
2524 | | : date: Thu Jan 01 00:00:24 1970 +0000
2525 | | : date: Thu Jan 01 00:00:24 1970 +0000
2525 | | : summary: (24) merge one known; immediate right
2526 | | : summary: (24) merge one known; immediate right
2526 | | /
2527 | | /
2527 | o : changeset: 23:a01cddf0766d
2528 | o : changeset: 23:a01cddf0766d
2528 | |\ \ parent: 1:6db2ef61d156
2529 | |\ \ parent: 1:6db2ef61d156
2529 | | ~ : parent: 22:e0d9cccacb5d
2530 | | ~ : parent: 22:e0d9cccacb5d
2530 | | : user: test
2531 | | : user: test
2531 | | : date: Thu Jan 01 00:00:23 1970 +0000
2532 | | : date: Thu Jan 01 00:00:23 1970 +0000
2532 | | : summary: (23) merge one known; immediate left
2533 | | : summary: (23) merge one known; immediate left
2533 | | /
2534 | | /
2534 | o : changeset: 22:e0d9cccacb5d
2535 | o : changeset: 22:e0d9cccacb5d
2535 |/:/ parent: 18:1aa84d96232a
2536 |/:/ parent: 18:1aa84d96232a
2536 | : parent: 21:d42a756af44d
2537 | : parent: 21:d42a756af44d
2537 | : user: test
2538 | : user: test
2538 | : date: Thu Jan 01 00:00:22 1970 +0000
2539 | : date: Thu Jan 01 00:00:22 1970 +0000
2539 | : summary: (22) merge two known; one far left, one far right
2540 | : summary: (22) merge two known; one far left, one far right
2540 | :
2541 | :
2541 | o changeset: 21:d42a756af44d
2542 | o changeset: 21:d42a756af44d
2542 | |\ parent: 19:31ddc2c1573b
2543 | |\ parent: 19:31ddc2c1573b
2543 | | | parent: 20:d30ed6450e32
2544 | | | parent: 20:d30ed6450e32
2544 | | | user: test
2545 | | | user: test
2545 | | | date: Thu Jan 01 00:00:21 1970 +0000
2546 | | | date: Thu Jan 01 00:00:21 1970 +0000
2546 | | | summary: (21) expand
2547 | | | summary: (21) expand
2547 | | |
2548 | | |
2548 +---o changeset: 20:d30ed6450e32
2549 +---o changeset: 20:d30ed6450e32
2549 | | | parent: 0:e6eb3150255d
2550 | | | parent: 0:e6eb3150255d
2550 | | ~ parent: 18:1aa84d96232a
2551 | | ~ parent: 18:1aa84d96232a
2551 | | user: test
2552 | | user: test
2552 | | date: Thu Jan 01 00:00:20 1970 +0000
2553 | | date: Thu Jan 01 00:00:20 1970 +0000
2553 | | summary: (20) merge two known; two far right
2554 | | summary: (20) merge two known; two far right
2554 | |
2555 | |
2555 | o changeset: 19:31ddc2c1573b
2556 | o changeset: 19:31ddc2c1573b
2556 | |\ parent: 15:1dda3f72782d
2557 | |\ parent: 15:1dda3f72782d
2557 | | | parent: 17:44765d7c06e0
2558 | | | parent: 17:44765d7c06e0
2558 | | | user: test
2559 | | | user: test
2559 | | | date: Thu Jan 01 00:00:19 1970 +0000
2560 | | | date: Thu Jan 01 00:00:19 1970 +0000
2560 | | | summary: (19) expand
2561 | | | summary: (19) expand
2561 | | |
2562 | | |
2562 o | | changeset: 18:1aa84d96232a
2563 o | | changeset: 18:1aa84d96232a
2563 |\| | parent: 1:6db2ef61d156
2564 |\| | parent: 1:6db2ef61d156
2564 ~ | | parent: 15:1dda3f72782d
2565 ~ | | parent: 15:1dda3f72782d
2565 | | user: test
2566 | | user: test
2566 | | date: Thu Jan 01 00:00:18 1970 +0000
2567 | | date: Thu Jan 01 00:00:18 1970 +0000
2567 | | summary: (18) merge two known; two far left
2568 | | summary: (18) merge two known; two far left
2568 / /
2569 / /
2569 | o changeset: 17:44765d7c06e0
2570 | o changeset: 17:44765d7c06e0
2570 | |\ parent: 12:86b91144a6e9
2571 | |\ parent: 12:86b91144a6e9
2571 | | | parent: 16:3677d192927d
2572 | | | parent: 16:3677d192927d
2572 | | | user: test
2573 | | | user: test
2573 | | | date: Thu Jan 01 00:00:17 1970 +0000
2574 | | | date: Thu Jan 01 00:00:17 1970 +0000
2574 | | | summary: (17) expand
2575 | | | summary: (17) expand
2575 | | |
2576 | | |
2576 | | o changeset: 16:3677d192927d
2577 | | o changeset: 16:3677d192927d
2577 | | |\ parent: 0:e6eb3150255d
2578 | | |\ parent: 0:e6eb3150255d
2578 | | ~ ~ parent: 1:6db2ef61d156
2579 | | ~ ~ parent: 1:6db2ef61d156
2579 | | user: test
2580 | | user: test
2580 | | date: Thu Jan 01 00:00:16 1970 +0000
2581 | | date: Thu Jan 01 00:00:16 1970 +0000
2581 | | summary: (16) merge two known; one immediate right, one near right
2582 | | summary: (16) merge two known; one immediate right, one near right
2582 | |
2583 | |
2583 o | changeset: 15:1dda3f72782d
2584 o | changeset: 15:1dda3f72782d
2584 |\ \ parent: 13:22d8966a97e3
2585 |\ \ parent: 13:22d8966a97e3
2585 | | | parent: 14:8eac370358ef
2586 | | | parent: 14:8eac370358ef
2586 | | | user: test
2587 | | | user: test
2587 | | | date: Thu Jan 01 00:00:15 1970 +0000
2588 | | | date: Thu Jan 01 00:00:15 1970 +0000
2588 | | | summary: (15) expand
2589 | | | summary: (15) expand
2589 | | |
2590 | | |
2590 | o | changeset: 14:8eac370358ef
2591 | o | changeset: 14:8eac370358ef
2591 | |\| parent: 0:e6eb3150255d
2592 | |\| parent: 0:e6eb3150255d
2592 | ~ | parent: 12:86b91144a6e9
2593 | ~ | parent: 12:86b91144a6e9
2593 | | user: test
2594 | | user: test
2594 | | date: Thu Jan 01 00:00:14 1970 +0000
2595 | | date: Thu Jan 01 00:00:14 1970 +0000
2595 | | summary: (14) merge two known; one immediate right, one far right
2596 | | summary: (14) merge two known; one immediate right, one far right
2596 | /
2597 | /
2597 o | changeset: 13:22d8966a97e3
2598 o | changeset: 13:22d8966a97e3
2598 |\ \ parent: 9:7010c0af0a35
2599 |\ \ parent: 9:7010c0af0a35
2599 | | | parent: 11:832d76e6bdf2
2600 | | | parent: 11:832d76e6bdf2
2600 | | | user: test
2601 | | | user: test
2601 | | | date: Thu Jan 01 00:00:13 1970 +0000
2602 | | | date: Thu Jan 01 00:00:13 1970 +0000
2602 | | | summary: (13) expand
2603 | | | summary: (13) expand
2603 | | |
2604 | | |
2604 +---o changeset: 12:86b91144a6e9
2605 +---o changeset: 12:86b91144a6e9
2605 | | | parent: 1:6db2ef61d156
2606 | | | parent: 1:6db2ef61d156
2606 | | ~ parent: 9:7010c0af0a35
2607 | | ~ parent: 9:7010c0af0a35
2607 | | user: test
2608 | | user: test
2608 | | date: Thu Jan 01 00:00:12 1970 +0000
2609 | | date: Thu Jan 01 00:00:12 1970 +0000
2609 | | summary: (12) merge two known; one immediate right, one far left
2610 | | summary: (12) merge two known; one immediate right, one far left
2610 | |
2611 | |
2611 | o changeset: 11:832d76e6bdf2
2612 | o changeset: 11:832d76e6bdf2
2612 | |\ parent: 6:b105a072e251
2613 | |\ parent: 6:b105a072e251
2613 | | | parent: 10:74c64d036d72
2614 | | | parent: 10:74c64d036d72
2614 | | | user: test
2615 | | | user: test
2615 | | | date: Thu Jan 01 00:00:11 1970 +0000
2616 | | | date: Thu Jan 01 00:00:11 1970 +0000
2616 | | | summary: (11) expand
2617 | | | summary: (11) expand
2617 | | |
2618 | | |
2618 | | o changeset: 10:74c64d036d72
2619 | | o changeset: 10:74c64d036d72
2619 | |/| parent: 0:e6eb3150255d
2620 | |/| parent: 0:e6eb3150255d
2620 | | ~ parent: 6:b105a072e251
2621 | | ~ parent: 6:b105a072e251
2621 | | user: test
2622 | | user: test
2622 | | date: Thu Jan 01 00:00:10 1970 +0000
2623 | | date: Thu Jan 01 00:00:10 1970 +0000
2623 | | summary: (10) merge two known; one immediate left, one near right
2624 | | summary: (10) merge two known; one immediate left, one near right
2624 | |
2625 | |
2625 o | changeset: 9:7010c0af0a35
2626 o | changeset: 9:7010c0af0a35
2626 |\ \ parent: 7:b632bb1b1224
2627 |\ \ parent: 7:b632bb1b1224
2627 | | | parent: 8:7a0b11f71937
2628 | | | parent: 8:7a0b11f71937
2628 | | | user: test
2629 | | | user: test
2629 | | | date: Thu Jan 01 00:00:09 1970 +0000
2630 | | | date: Thu Jan 01 00:00:09 1970 +0000
2630 | | | summary: (9) expand
2631 | | | summary: (9) expand
2631 | | |
2632 | | |
2632 | o | changeset: 8:7a0b11f71937
2633 | o | changeset: 8:7a0b11f71937
2633 |/| | parent: 0:e6eb3150255d
2634 |/| | parent: 0:e6eb3150255d
2634 | ~ | parent: 7:b632bb1b1224
2635 | ~ | parent: 7:b632bb1b1224
2635 | | user: test
2636 | | user: test
2636 | | date: Thu Jan 01 00:00:08 1970 +0000
2637 | | date: Thu Jan 01 00:00:08 1970 +0000
2637 | | summary: (8) merge two known; one immediate left, one far right
2638 | | summary: (8) merge two known; one immediate left, one far right
2638 | /
2639 | /
2639 o | changeset: 7:b632bb1b1224
2640 o | changeset: 7:b632bb1b1224
2640 |\ \ parent: 2:3d9a33b8d1e1
2641 |\ \ parent: 2:3d9a33b8d1e1
2641 | ~ | parent: 5:4409d547b708
2642 | ~ | parent: 5:4409d547b708
2642 | | user: test
2643 | | user: test
2643 | | date: Thu Jan 01 00:00:07 1970 +0000
2644 | | date: Thu Jan 01 00:00:07 1970 +0000
2644 | | summary: (7) expand
2645 | | summary: (7) expand
2645 | /
2646 | /
2646 | o changeset: 6:b105a072e251
2647 | o changeset: 6:b105a072e251
2647 |/| parent: 2:3d9a33b8d1e1
2648 |/| parent: 2:3d9a33b8d1e1
2648 | ~ parent: 5:4409d547b708
2649 | ~ parent: 5:4409d547b708
2649 | user: test
2650 | user: test
2650 | date: Thu Jan 01 00:00:06 1970 +0000
2651 | date: Thu Jan 01 00:00:06 1970 +0000
2651 | summary: (6) merge two known; one immediate left, one far left
2652 | summary: (6) merge two known; one immediate left, one far left
2652 |
2653 |
2653 o changeset: 5:4409d547b708
2654 o changeset: 5:4409d547b708
2654 |\ parent: 3:27eef8ed80b4
2655 |\ parent: 3:27eef8ed80b4
2655 | ~ parent: 4:26a8bac39d9f
2656 | ~ parent: 4:26a8bac39d9f
2656 | user: test
2657 | user: test
2657 | date: Thu Jan 01 00:00:05 1970 +0000
2658 | date: Thu Jan 01 00:00:05 1970 +0000
2658 | summary: (5) expand
2659 | summary: (5) expand
2659 |
2660 |
2660 o changeset: 4:26a8bac39d9f
2661 o changeset: 4:26a8bac39d9f
2661 |\ parent: 1:6db2ef61d156
2662 |\ parent: 1:6db2ef61d156
2662 ~ ~ parent: 3:27eef8ed80b4
2663 ~ ~ parent: 3:27eef8ed80b4
2663 user: test
2664 user: test
2664 date: Thu Jan 01 00:00:04 1970 +0000
2665 date: Thu Jan 01 00:00:04 1970 +0000
2665 summary: (4) merge two known; one immediate left, one immediate right
2666 summary: (4) merge two known; one immediate left, one immediate right
2666
2667
2667
2668
2668 Setting HGPLAIN ignores graphmod styling:
2669 Setting HGPLAIN ignores graphmod styling:
2669
2670
2670 $ HGPLAIN=1 hg log -G -r 'file("a")' -m
2671 $ HGPLAIN=1 hg log -G -r 'file("a")' -m
2671 @ changeset: 36:08a19a744424
2672 @ changeset: 36:08a19a744424
2672 | branch: branch
2673 | branch: branch
2673 | tag: tip
2674 | tag: tip
2674 | parent: 35:9159c3644c5e
2675 | parent: 35:9159c3644c5e
2675 | parent: 35:9159c3644c5e
2676 | parent: 35:9159c3644c5e
2676 | user: test
2677 | user: test
2677 | date: Thu Jan 01 00:00:36 1970 +0000
2678 | date: Thu Jan 01 00:00:36 1970 +0000
2678 | summary: (36) buggy merge: identical parents
2679 | summary: (36) buggy merge: identical parents
2679 |
2680 |
2680 o changeset: 32:d06dffa21a31
2681 o changeset: 32:d06dffa21a31
2681 |\ parent: 27:886ed638191b
2682 |\ parent: 27:886ed638191b
2682 | | parent: 31:621d83e11f67
2683 | | parent: 31:621d83e11f67
2683 | | user: test
2684 | | user: test
2684 | | date: Thu Jan 01 00:00:32 1970 +0000
2685 | | date: Thu Jan 01 00:00:32 1970 +0000
2685 | | summary: (32) expand
2686 | | summary: (32) expand
2686 | |
2687 | |
2687 o | changeset: 31:621d83e11f67
2688 o | changeset: 31:621d83e11f67
2688 |\| parent: 21:d42a756af44d
2689 |\| parent: 21:d42a756af44d
2689 | | parent: 30:6e11cd4b648f
2690 | | parent: 30:6e11cd4b648f
2690 | | user: test
2691 | | user: test
2691 | | date: Thu Jan 01 00:00:31 1970 +0000
2692 | | date: Thu Jan 01 00:00:31 1970 +0000
2692 | | summary: (31) expand
2693 | | summary: (31) expand
2693 | |
2694 | |
2694 o | changeset: 30:6e11cd4b648f
2695 o | changeset: 30:6e11cd4b648f
2695 |\ \ parent: 28:44ecd0b9ae99
2696 |\ \ parent: 28:44ecd0b9ae99
2696 | | | parent: 29:cd9bb2be7593
2697 | | | parent: 29:cd9bb2be7593
2697 | | | user: test
2698 | | | user: test
2698 | | | date: Thu Jan 01 00:00:30 1970 +0000
2699 | | | date: Thu Jan 01 00:00:30 1970 +0000
2699 | | | summary: (30) expand
2700 | | | summary: (30) expand
2700 | | |
2701 | | |
2701 o | | changeset: 28:44ecd0b9ae99
2702 o | | changeset: 28:44ecd0b9ae99
2702 |\ \ \ parent: 1:6db2ef61d156
2703 |\ \ \ parent: 1:6db2ef61d156
2703 | | | | parent: 26:7f25b6c2f0b9
2704 | | | | parent: 26:7f25b6c2f0b9
2704 | | | | user: test
2705 | | | | user: test
2705 | | | | date: Thu Jan 01 00:00:28 1970 +0000
2706 | | | | date: Thu Jan 01 00:00:28 1970 +0000
2706 | | | | summary: (28) merge zero known
2707 | | | | summary: (28) merge zero known
2707 | | | |
2708 | | | |
2708 o | | | changeset: 26:7f25b6c2f0b9
2709 o | | | changeset: 26:7f25b6c2f0b9
2709 |\ \ \ \ parent: 18:1aa84d96232a
2710 |\ \ \ \ parent: 18:1aa84d96232a
2710 | | | | | parent: 25:91da8ed57247
2711 | | | | | parent: 25:91da8ed57247
2711 | | | | | user: test
2712 | | | | | user: test
2712 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
2713 | | | | | date: Thu Jan 01 00:00:26 1970 +0000
2713 | | | | | summary: (26) merge one known; far right
2714 | | | | | summary: (26) merge one known; far right
2714 | | | | |
2715 | | | | |
2715 | o-----+ changeset: 25:91da8ed57247
2716 | o-----+ changeset: 25:91da8ed57247
2716 | | | | | parent: 21:d42a756af44d
2717 | | | | | parent: 21:d42a756af44d
2717 | | | | | parent: 24:a9c19a3d96b7
2718 | | | | | parent: 24:a9c19a3d96b7
2718 | | | | | user: test
2719 | | | | | user: test
2719 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
2720 | | | | | date: Thu Jan 01 00:00:25 1970 +0000
2720 | | | | | summary: (25) merge one known; far left
2721 | | | | | summary: (25) merge one known; far left
2721 | | | | |
2722 | | | | |
2722 | o | | | changeset: 24:a9c19a3d96b7
2723 | o | | | changeset: 24:a9c19a3d96b7
2723 | |\ \ \ \ parent: 0:e6eb3150255d
2724 | |\ \ \ \ parent: 0:e6eb3150255d
2724 | | | | | | parent: 23:a01cddf0766d
2725 | | | | | | parent: 23:a01cddf0766d
2725 | | | | | | user: test
2726 | | | | | | user: test
2726 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
2727 | | | | | | date: Thu Jan 01 00:00:24 1970 +0000
2727 | | | | | | summary: (24) merge one known; immediate right
2728 | | | | | | summary: (24) merge one known; immediate right
2728 | | | | | |
2729 | | | | | |
2729 | o---+ | | changeset: 23:a01cddf0766d
2730 | o---+ | | changeset: 23:a01cddf0766d
2730 | | | | | | parent: 1:6db2ef61d156
2731 | | | | | | parent: 1:6db2ef61d156
2731 | | | | | | parent: 22:e0d9cccacb5d
2732 | | | | | | parent: 22:e0d9cccacb5d
2732 | | | | | | user: test
2733 | | | | | | user: test
2733 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
2734 | | | | | | date: Thu Jan 01 00:00:23 1970 +0000
2734 | | | | | | summary: (23) merge one known; immediate left
2735 | | | | | | summary: (23) merge one known; immediate left
2735 | | | | | |
2736 | | | | | |
2736 | o-------+ changeset: 22:e0d9cccacb5d
2737 | o-------+ changeset: 22:e0d9cccacb5d
2737 | | | | | | parent: 18:1aa84d96232a
2738 | | | | | | parent: 18:1aa84d96232a
2738 |/ / / / / parent: 21:d42a756af44d
2739 |/ / / / / parent: 21:d42a756af44d
2739 | | | | | user: test
2740 | | | | | user: test
2740 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
2741 | | | | | date: Thu Jan 01 00:00:22 1970 +0000
2741 | | | | | summary: (22) merge two known; one far left, one far right
2742 | | | | | summary: (22) merge two known; one far left, one far right
2742 | | | | |
2743 | | | | |
2743 | | | | o changeset: 21:d42a756af44d
2744 | | | | o changeset: 21:d42a756af44d
2744 | | | | |\ parent: 19:31ddc2c1573b
2745 | | | | |\ parent: 19:31ddc2c1573b
2745 | | | | | | parent: 20:d30ed6450e32
2746 | | | | | | parent: 20:d30ed6450e32
2746 | | | | | | user: test
2747 | | | | | | user: test
2747 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
2748 | | | | | | date: Thu Jan 01 00:00:21 1970 +0000
2748 | | | | | | summary: (21) expand
2749 | | | | | | summary: (21) expand
2749 | | | | | |
2750 | | | | | |
2750 +-+-------o changeset: 20:d30ed6450e32
2751 +-+-------o changeset: 20:d30ed6450e32
2751 | | | | | parent: 0:e6eb3150255d
2752 | | | | | parent: 0:e6eb3150255d
2752 | | | | | parent: 18:1aa84d96232a
2753 | | | | | parent: 18:1aa84d96232a
2753 | | | | | user: test
2754 | | | | | user: test
2754 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
2755 | | | | | date: Thu Jan 01 00:00:20 1970 +0000
2755 | | | | | summary: (20) merge two known; two far right
2756 | | | | | summary: (20) merge two known; two far right
2756 | | | | |
2757 | | | | |
2757 | | | | o changeset: 19:31ddc2c1573b
2758 | | | | o changeset: 19:31ddc2c1573b
2758 | | | | |\ parent: 15:1dda3f72782d
2759 | | | | |\ parent: 15:1dda3f72782d
2759 | | | | | | parent: 17:44765d7c06e0
2760 | | | | | | parent: 17:44765d7c06e0
2760 | | | | | | user: test
2761 | | | | | | user: test
2761 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
2762 | | | | | | date: Thu Jan 01 00:00:19 1970 +0000
2762 | | | | | | summary: (19) expand
2763 | | | | | | summary: (19) expand
2763 | | | | | |
2764 | | | | | |
2764 o---+---+ | changeset: 18:1aa84d96232a
2765 o---+---+ | changeset: 18:1aa84d96232a
2765 | | | | | parent: 1:6db2ef61d156
2766 | | | | | parent: 1:6db2ef61d156
2766 / / / / / parent: 15:1dda3f72782d
2767 / / / / / parent: 15:1dda3f72782d
2767 | | | | | user: test
2768 | | | | | user: test
2768 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
2769 | | | | | date: Thu Jan 01 00:00:18 1970 +0000
2769 | | | | | summary: (18) merge two known; two far left
2770 | | | | | summary: (18) merge two known; two far left
2770 | | | | |
2771 | | | | |
2771 | | | | o changeset: 17:44765d7c06e0
2772 | | | | o changeset: 17:44765d7c06e0
2772 | | | | |\ parent: 12:86b91144a6e9
2773 | | | | |\ parent: 12:86b91144a6e9
2773 | | | | | | parent: 16:3677d192927d
2774 | | | | | | parent: 16:3677d192927d
2774 | | | | | | user: test
2775 | | | | | | user: test
2775 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
2776 | | | | | | date: Thu Jan 01 00:00:17 1970 +0000
2776 | | | | | | summary: (17) expand
2777 | | | | | | summary: (17) expand
2777 | | | | | |
2778 | | | | | |
2778 +-+-------o changeset: 16:3677d192927d
2779 +-+-------o changeset: 16:3677d192927d
2779 | | | | | parent: 0:e6eb3150255d
2780 | | | | | parent: 0:e6eb3150255d
2780 | | | | | parent: 1:6db2ef61d156
2781 | | | | | parent: 1:6db2ef61d156
2781 | | | | | user: test
2782 | | | | | user: test
2782 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
2783 | | | | | date: Thu Jan 01 00:00:16 1970 +0000
2783 | | | | | summary: (16) merge two known; one immediate right, one near right
2784 | | | | | summary: (16) merge two known; one immediate right, one near right
2784 | | | | |
2785 | | | | |
2785 | | | o | changeset: 15:1dda3f72782d
2786 | | | o | changeset: 15:1dda3f72782d
2786 | | | |\ \ parent: 13:22d8966a97e3
2787 | | | |\ \ parent: 13:22d8966a97e3
2787 | | | | | | parent: 14:8eac370358ef
2788 | | | | | | parent: 14:8eac370358ef
2788 | | | | | | user: test
2789 | | | | | | user: test
2789 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
2790 | | | | | | date: Thu Jan 01 00:00:15 1970 +0000
2790 | | | | | | summary: (15) expand
2791 | | | | | | summary: (15) expand
2791 | | | | | |
2792 | | | | | |
2792 +-------o | changeset: 14:8eac370358ef
2793 +-------o | changeset: 14:8eac370358ef
2793 | | | | |/ parent: 0:e6eb3150255d
2794 | | | | |/ parent: 0:e6eb3150255d
2794 | | | | | parent: 12:86b91144a6e9
2795 | | | | | parent: 12:86b91144a6e9
2795 | | | | | user: test
2796 | | | | | user: test
2796 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
2797 | | | | | date: Thu Jan 01 00:00:14 1970 +0000
2797 | | | | | summary: (14) merge two known; one immediate right, one far right
2798 | | | | | summary: (14) merge two known; one immediate right, one far right
2798 | | | | |
2799 | | | | |
2799 | | | o | changeset: 13:22d8966a97e3
2800 | | | o | changeset: 13:22d8966a97e3
2800 | | | |\ \ parent: 9:7010c0af0a35
2801 | | | |\ \ parent: 9:7010c0af0a35
2801 | | | | | | parent: 11:832d76e6bdf2
2802 | | | | | | parent: 11:832d76e6bdf2
2802 | | | | | | user: test
2803 | | | | | | user: test
2803 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
2804 | | | | | | date: Thu Jan 01 00:00:13 1970 +0000
2804 | | | | | | summary: (13) expand
2805 | | | | | | summary: (13) expand
2805 | | | | | |
2806 | | | | | |
2806 | +---+---o changeset: 12:86b91144a6e9
2807 | +---+---o changeset: 12:86b91144a6e9
2807 | | | | | parent: 1:6db2ef61d156
2808 | | | | | parent: 1:6db2ef61d156
2808 | | | | | parent: 9:7010c0af0a35
2809 | | | | | parent: 9:7010c0af0a35
2809 | | | | | user: test
2810 | | | | | user: test
2810 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
2811 | | | | | date: Thu Jan 01 00:00:12 1970 +0000
2811 | | | | | summary: (12) merge two known; one immediate right, one far left
2812 | | | | | summary: (12) merge two known; one immediate right, one far left
2812 | | | | |
2813 | | | | |
2813 | | | | o changeset: 11:832d76e6bdf2
2814 | | | | o changeset: 11:832d76e6bdf2
2814 | | | | |\ parent: 6:b105a072e251
2815 | | | | |\ parent: 6:b105a072e251
2815 | | | | | | parent: 10:74c64d036d72
2816 | | | | | | parent: 10:74c64d036d72
2816 | | | | | | user: test
2817 | | | | | | user: test
2817 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
2818 | | | | | | date: Thu Jan 01 00:00:11 1970 +0000
2818 | | | | | | summary: (11) expand
2819 | | | | | | summary: (11) expand
2819 | | | | | |
2820 | | | | | |
2820 +---------o changeset: 10:74c64d036d72
2821 +---------o changeset: 10:74c64d036d72
2821 | | | | |/ parent: 0:e6eb3150255d
2822 | | | | |/ parent: 0:e6eb3150255d
2822 | | | | | parent: 6:b105a072e251
2823 | | | | | parent: 6:b105a072e251
2823 | | | | | user: test
2824 | | | | | user: test
2824 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
2825 | | | | | date: Thu Jan 01 00:00:10 1970 +0000
2825 | | | | | summary: (10) merge two known; one immediate left, one near right
2826 | | | | | summary: (10) merge two known; one immediate left, one near right
2826 | | | | |
2827 | | | | |
2827 | | | o | changeset: 9:7010c0af0a35
2828 | | | o | changeset: 9:7010c0af0a35
2828 | | | |\ \ parent: 7:b632bb1b1224
2829 | | | |\ \ parent: 7:b632bb1b1224
2829 | | | | | | parent: 8:7a0b11f71937
2830 | | | | | | parent: 8:7a0b11f71937
2830 | | | | | | user: test
2831 | | | | | | user: test
2831 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
2832 | | | | | | date: Thu Jan 01 00:00:09 1970 +0000
2832 | | | | | | summary: (9) expand
2833 | | | | | | summary: (9) expand
2833 | | | | | |
2834 | | | | | |
2834 +-------o | changeset: 8:7a0b11f71937
2835 +-------o | changeset: 8:7a0b11f71937
2835 | | | |/ / parent: 0:e6eb3150255d
2836 | | | |/ / parent: 0:e6eb3150255d
2836 | | | | | parent: 7:b632bb1b1224
2837 | | | | | parent: 7:b632bb1b1224
2837 | | | | | user: test
2838 | | | | | user: test
2838 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
2839 | | | | | date: Thu Jan 01 00:00:08 1970 +0000
2839 | | | | | summary: (8) merge two known; one immediate left, one far right
2840 | | | | | summary: (8) merge two known; one immediate left, one far right
2840 | | | | |
2841 | | | | |
2841 | | | o | changeset: 7:b632bb1b1224
2842 | | | o | changeset: 7:b632bb1b1224
2842 | | | |\ \ parent: 2:3d9a33b8d1e1
2843 | | | |\ \ parent: 2:3d9a33b8d1e1
2843 | | | | | | parent: 5:4409d547b708
2844 | | | | | | parent: 5:4409d547b708
2844 | | | | | | user: test
2845 | | | | | | user: test
2845 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
2846 | | | | | | date: Thu Jan 01 00:00:07 1970 +0000
2846 | | | | | | summary: (7) expand
2847 | | | | | | summary: (7) expand
2847 | | | | | |
2848 | | | | | |
2848 | | | +---o changeset: 6:b105a072e251
2849 | | | +---o changeset: 6:b105a072e251
2849 | | | | |/ parent: 2:3d9a33b8d1e1
2850 | | | | |/ parent: 2:3d9a33b8d1e1
2850 | | | | | parent: 5:4409d547b708
2851 | | | | | parent: 5:4409d547b708
2851 | | | | | user: test
2852 | | | | | user: test
2852 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
2853 | | | | | date: Thu Jan 01 00:00:06 1970 +0000
2853 | | | | | summary: (6) merge two known; one immediate left, one far left
2854 | | | | | summary: (6) merge two known; one immediate left, one far left
2854 | | | | |
2855 | | | | |
2855 | | | o | changeset: 5:4409d547b708
2856 | | | o | changeset: 5:4409d547b708
2856 | | | |\ \ parent: 3:27eef8ed80b4
2857 | | | |\ \ parent: 3:27eef8ed80b4
2857 | | | | | | parent: 4:26a8bac39d9f
2858 | | | | | | parent: 4:26a8bac39d9f
2858 | | | | | | user: test
2859 | | | | | | user: test
2859 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
2860 | | | | | | date: Thu Jan 01 00:00:05 1970 +0000
2860 | | | | | | summary: (5) expand
2861 | | | | | | summary: (5) expand
2861 | | | | | |
2862 | | | | | |
2862 | +---o | | changeset: 4:26a8bac39d9f
2863 | +---o | | changeset: 4:26a8bac39d9f
2863 | | | |/ / parent: 1:6db2ef61d156
2864 | | | |/ / parent: 1:6db2ef61d156
2864 | | | | | parent: 3:27eef8ed80b4
2865 | | | | | parent: 3:27eef8ed80b4
2865 | | | | | user: test
2866 | | | | | user: test
2866 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
2867 | | | | | date: Thu Jan 01 00:00:04 1970 +0000
2867 | | | | | summary: (4) merge two known; one immediate left, one immediate right
2868 | | | | | summary: (4) merge two known; one immediate left, one immediate right
2868 | | | | |
2869 | | | | |
2869
2870
2870 .. unless HGPLAINEXCEPT=graph is set:
2871 .. unless HGPLAINEXCEPT=graph is set:
2871
2872
2872 $ HGPLAIN=1 HGPLAINEXCEPT=graph hg log -G -r 'file("a")' -m
2873 $ HGPLAIN=1 HGPLAINEXCEPT=graph hg log -G -r 'file("a")' -m
2873 @ changeset: 36:08a19a744424
2874 @ changeset: 36:08a19a744424
2874 : branch: branch
2875 : branch: branch
2875 : tag: tip
2876 : tag: tip
2876 : parent: 35:9159c3644c5e
2877 : parent: 35:9159c3644c5e
2877 : parent: 35:9159c3644c5e
2878 : parent: 35:9159c3644c5e
2878 : user: test
2879 : user: test
2879 : date: Thu Jan 01 00:00:36 1970 +0000
2880 : date: Thu Jan 01 00:00:36 1970 +0000
2880 : summary: (36) buggy merge: identical parents
2881 : summary: (36) buggy merge: identical parents
2881 :
2882 :
2882 o changeset: 32:d06dffa21a31
2883 o changeset: 32:d06dffa21a31
2883 |\ parent: 27:886ed638191b
2884 |\ parent: 27:886ed638191b
2884 | : parent: 31:621d83e11f67
2885 | : parent: 31:621d83e11f67
2885 | : user: test
2886 | : user: test
2886 | : date: Thu Jan 01 00:00:32 1970 +0000
2887 | : date: Thu Jan 01 00:00:32 1970 +0000
2887 | : summary: (32) expand
2888 | : summary: (32) expand
2888 | :
2889 | :
2889 o : changeset: 31:621d83e11f67
2890 o : changeset: 31:621d83e11f67
2890 |\: parent: 21:d42a756af44d
2891 |\: parent: 21:d42a756af44d
2891 | : parent: 30:6e11cd4b648f
2892 | : parent: 30:6e11cd4b648f
2892 | : user: test
2893 | : user: test
2893 | : date: Thu Jan 01 00:00:31 1970 +0000
2894 | : date: Thu Jan 01 00:00:31 1970 +0000
2894 | : summary: (31) expand
2895 | : summary: (31) expand
2895 | :
2896 | :
2896 o : changeset: 30:6e11cd4b648f
2897 o : changeset: 30:6e11cd4b648f
2897 |\ \ parent: 28:44ecd0b9ae99
2898 |\ \ parent: 28:44ecd0b9ae99
2898 | ~ : parent: 29:cd9bb2be7593
2899 | ~ : parent: 29:cd9bb2be7593
2899 | : user: test
2900 | : user: test
2900 | : date: Thu Jan 01 00:00:30 1970 +0000
2901 | : date: Thu Jan 01 00:00:30 1970 +0000
2901 | : summary: (30) expand
2902 | : summary: (30) expand
2902 | /
2903 | /
2903 o : changeset: 28:44ecd0b9ae99
2904 o : changeset: 28:44ecd0b9ae99
2904 |\ \ parent: 1:6db2ef61d156
2905 |\ \ parent: 1:6db2ef61d156
2905 | ~ : parent: 26:7f25b6c2f0b9
2906 | ~ : parent: 26:7f25b6c2f0b9
2906 | : user: test
2907 | : user: test
2907 | : date: Thu Jan 01 00:00:28 1970 +0000
2908 | : date: Thu Jan 01 00:00:28 1970 +0000
2908 | : summary: (28) merge zero known
2909 | : summary: (28) merge zero known
2909 | /
2910 | /
2910 o : changeset: 26:7f25b6c2f0b9
2911 o : changeset: 26:7f25b6c2f0b9
2911 |\ \ parent: 18:1aa84d96232a
2912 |\ \ parent: 18:1aa84d96232a
2912 | | : parent: 25:91da8ed57247
2913 | | : parent: 25:91da8ed57247
2913 | | : user: test
2914 | | : user: test
2914 | | : date: Thu Jan 01 00:00:26 1970 +0000
2915 | | : date: Thu Jan 01 00:00:26 1970 +0000
2915 | | : summary: (26) merge one known; far right
2916 | | : summary: (26) merge one known; far right
2916 | | :
2917 | | :
2917 | o : changeset: 25:91da8ed57247
2918 | o : changeset: 25:91da8ed57247
2918 | |\: parent: 21:d42a756af44d
2919 | |\: parent: 21:d42a756af44d
2919 | | : parent: 24:a9c19a3d96b7
2920 | | : parent: 24:a9c19a3d96b7
2920 | | : user: test
2921 | | : user: test
2921 | | : date: Thu Jan 01 00:00:25 1970 +0000
2922 | | : date: Thu Jan 01 00:00:25 1970 +0000
2922 | | : summary: (25) merge one known; far left
2923 | | : summary: (25) merge one known; far left
2923 | | :
2924 | | :
2924 | o : changeset: 24:a9c19a3d96b7
2925 | o : changeset: 24:a9c19a3d96b7
2925 | |\ \ parent: 0:e6eb3150255d
2926 | |\ \ parent: 0:e6eb3150255d
2926 | | ~ : parent: 23:a01cddf0766d
2927 | | ~ : parent: 23:a01cddf0766d
2927 | | : user: test
2928 | | : user: test
2928 | | : date: Thu Jan 01 00:00:24 1970 +0000
2929 | | : date: Thu Jan 01 00:00:24 1970 +0000
2929 | | : summary: (24) merge one known; immediate right
2930 | | : summary: (24) merge one known; immediate right
2930 | | /
2931 | | /
2931 | o : changeset: 23:a01cddf0766d
2932 | o : changeset: 23:a01cddf0766d
2932 | |\ \ parent: 1:6db2ef61d156
2933 | |\ \ parent: 1:6db2ef61d156
2933 | | ~ : parent: 22:e0d9cccacb5d
2934 | | ~ : parent: 22:e0d9cccacb5d
2934 | | : user: test
2935 | | : user: test
2935 | | : date: Thu Jan 01 00:00:23 1970 +0000
2936 | | : date: Thu Jan 01 00:00:23 1970 +0000
2936 | | : summary: (23) merge one known; immediate left
2937 | | : summary: (23) merge one known; immediate left
2937 | | /
2938 | | /
2938 | o : changeset: 22:e0d9cccacb5d
2939 | o : changeset: 22:e0d9cccacb5d
2939 |/:/ parent: 18:1aa84d96232a
2940 |/:/ parent: 18:1aa84d96232a
2940 | : parent: 21:d42a756af44d
2941 | : parent: 21:d42a756af44d
2941 | : user: test
2942 | : user: test
2942 | : date: Thu Jan 01 00:00:22 1970 +0000
2943 | : date: Thu Jan 01 00:00:22 1970 +0000
2943 | : summary: (22) merge two known; one far left, one far right
2944 | : summary: (22) merge two known; one far left, one far right
2944 | :
2945 | :
2945 | o changeset: 21:d42a756af44d
2946 | o changeset: 21:d42a756af44d
2946 | |\ parent: 19:31ddc2c1573b
2947 | |\ parent: 19:31ddc2c1573b
2947 | | | parent: 20:d30ed6450e32
2948 | | | parent: 20:d30ed6450e32
2948 | | | user: test
2949 | | | user: test
2949 | | | date: Thu Jan 01 00:00:21 1970 +0000
2950 | | | date: Thu Jan 01 00:00:21 1970 +0000
2950 | | | summary: (21) expand
2951 | | | summary: (21) expand
2951 | | |
2952 | | |
2952 +---o changeset: 20:d30ed6450e32
2953 +---o changeset: 20:d30ed6450e32
2953 | | | parent: 0:e6eb3150255d
2954 | | | parent: 0:e6eb3150255d
2954 | | ~ parent: 18:1aa84d96232a
2955 | | ~ parent: 18:1aa84d96232a
2955 | | user: test
2956 | | user: test
2956 | | date: Thu Jan 01 00:00:20 1970 +0000
2957 | | date: Thu Jan 01 00:00:20 1970 +0000
2957 | | summary: (20) merge two known; two far right
2958 | | summary: (20) merge two known; two far right
2958 | |
2959 | |
2959 | o changeset: 19:31ddc2c1573b
2960 | o changeset: 19:31ddc2c1573b
2960 | |\ parent: 15:1dda3f72782d
2961 | |\ parent: 15:1dda3f72782d
2961 | | | parent: 17:44765d7c06e0
2962 | | | parent: 17:44765d7c06e0
2962 | | | user: test
2963 | | | user: test
2963 | | | date: Thu Jan 01 00:00:19 1970 +0000
2964 | | | date: Thu Jan 01 00:00:19 1970 +0000
2964 | | | summary: (19) expand
2965 | | | summary: (19) expand
2965 | | |
2966 | | |
2966 o | | changeset: 18:1aa84d96232a
2967 o | | changeset: 18:1aa84d96232a
2967 |\| | parent: 1:6db2ef61d156
2968 |\| | parent: 1:6db2ef61d156
2968 ~ | | parent: 15:1dda3f72782d
2969 ~ | | parent: 15:1dda3f72782d
2969 | | user: test
2970 | | user: test
2970 | | date: Thu Jan 01 00:00:18 1970 +0000
2971 | | date: Thu Jan 01 00:00:18 1970 +0000
2971 | | summary: (18) merge two known; two far left
2972 | | summary: (18) merge two known; two far left
2972 / /
2973 / /
2973 | o changeset: 17:44765d7c06e0
2974 | o changeset: 17:44765d7c06e0
2974 | |\ parent: 12:86b91144a6e9
2975 | |\ parent: 12:86b91144a6e9
2975 | | | parent: 16:3677d192927d
2976 | | | parent: 16:3677d192927d
2976 | | | user: test
2977 | | | user: test
2977 | | | date: Thu Jan 01 00:00:17 1970 +0000
2978 | | | date: Thu Jan 01 00:00:17 1970 +0000
2978 | | | summary: (17) expand
2979 | | | summary: (17) expand
2979 | | |
2980 | | |
2980 | | o changeset: 16:3677d192927d
2981 | | o changeset: 16:3677d192927d
2981 | | |\ parent: 0:e6eb3150255d
2982 | | |\ parent: 0:e6eb3150255d
2982 | | ~ ~ parent: 1:6db2ef61d156
2983 | | ~ ~ parent: 1:6db2ef61d156
2983 | | user: test
2984 | | user: test
2984 | | date: Thu Jan 01 00:00:16 1970 +0000
2985 | | date: Thu Jan 01 00:00:16 1970 +0000
2985 | | summary: (16) merge two known; one immediate right, one near right
2986 | | summary: (16) merge two known; one immediate right, one near right
2986 | |
2987 | |
2987 o | changeset: 15:1dda3f72782d
2988 o | changeset: 15:1dda3f72782d
2988 |\ \ parent: 13:22d8966a97e3
2989 |\ \ parent: 13:22d8966a97e3
2989 | | | parent: 14:8eac370358ef
2990 | | | parent: 14:8eac370358ef
2990 | | | user: test
2991 | | | user: test
2991 | | | date: Thu Jan 01 00:00:15 1970 +0000
2992 | | | date: Thu Jan 01 00:00:15 1970 +0000
2992 | | | summary: (15) expand
2993 | | | summary: (15) expand
2993 | | |
2994 | | |
2994 | o | changeset: 14:8eac370358ef
2995 | o | changeset: 14:8eac370358ef
2995 | |\| parent: 0:e6eb3150255d
2996 | |\| parent: 0:e6eb3150255d
2996 | ~ | parent: 12:86b91144a6e9
2997 | ~ | parent: 12:86b91144a6e9
2997 | | user: test
2998 | | user: test
2998 | | date: Thu Jan 01 00:00:14 1970 +0000
2999 | | date: Thu Jan 01 00:00:14 1970 +0000
2999 | | summary: (14) merge two known; one immediate right, one far right
3000 | | summary: (14) merge two known; one immediate right, one far right
3000 | /
3001 | /
3001 o | changeset: 13:22d8966a97e3
3002 o | changeset: 13:22d8966a97e3
3002 |\ \ parent: 9:7010c0af0a35
3003 |\ \ parent: 9:7010c0af0a35
3003 | | | parent: 11:832d76e6bdf2
3004 | | | parent: 11:832d76e6bdf2
3004 | | | user: test
3005 | | | user: test
3005 | | | date: Thu Jan 01 00:00:13 1970 +0000
3006 | | | date: Thu Jan 01 00:00:13 1970 +0000
3006 | | | summary: (13) expand
3007 | | | summary: (13) expand
3007 | | |
3008 | | |
3008 +---o changeset: 12:86b91144a6e9
3009 +---o changeset: 12:86b91144a6e9
3009 | | | parent: 1:6db2ef61d156
3010 | | | parent: 1:6db2ef61d156
3010 | | ~ parent: 9:7010c0af0a35
3011 | | ~ parent: 9:7010c0af0a35
3011 | | user: test
3012 | | user: test
3012 | | date: Thu Jan 01 00:00:12 1970 +0000
3013 | | date: Thu Jan 01 00:00:12 1970 +0000
3013 | | summary: (12) merge two known; one immediate right, one far left
3014 | | summary: (12) merge two known; one immediate right, one far left
3014 | |
3015 | |
3015 | o changeset: 11:832d76e6bdf2
3016 | o changeset: 11:832d76e6bdf2
3016 | |\ parent: 6:b105a072e251
3017 | |\ parent: 6:b105a072e251
3017 | | | parent: 10:74c64d036d72
3018 | | | parent: 10:74c64d036d72
3018 | | | user: test
3019 | | | user: test
3019 | | | date: Thu Jan 01 00:00:11 1970 +0000
3020 | | | date: Thu Jan 01 00:00:11 1970 +0000
3020 | | | summary: (11) expand
3021 | | | summary: (11) expand
3021 | | |
3022 | | |
3022 | | o changeset: 10:74c64d036d72
3023 | | o changeset: 10:74c64d036d72
3023 | |/| parent: 0:e6eb3150255d
3024 | |/| parent: 0:e6eb3150255d
3024 | | ~ parent: 6:b105a072e251
3025 | | ~ parent: 6:b105a072e251
3025 | | user: test
3026 | | user: test
3026 | | date: Thu Jan 01 00:00:10 1970 +0000
3027 | | date: Thu Jan 01 00:00:10 1970 +0000
3027 | | summary: (10) merge two known; one immediate left, one near right
3028 | | summary: (10) merge two known; one immediate left, one near right
3028 | |
3029 | |
3029 o | changeset: 9:7010c0af0a35
3030 o | changeset: 9:7010c0af0a35
3030 |\ \ parent: 7:b632bb1b1224
3031 |\ \ parent: 7:b632bb1b1224
3031 | | | parent: 8:7a0b11f71937
3032 | | | parent: 8:7a0b11f71937
3032 | | | user: test
3033 | | | user: test
3033 | | | date: Thu Jan 01 00:00:09 1970 +0000
3034 | | | date: Thu Jan 01 00:00:09 1970 +0000
3034 | | | summary: (9) expand
3035 | | | summary: (9) expand
3035 | | |
3036 | | |
3036 | o | changeset: 8:7a0b11f71937
3037 | o | changeset: 8:7a0b11f71937
3037 |/| | parent: 0:e6eb3150255d
3038 |/| | parent: 0:e6eb3150255d
3038 | ~ | parent: 7:b632bb1b1224
3039 | ~ | parent: 7:b632bb1b1224
3039 | | user: test
3040 | | user: test
3040 | | date: Thu Jan 01 00:00:08 1970 +0000
3041 | | date: Thu Jan 01 00:00:08 1970 +0000
3041 | | summary: (8) merge two known; one immediate left, one far right
3042 | | summary: (8) merge two known; one immediate left, one far right
3042 | /
3043 | /
3043 o | changeset: 7:b632bb1b1224
3044 o | changeset: 7:b632bb1b1224
3044 |\ \ parent: 2:3d9a33b8d1e1
3045 |\ \ parent: 2:3d9a33b8d1e1
3045 | ~ | parent: 5:4409d547b708
3046 | ~ | parent: 5:4409d547b708
3046 | | user: test
3047 | | user: test
3047 | | date: Thu Jan 01 00:00:07 1970 +0000
3048 | | date: Thu Jan 01 00:00:07 1970 +0000
3048 | | summary: (7) expand
3049 | | summary: (7) expand
3049 | /
3050 | /
3050 | o changeset: 6:b105a072e251
3051 | o changeset: 6:b105a072e251
3051 |/| parent: 2:3d9a33b8d1e1
3052 |/| parent: 2:3d9a33b8d1e1
3052 | ~ parent: 5:4409d547b708
3053 | ~ parent: 5:4409d547b708
3053 | user: test
3054 | user: test
3054 | date: Thu Jan 01 00:00:06 1970 +0000
3055 | date: Thu Jan 01 00:00:06 1970 +0000
3055 | summary: (6) merge two known; one immediate left, one far left
3056 | summary: (6) merge two known; one immediate left, one far left
3056 |
3057 |
3057 o changeset: 5:4409d547b708
3058 o changeset: 5:4409d547b708
3058 |\ parent: 3:27eef8ed80b4
3059 |\ parent: 3:27eef8ed80b4
3059 | ~ parent: 4:26a8bac39d9f
3060 | ~ parent: 4:26a8bac39d9f
3060 | user: test
3061 | user: test
3061 | date: Thu Jan 01 00:00:05 1970 +0000
3062 | date: Thu Jan 01 00:00:05 1970 +0000
3062 | summary: (5) expand
3063 | summary: (5) expand
3063 |
3064 |
3064 o changeset: 4:26a8bac39d9f
3065 o changeset: 4:26a8bac39d9f
3065 |\ parent: 1:6db2ef61d156
3066 |\ parent: 1:6db2ef61d156
3066 ~ ~ parent: 3:27eef8ed80b4
3067 ~ ~ parent: 3:27eef8ed80b4
3067 user: test
3068 user: test
3068 date: Thu Jan 01 00:00:04 1970 +0000
3069 date: Thu Jan 01 00:00:04 1970 +0000
3069 summary: (4) merge two known; one immediate left, one immediate right
3070 summary: (4) merge two known; one immediate left, one immediate right
3070
3071
3071 Draw only part of a grandparent line differently with "<N><char>"; only the
3072 Draw only part of a grandparent line differently with "<N><char>"; only the
3072 last N lines (for positive N) or everything but the first N lines (for
3073 last N lines (for positive N) or everything but the first N lines (for
3073 negative N) along the current node use the style, the rest of the edge uses
3074 negative N) along the current node use the style, the rest of the edge uses
3074 the parent edge styling.
3075 the parent edge styling.
3075
3076
3076 Last 3 lines:
3077 Last 3 lines:
3077
3078
3078 $ cat << EOF >> $HGRCPATH
3079 $ cat << EOF >> $HGRCPATH
3079 > [experimental]
3080 > [experimental]
3080 > graphstyle.parent = !
3081 > graphstyle.parent = !
3081 > graphstyle.grandparent = 3.
3082 > graphstyle.grandparent = 3.
3082 > graphstyle.missing =
3083 > graphstyle.missing =
3083 > EOF
3084 > EOF
3084 $ hg log -G -r '36:18 & file("a")' -m
3085 $ hg log -G -r '36:18 & file("a")' -m
3085 @ changeset: 36:08a19a744424
3086 @ changeset: 36:08a19a744424
3086 ! branch: branch
3087 ! branch: branch
3087 ! tag: tip
3088 ! tag: tip
3088 ! parent: 35:9159c3644c5e
3089 ! parent: 35:9159c3644c5e
3089 ! parent: 35:9159c3644c5e
3090 ! parent: 35:9159c3644c5e
3090 ! user: test
3091 ! user: test
3091 . date: Thu Jan 01 00:00:36 1970 +0000
3092 . date: Thu Jan 01 00:00:36 1970 +0000
3092 . summary: (36) buggy merge: identical parents
3093 . summary: (36) buggy merge: identical parents
3093 .
3094 .
3094 o changeset: 32:d06dffa21a31
3095 o changeset: 32:d06dffa21a31
3095 !\ parent: 27:886ed638191b
3096 !\ parent: 27:886ed638191b
3096 ! ! parent: 31:621d83e11f67
3097 ! ! parent: 31:621d83e11f67
3097 ! ! user: test
3098 ! ! user: test
3098 ! . date: Thu Jan 01 00:00:32 1970 +0000
3099 ! . date: Thu Jan 01 00:00:32 1970 +0000
3099 ! . summary: (32) expand
3100 ! . summary: (32) expand
3100 ! .
3101 ! .
3101 o ! changeset: 31:621d83e11f67
3102 o ! changeset: 31:621d83e11f67
3102 !\! parent: 21:d42a756af44d
3103 !\! parent: 21:d42a756af44d
3103 ! ! parent: 30:6e11cd4b648f
3104 ! ! parent: 30:6e11cd4b648f
3104 ! ! user: test
3105 ! ! user: test
3105 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3106 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3106 ! ! summary: (31) expand
3107 ! ! summary: (31) expand
3107 ! !
3108 ! !
3108 o ! changeset: 30:6e11cd4b648f
3109 o ! changeset: 30:6e11cd4b648f
3109 !\ \ parent: 28:44ecd0b9ae99
3110 !\ \ parent: 28:44ecd0b9ae99
3110 ! ~ ! parent: 29:cd9bb2be7593
3111 ! ~ ! parent: 29:cd9bb2be7593
3111 ! ! user: test
3112 ! ! user: test
3112 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3113 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3113 ! ! summary: (30) expand
3114 ! ! summary: (30) expand
3114 ! /
3115 ! /
3115 o ! changeset: 28:44ecd0b9ae99
3116 o ! changeset: 28:44ecd0b9ae99
3116 !\ \ parent: 1:6db2ef61d156
3117 !\ \ parent: 1:6db2ef61d156
3117 ! ~ ! parent: 26:7f25b6c2f0b9
3118 ! ~ ! parent: 26:7f25b6c2f0b9
3118 ! ! user: test
3119 ! ! user: test
3119 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3120 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3120 ! ! summary: (28) merge zero known
3121 ! ! summary: (28) merge zero known
3121 ! /
3122 ! /
3122 o ! changeset: 26:7f25b6c2f0b9
3123 o ! changeset: 26:7f25b6c2f0b9
3123 !\ \ parent: 18:1aa84d96232a
3124 !\ \ parent: 18:1aa84d96232a
3124 ! ! ! parent: 25:91da8ed57247
3125 ! ! ! parent: 25:91da8ed57247
3125 ! ! ! user: test
3126 ! ! ! user: test
3126 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3127 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3127 ! ! ! summary: (26) merge one known; far right
3128 ! ! ! summary: (26) merge one known; far right
3128 ! ! !
3129 ! ! !
3129 ! o ! changeset: 25:91da8ed57247
3130 ! o ! changeset: 25:91da8ed57247
3130 ! !\! parent: 21:d42a756af44d
3131 ! !\! parent: 21:d42a756af44d
3131 ! ! ! parent: 24:a9c19a3d96b7
3132 ! ! ! parent: 24:a9c19a3d96b7
3132 ! ! ! user: test
3133 ! ! ! user: test
3133 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3134 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3134 ! ! ! summary: (25) merge one known; far left
3135 ! ! ! summary: (25) merge one known; far left
3135 ! ! !
3136 ! ! !
3136 ! o ! changeset: 24:a9c19a3d96b7
3137 ! o ! changeset: 24:a9c19a3d96b7
3137 ! !\ \ parent: 0:e6eb3150255d
3138 ! !\ \ parent: 0:e6eb3150255d
3138 ! ! ~ ! parent: 23:a01cddf0766d
3139 ! ! ~ ! parent: 23:a01cddf0766d
3139 ! ! ! user: test
3140 ! ! ! user: test
3140 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3141 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3141 ! ! ! summary: (24) merge one known; immediate right
3142 ! ! ! summary: (24) merge one known; immediate right
3142 ! ! /
3143 ! ! /
3143 ! o ! changeset: 23:a01cddf0766d
3144 ! o ! changeset: 23:a01cddf0766d
3144 ! !\ \ parent: 1:6db2ef61d156
3145 ! !\ \ parent: 1:6db2ef61d156
3145 ! ! ~ ! parent: 22:e0d9cccacb5d
3146 ! ! ~ ! parent: 22:e0d9cccacb5d
3146 ! ! ! user: test
3147 ! ! ! user: test
3147 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3148 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3148 ! ! ! summary: (23) merge one known; immediate left
3149 ! ! ! summary: (23) merge one known; immediate left
3149 ! ! /
3150 ! ! /
3150 ! o ! changeset: 22:e0d9cccacb5d
3151 ! o ! changeset: 22:e0d9cccacb5d
3151 !/!/ parent: 18:1aa84d96232a
3152 !/!/ parent: 18:1aa84d96232a
3152 ! ! parent: 21:d42a756af44d
3153 ! ! parent: 21:d42a756af44d
3153 ! ! user: test
3154 ! ! user: test
3154 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3155 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3155 ! ! summary: (22) merge two known; one far left, one far right
3156 ! ! summary: (22) merge two known; one far left, one far right
3156 ! !
3157 ! !
3157 ! o changeset: 21:d42a756af44d
3158 ! o changeset: 21:d42a756af44d
3158 ! !\ parent: 19:31ddc2c1573b
3159 ! !\ parent: 19:31ddc2c1573b
3159 ! ! ! parent: 20:d30ed6450e32
3160 ! ! ! parent: 20:d30ed6450e32
3160 ! ! ! user: test
3161 ! ! ! user: test
3161 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3162 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3162 ! ! ! summary: (21) expand
3163 ! ! ! summary: (21) expand
3163 ! ! !
3164 ! ! !
3164 +---o changeset: 20:d30ed6450e32
3165 +---o changeset: 20:d30ed6450e32
3165 ! ! | parent: 0:e6eb3150255d
3166 ! ! | parent: 0:e6eb3150255d
3166 ! ! ~ parent: 18:1aa84d96232a
3167 ! ! ~ parent: 18:1aa84d96232a
3167 ! ! user: test
3168 ! ! user: test
3168 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3169 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3169 ! ! summary: (20) merge two known; two far right
3170 ! ! summary: (20) merge two known; two far right
3170 ! !
3171 ! !
3171 ! o changeset: 19:31ddc2c1573b
3172 ! o changeset: 19:31ddc2c1573b
3172 ! |\ parent: 15:1dda3f72782d
3173 ! |\ parent: 15:1dda3f72782d
3173 ! ~ ~ parent: 17:44765d7c06e0
3174 ! ~ ~ parent: 17:44765d7c06e0
3174 ! user: test
3175 ! user: test
3175 ! date: Thu Jan 01 00:00:19 1970 +0000
3176 ! date: Thu Jan 01 00:00:19 1970 +0000
3176 ! summary: (19) expand
3177 ! summary: (19) expand
3177 !
3178 !
3178 o changeset: 18:1aa84d96232a
3179 o changeset: 18:1aa84d96232a
3179 |\ parent: 1:6db2ef61d156
3180 |\ parent: 1:6db2ef61d156
3180 ~ ~ parent: 15:1dda3f72782d
3181 ~ ~ parent: 15:1dda3f72782d
3181 user: test
3182 user: test
3182 date: Thu Jan 01 00:00:18 1970 +0000
3183 date: Thu Jan 01 00:00:18 1970 +0000
3183 summary: (18) merge two known; two far left
3184 summary: (18) merge two known; two far left
3184
3185
3185 All but the first 3 lines:
3186 All but the first 3 lines:
3186
3187
3187 $ cat << EOF >> $HGRCPATH
3188 $ cat << EOF >> $HGRCPATH
3188 > [experimental]
3189 > [experimental]
3189 > graphstyle.parent = !
3190 > graphstyle.parent = !
3190 > graphstyle.grandparent = -3.
3191 > graphstyle.grandparent = -3.
3191 > graphstyle.missing =
3192 > graphstyle.missing =
3192 > EOF
3193 > EOF
3193 $ hg log -G -r '36:18 & file("a")' -m
3194 $ hg log -G -r '36:18 & file("a")' -m
3194 @ changeset: 36:08a19a744424
3195 @ changeset: 36:08a19a744424
3195 ! branch: branch
3196 ! branch: branch
3196 ! tag: tip
3197 ! tag: tip
3197 . parent: 35:9159c3644c5e
3198 . parent: 35:9159c3644c5e
3198 . parent: 35:9159c3644c5e
3199 . parent: 35:9159c3644c5e
3199 . user: test
3200 . user: test
3200 . date: Thu Jan 01 00:00:36 1970 +0000
3201 . date: Thu Jan 01 00:00:36 1970 +0000
3201 . summary: (36) buggy merge: identical parents
3202 . summary: (36) buggy merge: identical parents
3202 .
3203 .
3203 o changeset: 32:d06dffa21a31
3204 o changeset: 32:d06dffa21a31
3204 !\ parent: 27:886ed638191b
3205 !\ parent: 27:886ed638191b
3205 ! ! parent: 31:621d83e11f67
3206 ! ! parent: 31:621d83e11f67
3206 ! . user: test
3207 ! . user: test
3207 ! . date: Thu Jan 01 00:00:32 1970 +0000
3208 ! . date: Thu Jan 01 00:00:32 1970 +0000
3208 ! . summary: (32) expand
3209 ! . summary: (32) expand
3209 ! .
3210 ! .
3210 o ! changeset: 31:621d83e11f67
3211 o ! changeset: 31:621d83e11f67
3211 !\! parent: 21:d42a756af44d
3212 !\! parent: 21:d42a756af44d
3212 ! ! parent: 30:6e11cd4b648f
3213 ! ! parent: 30:6e11cd4b648f
3213 ! ! user: test
3214 ! ! user: test
3214 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3215 ! ! date: Thu Jan 01 00:00:31 1970 +0000
3215 ! ! summary: (31) expand
3216 ! ! summary: (31) expand
3216 ! !
3217 ! !
3217 o ! changeset: 30:6e11cd4b648f
3218 o ! changeset: 30:6e11cd4b648f
3218 !\ \ parent: 28:44ecd0b9ae99
3219 !\ \ parent: 28:44ecd0b9ae99
3219 ! ~ ! parent: 29:cd9bb2be7593
3220 ! ~ ! parent: 29:cd9bb2be7593
3220 ! ! user: test
3221 ! ! user: test
3221 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3222 ! ! date: Thu Jan 01 00:00:30 1970 +0000
3222 ! ! summary: (30) expand
3223 ! ! summary: (30) expand
3223 ! /
3224 ! /
3224 o ! changeset: 28:44ecd0b9ae99
3225 o ! changeset: 28:44ecd0b9ae99
3225 !\ \ parent: 1:6db2ef61d156
3226 !\ \ parent: 1:6db2ef61d156
3226 ! ~ ! parent: 26:7f25b6c2f0b9
3227 ! ~ ! parent: 26:7f25b6c2f0b9
3227 ! ! user: test
3228 ! ! user: test
3228 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3229 ! ! date: Thu Jan 01 00:00:28 1970 +0000
3229 ! ! summary: (28) merge zero known
3230 ! ! summary: (28) merge zero known
3230 ! /
3231 ! /
3231 o ! changeset: 26:7f25b6c2f0b9
3232 o ! changeset: 26:7f25b6c2f0b9
3232 !\ \ parent: 18:1aa84d96232a
3233 !\ \ parent: 18:1aa84d96232a
3233 ! ! ! parent: 25:91da8ed57247
3234 ! ! ! parent: 25:91da8ed57247
3234 ! ! ! user: test
3235 ! ! ! user: test
3235 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3236 ! ! ! date: Thu Jan 01 00:00:26 1970 +0000
3236 ! ! ! summary: (26) merge one known; far right
3237 ! ! ! summary: (26) merge one known; far right
3237 ! ! !
3238 ! ! !
3238 ! o ! changeset: 25:91da8ed57247
3239 ! o ! changeset: 25:91da8ed57247
3239 ! !\! parent: 21:d42a756af44d
3240 ! !\! parent: 21:d42a756af44d
3240 ! ! ! parent: 24:a9c19a3d96b7
3241 ! ! ! parent: 24:a9c19a3d96b7
3241 ! ! ! user: test
3242 ! ! ! user: test
3242 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3243 ! ! ! date: Thu Jan 01 00:00:25 1970 +0000
3243 ! ! ! summary: (25) merge one known; far left
3244 ! ! ! summary: (25) merge one known; far left
3244 ! ! !
3245 ! ! !
3245 ! o ! changeset: 24:a9c19a3d96b7
3246 ! o ! changeset: 24:a9c19a3d96b7
3246 ! !\ \ parent: 0:e6eb3150255d
3247 ! !\ \ parent: 0:e6eb3150255d
3247 ! ! ~ ! parent: 23:a01cddf0766d
3248 ! ! ~ ! parent: 23:a01cddf0766d
3248 ! ! ! user: test
3249 ! ! ! user: test
3249 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3250 ! ! ! date: Thu Jan 01 00:00:24 1970 +0000
3250 ! ! ! summary: (24) merge one known; immediate right
3251 ! ! ! summary: (24) merge one known; immediate right
3251 ! ! /
3252 ! ! /
3252 ! o ! changeset: 23:a01cddf0766d
3253 ! o ! changeset: 23:a01cddf0766d
3253 ! !\ \ parent: 1:6db2ef61d156
3254 ! !\ \ parent: 1:6db2ef61d156
3254 ! ! ~ ! parent: 22:e0d9cccacb5d
3255 ! ! ~ ! parent: 22:e0d9cccacb5d
3255 ! ! ! user: test
3256 ! ! ! user: test
3256 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3257 ! ! ! date: Thu Jan 01 00:00:23 1970 +0000
3257 ! ! ! summary: (23) merge one known; immediate left
3258 ! ! ! summary: (23) merge one known; immediate left
3258 ! ! /
3259 ! ! /
3259 ! o ! changeset: 22:e0d9cccacb5d
3260 ! o ! changeset: 22:e0d9cccacb5d
3260 !/!/ parent: 18:1aa84d96232a
3261 !/!/ parent: 18:1aa84d96232a
3261 ! ! parent: 21:d42a756af44d
3262 ! ! parent: 21:d42a756af44d
3262 ! ! user: test
3263 ! ! user: test
3263 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3264 ! ! date: Thu Jan 01 00:00:22 1970 +0000
3264 ! ! summary: (22) merge two known; one far left, one far right
3265 ! ! summary: (22) merge two known; one far left, one far right
3265 ! !
3266 ! !
3266 ! o changeset: 21:d42a756af44d
3267 ! o changeset: 21:d42a756af44d
3267 ! !\ parent: 19:31ddc2c1573b
3268 ! !\ parent: 19:31ddc2c1573b
3268 ! ! ! parent: 20:d30ed6450e32
3269 ! ! ! parent: 20:d30ed6450e32
3269 ! ! ! user: test
3270 ! ! ! user: test
3270 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3271 ! ! ! date: Thu Jan 01 00:00:21 1970 +0000
3271 ! ! ! summary: (21) expand
3272 ! ! ! summary: (21) expand
3272 ! ! !
3273 ! ! !
3273 +---o changeset: 20:d30ed6450e32
3274 +---o changeset: 20:d30ed6450e32
3274 ! ! | parent: 0:e6eb3150255d
3275 ! ! | parent: 0:e6eb3150255d
3275 ! ! ~ parent: 18:1aa84d96232a
3276 ! ! ~ parent: 18:1aa84d96232a
3276 ! ! user: test
3277 ! ! user: test
3277 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3278 ! ! date: Thu Jan 01 00:00:20 1970 +0000
3278 ! ! summary: (20) merge two known; two far right
3279 ! ! summary: (20) merge two known; two far right
3279 ! !
3280 ! !
3280 ! o changeset: 19:31ddc2c1573b
3281 ! o changeset: 19:31ddc2c1573b
3281 ! |\ parent: 15:1dda3f72782d
3282 ! |\ parent: 15:1dda3f72782d
3282 ! ~ ~ parent: 17:44765d7c06e0
3283 ! ~ ~ parent: 17:44765d7c06e0
3283 ! user: test
3284 ! user: test
3284 ! date: Thu Jan 01 00:00:19 1970 +0000
3285 ! date: Thu Jan 01 00:00:19 1970 +0000
3285 ! summary: (19) expand
3286 ! summary: (19) expand
3286 !
3287 !
3287 o changeset: 18:1aa84d96232a
3288 o changeset: 18:1aa84d96232a
3288 |\ parent: 1:6db2ef61d156
3289 |\ parent: 1:6db2ef61d156
3289 ~ ~ parent: 15:1dda3f72782d
3290 ~ ~ parent: 15:1dda3f72782d
3290 user: test
3291 user: test
3291 date: Thu Jan 01 00:00:18 1970 +0000
3292 date: Thu Jan 01 00:00:18 1970 +0000
3292 summary: (18) merge two known; two far left
3293 summary: (18) merge two known; two far left
3293
3294
3294 $ cd ..
3295 $ cd ..
3295
3296
3296 Change graph shorten, test better with graphstyle.missing not none
3297 Change graph shorten, test better with graphstyle.missing not none
3297
3298
3298 $ cd repo
3299 $ cd repo
3299 $ cat << EOF >> $HGRCPATH
3300 $ cat << EOF >> $HGRCPATH
3300 > [experimental]
3301 > [experimental]
3301 > graphstyle.parent = |
3302 > graphstyle.parent = |
3302 > graphstyle.grandparent = :
3303 > graphstyle.grandparent = :
3303 > graphstyle.missing = '
3304 > graphstyle.missing = '
3304 > graphshorten = true
3305 > graphshorten = true
3305 > EOF
3306 > EOF
3306 $ hg log -G -r 'file("a")' -m -T '{rev} {desc}'
3307 $ hg log -G -r 'file("a")' -m -T '{rev} {desc}'
3307 @ 36 (36) buggy merge: identical parents
3308 @ 36 (36) buggy merge: identical parents
3308 o 32 (32) expand
3309 o 32 (32) expand
3309 |\
3310 |\
3310 o : 31 (31) expand
3311 o : 31 (31) expand
3311 |\:
3312 |\:
3312 o : 30 (30) expand
3313 o : 30 (30) expand
3313 |\ \
3314 |\ \
3314 o \ \ 28 (28) merge zero known
3315 o \ \ 28 (28) merge zero known
3315 |\ \ \
3316 |\ \ \
3316 o \ \ \ 26 (26) merge one known; far right
3317 o \ \ \ 26 (26) merge one known; far right
3317 |\ \ \ \
3318 |\ \ \ \
3318 | o-----+ 25 (25) merge one known; far left
3319 | o-----+ 25 (25) merge one known; far left
3319 | o ' ' : 24 (24) merge one known; immediate right
3320 | o ' ' : 24 (24) merge one known; immediate right
3320 | |\ \ \ \
3321 | |\ \ \ \
3321 | o---+ ' : 23 (23) merge one known; immediate left
3322 | o---+ ' : 23 (23) merge one known; immediate left
3322 | o-------+ 22 (22) merge two known; one far left, one far right
3323 | o-------+ 22 (22) merge two known; one far left, one far right
3323 |/ / / / /
3324 |/ / / / /
3324 | ' ' ' o 21 (21) expand
3325 | ' ' ' o 21 (21) expand
3325 | ' ' ' |\
3326 | ' ' ' |\
3326 +-+-------o 20 (20) merge two known; two far right
3327 +-+-------o 20 (20) merge two known; two far right
3327 | ' ' ' o 19 (19) expand
3328 | ' ' ' o 19 (19) expand
3328 | ' ' ' |\
3329 | ' ' ' |\
3329 o---+---+ | 18 (18) merge two known; two far left
3330 o---+---+ | 18 (18) merge two known; two far left
3330 / / / / /
3331 / / / / /
3331 ' ' ' | o 17 (17) expand
3332 ' ' ' | o 17 (17) expand
3332 ' ' ' | |\
3333 ' ' ' | |\
3333 +-+-------o 16 (16) merge two known; one immediate right, one near right
3334 +-+-------o 16 (16) merge two known; one immediate right, one near right
3334 ' ' ' o | 15 (15) expand
3335 ' ' ' o | 15 (15) expand
3335 ' ' ' |\ \
3336 ' ' ' |\ \
3336 +-------o | 14 (14) merge two known; one immediate right, one far right
3337 +-------o | 14 (14) merge two known; one immediate right, one far right
3337 ' ' ' | |/
3338 ' ' ' | |/
3338 ' ' ' o | 13 (13) expand
3339 ' ' ' o | 13 (13) expand
3339 ' ' ' |\ \
3340 ' ' ' |\ \
3340 ' +---+---o 12 (12) merge two known; one immediate right, one far left
3341 ' +---+---o 12 (12) merge two known; one immediate right, one far left
3341 ' ' ' | o 11 (11) expand
3342 ' ' ' | o 11 (11) expand
3342 ' ' ' | |\
3343 ' ' ' | |\
3343 +---------o 10 (10) merge two known; one immediate left, one near right
3344 +---------o 10 (10) merge two known; one immediate left, one near right
3344 ' ' ' | |/
3345 ' ' ' | |/
3345 ' ' ' o | 9 (9) expand
3346 ' ' ' o | 9 (9) expand
3346 ' ' ' |\ \
3347 ' ' ' |\ \
3347 +-------o | 8 (8) merge two known; one immediate left, one far right
3348 +-------o | 8 (8) merge two known; one immediate left, one far right
3348 ' ' ' |/ /
3349 ' ' ' |/ /
3349 ' ' ' o | 7 (7) expand
3350 ' ' ' o | 7 (7) expand
3350 ' ' ' |\ \
3351 ' ' ' |\ \
3351 ' ' ' +---o 6 (6) merge two known; one immediate left, one far left
3352 ' ' ' +---o 6 (6) merge two known; one immediate left, one far left
3352 ' ' ' | '/
3353 ' ' ' | '/
3353 ' ' ' o ' 5 (5) expand
3354 ' ' ' o ' 5 (5) expand
3354 ' ' ' |\ \
3355 ' ' ' |\ \
3355 ' +---o ' ' 4 (4) merge two known; one immediate left, one immediate right
3356 ' +---o ' ' 4 (4) merge two known; one immediate left, one immediate right
3356 ' ' ' '/ /
3357 ' ' ' '/ /
3357
3358
3358 behavior with newlines
3359 behavior with newlines
3359
3360
3360 $ hg log -G -r ::2 -T '{rev} {desc}'
3361 $ hg log -G -r ::2 -T '{rev} {desc}'
3361 o 2 (2) collapse
3362 o 2 (2) collapse
3362 o 1 (1) collapse
3363 o 1 (1) collapse
3363 o 0 (0) root
3364 o 0 (0) root
3364
3365
3365 $ hg log -G -r ::2 -T '{rev} {desc}\n'
3366 $ hg log -G -r ::2 -T '{rev} {desc}\n'
3366 o 2 (2) collapse
3367 o 2 (2) collapse
3367 o 1 (1) collapse
3368 o 1 (1) collapse
3368 o 0 (0) root
3369 o 0 (0) root
3369
3370
3370 $ hg log -G -r ::2 -T '{rev} {desc}\n\n'
3371 $ hg log -G -r ::2 -T '{rev} {desc}\n\n'
3371 o 2 (2) collapse
3372 o 2 (2) collapse
3372 |
3373 |
3373 o 1 (1) collapse
3374 o 1 (1) collapse
3374 |
3375 |
3375 o 0 (0) root
3376 o 0 (0) root
3376
3377
3377
3378
3378 $ hg log -G -r ::2 -T '\n{rev} {desc}'
3379 $ hg log -G -r ::2 -T '\n{rev} {desc}'
3379 o
3380 o
3380 | 2 (2) collapse
3381 | 2 (2) collapse
3381 o
3382 o
3382 | 1 (1) collapse
3383 | 1 (1) collapse
3383 o
3384 o
3384 0 (0) root
3385 0 (0) root
3385
3386
3386 $ hg log -G -r ::2 -T '{rev} {desc}\n\n\n'
3387 $ hg log -G -r ::2 -T '{rev} {desc}\n\n\n'
3387 o 2 (2) collapse
3388 o 2 (2) collapse
3388 |
3389 |
3389 |
3390 |
3390 o 1 (1) collapse
3391 o 1 (1) collapse
3391 |
3392 |
3392 |
3393 |
3393 o 0 (0) root
3394 o 0 (0) root
3394
3395
3395
3396
3396 $ cd ..
3397 $ cd ..
3397
3398
3398 When inserting extra line nodes to handle more than 2 parents, ensure that
3399 When inserting extra line nodes to handle more than 2 parents, ensure that
3399 the right node styles are used (issue5174):
3400 the right node styles are used (issue5174):
3400
3401
3401 $ hg init repo-issue5174
3402 $ hg init repo-issue5174
3402 $ cd repo-issue5174
3403 $ cd repo-issue5174
3403 $ echo a > f0
3404 $ echo a > f0
3404 $ hg ci -Aqm 0
3405 $ hg ci -Aqm 0
3405 $ echo a > f1
3406 $ echo a > f1
3406 $ hg ci -Aqm 1
3407 $ hg ci -Aqm 1
3407 $ echo a > f2
3408 $ echo a > f2
3408 $ hg ci -Aqm 2
3409 $ hg ci -Aqm 2
3409 $ hg co ".^"
3410 $ hg co ".^"
3410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3411 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3411 $ echo a > f3
3412 $ echo a > f3
3412 $ hg ci -Aqm 3
3413 $ hg ci -Aqm 3
3413 $ hg co ".^^"
3414 $ hg co ".^^"
3414 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
3415 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
3415 $ echo a > f4
3416 $ echo a > f4
3416 $ hg ci -Aqm 4
3417 $ hg ci -Aqm 4
3417 $ hg merge -r 2
3418 $ hg merge -r 2
3418 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3419 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3419 (branch merge, don't forget to commit)
3420 (branch merge, don't forget to commit)
3420 $ hg ci -qm 5
3421 $ hg ci -qm 5
3421 $ hg merge -r 3
3422 $ hg merge -r 3
3422 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3423 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3423 (branch merge, don't forget to commit)
3424 (branch merge, don't forget to commit)
3424 $ hg ci -qm 6
3425 $ hg ci -qm 6
3425 $ hg log -G -r '0 | 1 | 2 | 6'
3426 $ hg log -G -r '0 | 1 | 2 | 6'
3426 @ changeset: 6:851fe89689ad
3427 @ changeset: 6:851fe89689ad
3427 :\ tag: tip
3428 :\ tag: tip
3428 : : parent: 5:4f1e3cf15f5d
3429 : : parent: 5:4f1e3cf15f5d
3429 : : parent: 3:b74ba7084d2d
3430 : : parent: 3:b74ba7084d2d
3430 : : user: test
3431 : : user: test
3431 : : date: Thu Jan 01 00:00:00 1970 +0000
3432 : : date: Thu Jan 01 00:00:00 1970 +0000
3432 : : summary: 6
3433 : : summary: 6
3433 : :
3434 : :
3434 : \
3435 : \
3435 : :\
3436 : :\
3436 : o : changeset: 2:3e6599df4cce
3437 : o : changeset: 2:3e6599df4cce
3437 : :/ user: test
3438 : :/ user: test
3438 : : date: Thu Jan 01 00:00:00 1970 +0000
3439 : : date: Thu Jan 01 00:00:00 1970 +0000
3439 : : summary: 2
3440 : : summary: 2
3440 : :
3441 : :
3441 : o changeset: 1:bd9a55143933
3442 : o changeset: 1:bd9a55143933
3442 :/ user: test
3443 :/ user: test
3443 : date: Thu Jan 01 00:00:00 1970 +0000
3444 : date: Thu Jan 01 00:00:00 1970 +0000
3444 : summary: 1
3445 : summary: 1
3445 :
3446 :
3446 o changeset: 0:870a5edc339c
3447 o changeset: 0:870a5edc339c
3447 user: test
3448 user: test
3448 date: Thu Jan 01 00:00:00 1970 +0000
3449 date: Thu Jan 01 00:00:00 1970 +0000
3449 summary: 0
3450 summary: 0
3450
3451
3451
3452
3452 $ cd ..
3453 $ cd ..
3453
3454
3454 Multiple roots (issue5440):
3455 Multiple roots (issue5440):
3455
3456
3456 $ hg init multiroots
3457 $ hg init multiroots
3457 $ cd multiroots
3458 $ cd multiroots
3458 $ cat <<EOF > .hg/hgrc
3459 $ cat <<EOF > .hg/hgrc
3459 > [ui]
3460 > [ui]
3460 > logtemplate = '{rev} {desc}\n\n'
3461 > logtemplate = '{rev} {desc}\n\n'
3461 > EOF
3462 > EOF
3462
3463
3463 $ touch foo
3464 $ touch foo
3464 $ hg ci -Aqm foo
3465 $ hg ci -Aqm foo
3465 $ hg co -q null
3466 $ hg co -q null
3466 $ touch bar
3467 $ touch bar
3467 $ hg ci -Aqm bar
3468 $ hg ci -Aqm bar
3468
3469
3469 $ hg log -Gr null:
3470 $ hg log -Gr null:
3470 @ 1 bar
3471 @ 1 bar
3471 |
3472 |
3472 | o 0 foo
3473 | o 0 foo
3473 |/
3474 |/
3474 o -1
3475 o -1
3475
3476
3476 $ hg log -Gr null+0
3477 $ hg log -Gr null+0
3477 o 0 foo
3478 o 0 foo
3478 |
3479 |
3479 o -1
3480 o -1
3480
3481
3481 $ hg log -Gr null+1
3482 $ hg log -Gr null+1
3482 @ 1 bar
3483 @ 1 bar
3483 |
3484 |
3484 o -1
3485 o -1
3485
3486
3486
3487
3487 $ cd ..
3488 $ cd ..
@@ -1,2841 +1,2841 b''
1 $ HGENCODING=utf-8
1 $ HGENCODING=utf-8
2 $ export HGENCODING
2 $ export HGENCODING
3 $ cat > testrevset.py << EOF
3 $ cat > testrevset.py << EOF
4 > import mercurial.revset
4 > import mercurial.revset
5 >
5 >
6 > baseset = mercurial.revset.baseset
6 > baseset = mercurial.revset.baseset
7 >
7 >
8 > def r3232(repo, subset, x):
8 > def r3232(repo, subset, x):
9 > """"simple revset that return [3,2,3,2]
9 > """"simple revset that return [3,2,3,2]
10 >
10 >
11 > revisions duplicated on purpose.
11 > revisions duplicated on purpose.
12 > """
12 > """
13 > if 3 not in subset:
13 > if 3 not in subset:
14 > if 2 in subset:
14 > if 2 in subset:
15 > return baseset([2,2])
15 > return baseset([2,2])
16 > return baseset()
16 > return baseset()
17 > return baseset([3,3,2,2])
17 > return baseset([3,3,2,2])
18 >
18 >
19 > mercurial.revset.symbols[b'r3232'] = r3232
19 > mercurial.revset.symbols[b'r3232'] = r3232
20 > EOF
20 > EOF
21 $ cat >> $HGRCPATH << EOF
21 $ cat >> $HGRCPATH << EOF
22 > [extensions]
22 > [extensions]
23 > drawdag=$TESTDIR/drawdag.py
23 > drawdag=$TESTDIR/drawdag.py
24 > testrevset=$TESTTMP/testrevset.py
24 > testrevset=$TESTTMP/testrevset.py
25 > EOF
25 > EOF
26
26
27 $ try() {
27 $ try() {
28 > hg debugrevspec --debug "$@"
28 > hg debugrevspec --debug "$@"
29 > }
29 > }
30
30
31 $ log() {
31 $ log() {
32 > hg log --template '{rev}\n' -r "$1"
32 > hg log --template '{rev}\n' -r "$1"
33 > }
33 > }
34
34
35 extension to build '_intlist()' and '_hexlist()', which is necessary because
35 extension to build '_intlist()' and '_hexlist()', which is necessary because
36 these predicates use '\0' as a separator:
36 these predicates use '\0' as a separator:
37
37
38 $ cat <<EOF > debugrevlistspec.py
38 $ cat <<EOF > debugrevlistspec.py
39 > from __future__ import absolute_import
39 > from __future__ import absolute_import
40 > from mercurial import (
40 > from mercurial import (
41 > node as nodemod,
41 > node as nodemod,
42 > registrar,
42 > registrar,
43 > revset,
43 > revset,
44 > revsetlang,
44 > revsetlang,
45 > smartset,
46 > )
45 > )
46 > from mercurial.utils import stringutil
47 > cmdtable = {}
47 > cmdtable = {}
48 > command = registrar.command(cmdtable)
48 > command = registrar.command(cmdtable)
49 > @command(b'debugrevlistspec',
49 > @command(b'debugrevlistspec',
50 > [(b'', b'optimize', None, b'print parsed tree after optimizing'),
50 > [(b'', b'optimize', None, b'print parsed tree after optimizing'),
51 > (b'', b'bin', None, b'unhexlify arguments')])
51 > (b'', b'bin', None, b'unhexlify arguments')])
52 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
52 > def debugrevlistspec(ui, repo, fmt, *args, **opts):
53 > if opts['bin']:
53 > if opts['bin']:
54 > args = map(nodemod.bin, args)
54 > args = map(nodemod.bin, args)
55 > expr = revsetlang.formatspec(fmt, list(args))
55 > expr = revsetlang.formatspec(fmt, list(args))
56 > if ui.verbose:
56 > if ui.verbose:
57 > tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
57 > tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
58 > ui.note(revsetlang.prettyformat(tree), b"\n")
58 > ui.note(revsetlang.prettyformat(tree), b"\n")
59 > if opts["optimize"]:
59 > if opts["optimize"]:
60 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
60 > opttree = revsetlang.optimize(revsetlang.analyze(tree))
61 > ui.note(b"* optimized:\n", revsetlang.prettyformat(opttree),
61 > ui.note(b"* optimized:\n", revsetlang.prettyformat(opttree),
62 > b"\n")
62 > b"\n")
63 > func = revset.match(ui, expr, lookup=revset.lookupfn(repo))
63 > func = revset.match(ui, expr, lookup=revset.lookupfn(repo))
64 > revs = func(repo)
64 > revs = func(repo)
65 > if ui.verbose:
65 > if ui.verbose:
66 > ui.note(b"* set:\n", smartset.prettyformat(revs), b"\n")
66 > ui.note(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
67 > for c in revs:
67 > for c in revs:
68 > ui.write(b"%d\n" % c)
68 > ui.write(b"%d\n" % c)
69 > EOF
69 > EOF
70 $ cat <<EOF >> $HGRCPATH
70 $ cat <<EOF >> $HGRCPATH
71 > [extensions]
71 > [extensions]
72 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
72 > debugrevlistspec = $TESTTMP/debugrevlistspec.py
73 > EOF
73 > EOF
74 $ trylist() {
74 $ trylist() {
75 > hg debugrevlistspec --debug "$@"
75 > hg debugrevlistspec --debug "$@"
76 > }
76 > }
77
77
78 $ hg init repo
78 $ hg init repo
79 $ cd repo
79 $ cd repo
80
80
81 $ echo a > a
81 $ echo a > a
82 $ hg branch a
82 $ hg branch a
83 marked working directory as branch a
83 marked working directory as branch a
84 (branches are permanent and global, did you want a bookmark?)
84 (branches are permanent and global, did you want a bookmark?)
85 $ hg ci -Aqm0
85 $ hg ci -Aqm0
86
86
87 $ echo b > b
87 $ echo b > b
88 $ hg branch b
88 $ hg branch b
89 marked working directory as branch b
89 marked working directory as branch b
90 $ hg ci -Aqm1
90 $ hg ci -Aqm1
91
91
92 $ rm a
92 $ rm a
93 $ hg branch a-b-c-
93 $ hg branch a-b-c-
94 marked working directory as branch a-b-c-
94 marked working directory as branch a-b-c-
95 $ hg ci -Aqm2 -u Bob
95 $ hg ci -Aqm2 -u Bob
96
96
97 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
97 $ hg log -r "extra('branch', 'a-b-c-')" --template '{rev}\n'
98 2
98 2
99 $ hg log -r "extra('branch')" --template '{rev}\n'
99 $ hg log -r "extra('branch')" --template '{rev}\n'
100 0
100 0
101 1
101 1
102 2
102 2
103 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
103 $ hg log -r "extra('branch', 're:a')" --template '{rev} {branch}\n'
104 0 a
104 0 a
105 2 a-b-c-
105 2 a-b-c-
106
106
107 $ hg co 1
107 $ hg co 1
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 $ hg branch +a+b+c+
109 $ hg branch +a+b+c+
110 marked working directory as branch +a+b+c+
110 marked working directory as branch +a+b+c+
111 $ hg ci -Aqm3
111 $ hg ci -Aqm3
112
112
113 $ hg co 2 # interleave
113 $ hg co 2 # interleave
114 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
114 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
115 $ echo bb > b
115 $ echo bb > b
116 $ hg branch -- -a-b-c-
116 $ hg branch -- -a-b-c-
117 marked working directory as branch -a-b-c-
117 marked working directory as branch -a-b-c-
118 $ hg ci -Aqm4 -d "May 12 2005"
118 $ hg ci -Aqm4 -d "May 12 2005"
119
119
120 $ hg co 3
120 $ hg co 3
121 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 $ hg branch !a/b/c/
122 $ hg branch !a/b/c/
123 marked working directory as branch !a/b/c/
123 marked working directory as branch !a/b/c/
124 $ hg ci -Aqm"5 bug"
124 $ hg ci -Aqm"5 bug"
125
125
126 $ hg merge 4
126 $ hg merge 4
127 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
127 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
128 (branch merge, don't forget to commit)
128 (branch merge, don't forget to commit)
129 $ hg branch _a_b_c_
129 $ hg branch _a_b_c_
130 marked working directory as branch _a_b_c_
130 marked working directory as branch _a_b_c_
131 $ hg ci -Aqm"6 issue619"
131 $ hg ci -Aqm"6 issue619"
132
132
133 $ hg branch .a.b.c.
133 $ hg branch .a.b.c.
134 marked working directory as branch .a.b.c.
134 marked working directory as branch .a.b.c.
135 $ hg ci -Aqm7
135 $ hg ci -Aqm7
136
136
137 $ hg branch all
137 $ hg branch all
138 marked working directory as branch all
138 marked working directory as branch all
139
139
140 $ hg co 4
140 $ hg co 4
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 $ hg branch Γ©
142 $ hg branch Γ©
143 marked working directory as branch \xc3\xa9 (esc)
143 marked working directory as branch \xc3\xa9 (esc)
144 $ hg ci -Aqm9
144 $ hg ci -Aqm9
145
145
146 $ hg tag -r6 1.0
146 $ hg tag -r6 1.0
147 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
147 $ hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
148
148
149 $ hg clone --quiet -U -r 7 . ../remote1
149 $ hg clone --quiet -U -r 7 . ../remote1
150 $ hg clone --quiet -U -r 8 . ../remote2
150 $ hg clone --quiet -U -r 8 . ../remote2
151 $ echo "[paths]" >> .hg/hgrc
151 $ echo "[paths]" >> .hg/hgrc
152 $ echo "default = ../remote1" >> .hg/hgrc
152 $ echo "default = ../remote1" >> .hg/hgrc
153
153
154 trivial
154 trivial
155
155
156 $ try 0:1
156 $ try 0:1
157 (range
157 (range
158 (symbol '0')
158 (symbol '0')
159 (symbol '1'))
159 (symbol '1'))
160 * set:
160 * set:
161 <spanset+ 0:2>
161 <spanset+ 0:2>
162 0
162 0
163 1
163 1
164 $ try --optimize :
164 $ try --optimize :
165 (rangeall
165 (rangeall
166 None)
166 None)
167 * optimized:
167 * optimized:
168 (rangeall
168 (rangeall
169 None)
169 None)
170 * set:
170 * set:
171 <spanset+ 0:10>
171 <spanset+ 0:10>
172 0
172 0
173 1
173 1
174 2
174 2
175 3
175 3
176 4
176 4
177 5
177 5
178 6
178 6
179 7
179 7
180 8
180 8
181 9
181 9
182 $ try 3::6
182 $ try 3::6
183 (dagrange
183 (dagrange
184 (symbol '3')
184 (symbol '3')
185 (symbol '6'))
185 (symbol '6'))
186 * set:
186 * set:
187 <baseset+ [3, 5, 6]>
187 <baseset+ [3, 5, 6]>
188 3
188 3
189 5
189 5
190 6
190 6
191 $ try '0|1|2'
191 $ try '0|1|2'
192 (or
192 (or
193 (list
193 (list
194 (symbol '0')
194 (symbol '0')
195 (symbol '1')
195 (symbol '1')
196 (symbol '2')))
196 (symbol '2')))
197 * set:
197 * set:
198 <baseset [0, 1, 2]>
198 <baseset [0, 1, 2]>
199 0
199 0
200 1
200 1
201 2
201 2
202
202
203 names that should work without quoting
203 names that should work without quoting
204
204
205 $ try a
205 $ try a
206 (symbol 'a')
206 (symbol 'a')
207 * set:
207 * set:
208 <baseset [0]>
208 <baseset [0]>
209 0
209 0
210 $ try b-a
210 $ try b-a
211 (minus
211 (minus
212 (symbol 'b')
212 (symbol 'b')
213 (symbol 'a'))
213 (symbol 'a'))
214 * set:
214 * set:
215 <filteredset
215 <filteredset
216 <baseset [1]>,
216 <baseset [1]>,
217 <not
217 <not
218 <baseset [0]>>>
218 <baseset [0]>>>
219 1
219 1
220 $ try _a_b_c_
220 $ try _a_b_c_
221 (symbol '_a_b_c_')
221 (symbol '_a_b_c_')
222 * set:
222 * set:
223 <baseset [6]>
223 <baseset [6]>
224 6
224 6
225 $ try _a_b_c_-a
225 $ try _a_b_c_-a
226 (minus
226 (minus
227 (symbol '_a_b_c_')
227 (symbol '_a_b_c_')
228 (symbol 'a'))
228 (symbol 'a'))
229 * set:
229 * set:
230 <filteredset
230 <filteredset
231 <baseset [6]>,
231 <baseset [6]>,
232 <not
232 <not
233 <baseset [0]>>>
233 <baseset [0]>>>
234 6
234 6
235 $ try .a.b.c.
235 $ try .a.b.c.
236 (symbol '.a.b.c.')
236 (symbol '.a.b.c.')
237 * set:
237 * set:
238 <baseset [7]>
238 <baseset [7]>
239 7
239 7
240 $ try .a.b.c.-a
240 $ try .a.b.c.-a
241 (minus
241 (minus
242 (symbol '.a.b.c.')
242 (symbol '.a.b.c.')
243 (symbol 'a'))
243 (symbol 'a'))
244 * set:
244 * set:
245 <filteredset
245 <filteredset
246 <baseset [7]>,
246 <baseset [7]>,
247 <not
247 <not
248 <baseset [0]>>>
248 <baseset [0]>>>
249 7
249 7
250
250
251 names that should be caught by fallback mechanism
251 names that should be caught by fallback mechanism
252
252
253 $ try -- '-a-b-c-'
253 $ try -- '-a-b-c-'
254 (symbol '-a-b-c-')
254 (symbol '-a-b-c-')
255 * set:
255 * set:
256 <baseset [4]>
256 <baseset [4]>
257 4
257 4
258 $ log -a-b-c-
258 $ log -a-b-c-
259 4
259 4
260 $ try '+a+b+c+'
260 $ try '+a+b+c+'
261 (symbol '+a+b+c+')
261 (symbol '+a+b+c+')
262 * set:
262 * set:
263 <baseset [3]>
263 <baseset [3]>
264 3
264 3
265 $ try '+a+b+c+:'
265 $ try '+a+b+c+:'
266 (rangepost
266 (rangepost
267 (symbol '+a+b+c+'))
267 (symbol '+a+b+c+'))
268 * set:
268 * set:
269 <spanset+ 3:10>
269 <spanset+ 3:10>
270 3
270 3
271 4
271 4
272 5
272 5
273 6
273 6
274 7
274 7
275 8
275 8
276 9
276 9
277 $ try ':+a+b+c+'
277 $ try ':+a+b+c+'
278 (rangepre
278 (rangepre
279 (symbol '+a+b+c+'))
279 (symbol '+a+b+c+'))
280 * set:
280 * set:
281 <spanset+ 0:4>
281 <spanset+ 0:4>
282 0
282 0
283 1
283 1
284 2
284 2
285 3
285 3
286 $ try -- '-a-b-c-:+a+b+c+'
286 $ try -- '-a-b-c-:+a+b+c+'
287 (range
287 (range
288 (symbol '-a-b-c-')
288 (symbol '-a-b-c-')
289 (symbol '+a+b+c+'))
289 (symbol '+a+b+c+'))
290 * set:
290 * set:
291 <spanset- 3:5>
291 <spanset- 3:5>
292 4
292 4
293 3
293 3
294 $ log '-a-b-c-:+a+b+c+'
294 $ log '-a-b-c-:+a+b+c+'
295 4
295 4
296 3
296 3
297
297
298 $ try -- -a-b-c--a # complains
298 $ try -- -a-b-c--a # complains
299 (minus
299 (minus
300 (minus
300 (minus
301 (minus
301 (minus
302 (negate
302 (negate
303 (symbol 'a'))
303 (symbol 'a'))
304 (symbol 'b'))
304 (symbol 'b'))
305 (symbol 'c'))
305 (symbol 'c'))
306 (negate
306 (negate
307 (symbol 'a')))
307 (symbol 'a')))
308 abort: unknown revision '-a'!
308 abort: unknown revision '-a'!
309 [255]
309 [255]
310 $ try Γ©
310 $ try Γ©
311 (symbol '\xc3\xa9')
311 (symbol '\xc3\xa9')
312 * set:
312 * set:
313 <baseset [9]>
313 <baseset [9]>
314 9
314 9
315
315
316 no quoting needed
316 no quoting needed
317
317
318 $ log ::a-b-c-
318 $ log ::a-b-c-
319 0
319 0
320 1
320 1
321 2
321 2
322
322
323 quoting needed
323 quoting needed
324
324
325 $ try '"-a-b-c-"-a'
325 $ try '"-a-b-c-"-a'
326 (minus
326 (minus
327 (string '-a-b-c-')
327 (string '-a-b-c-')
328 (symbol 'a'))
328 (symbol 'a'))
329 * set:
329 * set:
330 <filteredset
330 <filteredset
331 <baseset [4]>,
331 <baseset [4]>,
332 <not
332 <not
333 <baseset [0]>>>
333 <baseset [0]>>>
334 4
334 4
335
335
336 $ log '1 or 2'
336 $ log '1 or 2'
337 1
337 1
338 2
338 2
339 $ log '1|2'
339 $ log '1|2'
340 1
340 1
341 2
341 2
342 $ log '1 and 2'
342 $ log '1 and 2'
343 $ log '1&2'
343 $ log '1&2'
344 $ try '1&2|3' # precedence - and is higher
344 $ try '1&2|3' # precedence - and is higher
345 (or
345 (or
346 (list
346 (list
347 (and
347 (and
348 (symbol '1')
348 (symbol '1')
349 (symbol '2'))
349 (symbol '2'))
350 (symbol '3')))
350 (symbol '3')))
351 * set:
351 * set:
352 <addset
352 <addset
353 <baseset []>,
353 <baseset []>,
354 <baseset [3]>>
354 <baseset [3]>>
355 3
355 3
356 $ try '1|2&3'
356 $ try '1|2&3'
357 (or
357 (or
358 (list
358 (list
359 (symbol '1')
359 (symbol '1')
360 (and
360 (and
361 (symbol '2')
361 (symbol '2')
362 (symbol '3'))))
362 (symbol '3'))))
363 * set:
363 * set:
364 <addset
364 <addset
365 <baseset [1]>,
365 <baseset [1]>,
366 <baseset []>>
366 <baseset []>>
367 1
367 1
368 $ try '1&2&3' # associativity
368 $ try '1&2&3' # associativity
369 (and
369 (and
370 (and
370 (and
371 (symbol '1')
371 (symbol '1')
372 (symbol '2'))
372 (symbol '2'))
373 (symbol '3'))
373 (symbol '3'))
374 * set:
374 * set:
375 <baseset []>
375 <baseset []>
376 $ try '1|(2|3)'
376 $ try '1|(2|3)'
377 (or
377 (or
378 (list
378 (list
379 (symbol '1')
379 (symbol '1')
380 (group
380 (group
381 (or
381 (or
382 (list
382 (list
383 (symbol '2')
383 (symbol '2')
384 (symbol '3'))))))
384 (symbol '3'))))))
385 * set:
385 * set:
386 <addset
386 <addset
387 <baseset [1]>,
387 <baseset [1]>,
388 <baseset [2, 3]>>
388 <baseset [2, 3]>>
389 1
389 1
390 2
390 2
391 3
391 3
392 $ log '1.0' # tag
392 $ log '1.0' # tag
393 6
393 6
394 $ log 'a' # branch
394 $ log 'a' # branch
395 0
395 0
396 $ log '2785f51ee'
396 $ log '2785f51ee'
397 0
397 0
398 $ log 'date(2005)'
398 $ log 'date(2005)'
399 4
399 4
400 $ log 'date(this is a test)'
400 $ log 'date(this is a test)'
401 hg: parse error at 10: unexpected token: symbol
401 hg: parse error at 10: unexpected token: symbol
402 (date(this is a test)
402 (date(this is a test)
403 ^ here)
403 ^ here)
404 [255]
404 [255]
405 $ log 'date()'
405 $ log 'date()'
406 hg: parse error: date requires a string
406 hg: parse error: date requires a string
407 [255]
407 [255]
408 $ log 'date'
408 $ log 'date'
409 abort: unknown revision 'date'!
409 abort: unknown revision 'date'!
410 [255]
410 [255]
411 $ log 'date('
411 $ log 'date('
412 hg: parse error at 5: not a prefix: end
412 hg: parse error at 5: not a prefix: end
413 (date(
413 (date(
414 ^ here)
414 ^ here)
415 [255]
415 [255]
416 $ log 'date("\xy")'
416 $ log 'date("\xy")'
417 hg: parse error: invalid \x escape* (glob)
417 hg: parse error: invalid \x escape* (glob)
418 [255]
418 [255]
419 $ log 'date(tip)'
419 $ log 'date(tip)'
420 hg: parse error: invalid date: 'tip'
420 hg: parse error: invalid date: 'tip'
421 [255]
421 [255]
422 $ log '0:date'
422 $ log '0:date'
423 abort: unknown revision 'date'!
423 abort: unknown revision 'date'!
424 [255]
424 [255]
425 $ log '::"date"'
425 $ log '::"date"'
426 abort: unknown revision 'date'!
426 abort: unknown revision 'date'!
427 [255]
427 [255]
428 $ hg book date -r 4
428 $ hg book date -r 4
429 $ log '0:date'
429 $ log '0:date'
430 0
430 0
431 1
431 1
432 2
432 2
433 3
433 3
434 4
434 4
435 $ log '::date'
435 $ log '::date'
436 0
436 0
437 1
437 1
438 2
438 2
439 4
439 4
440 $ log '::"date"'
440 $ log '::"date"'
441 0
441 0
442 1
442 1
443 2
443 2
444 4
444 4
445 $ log 'date(2005) and 1::'
445 $ log 'date(2005) and 1::'
446 4
446 4
447 $ hg book -d date
447 $ hg book -d date
448
448
449 function name should be a symbol
449 function name should be a symbol
450
450
451 $ log '"date"(2005)'
451 $ log '"date"(2005)'
452 hg: parse error: not a symbol
452 hg: parse error: not a symbol
453 [255]
453 [255]
454
454
455 keyword arguments
455 keyword arguments
456
456
457 $ log 'extra(branch, value=a)'
457 $ log 'extra(branch, value=a)'
458 0
458 0
459
459
460 $ log 'extra(branch, a, b)'
460 $ log 'extra(branch, a, b)'
461 hg: parse error: extra takes at most 2 positional arguments
461 hg: parse error: extra takes at most 2 positional arguments
462 [255]
462 [255]
463 $ log 'extra(a, label=b)'
463 $ log 'extra(a, label=b)'
464 hg: parse error: extra got multiple values for keyword argument 'label'
464 hg: parse error: extra got multiple values for keyword argument 'label'
465 [255]
465 [255]
466 $ log 'extra(label=branch, default)'
466 $ log 'extra(label=branch, default)'
467 hg: parse error: extra got an invalid argument
467 hg: parse error: extra got an invalid argument
468 [255]
468 [255]
469 $ log 'extra(branch, foo+bar=baz)'
469 $ log 'extra(branch, foo+bar=baz)'
470 hg: parse error: extra got an invalid argument
470 hg: parse error: extra got an invalid argument
471 [255]
471 [255]
472 $ log 'extra(unknown=branch)'
472 $ log 'extra(unknown=branch)'
473 hg: parse error: extra got an unexpected keyword argument 'unknown'
473 hg: parse error: extra got an unexpected keyword argument 'unknown'
474 [255]
474 [255]
475
475
476 $ try 'foo=bar|baz'
476 $ try 'foo=bar|baz'
477 (keyvalue
477 (keyvalue
478 (symbol 'foo')
478 (symbol 'foo')
479 (or
479 (or
480 (list
480 (list
481 (symbol 'bar')
481 (symbol 'bar')
482 (symbol 'baz'))))
482 (symbol 'baz'))))
483 hg: parse error: can't use a key-value pair in this context
483 hg: parse error: can't use a key-value pair in this context
484 [255]
484 [255]
485
485
486 right-hand side should be optimized recursively
486 right-hand side should be optimized recursively
487
487
488 $ try --optimize 'foo=(not public())'
488 $ try --optimize 'foo=(not public())'
489 (keyvalue
489 (keyvalue
490 (symbol 'foo')
490 (symbol 'foo')
491 (group
491 (group
492 (not
492 (not
493 (func
493 (func
494 (symbol 'public')
494 (symbol 'public')
495 None))))
495 None))))
496 * optimized:
496 * optimized:
497 (keyvalue
497 (keyvalue
498 (symbol 'foo')
498 (symbol 'foo')
499 (func
499 (func
500 (symbol '_notpublic')
500 (symbol '_notpublic')
501 None))
501 None))
502 hg: parse error: can't use a key-value pair in this context
502 hg: parse error: can't use a key-value pair in this context
503 [255]
503 [255]
504
504
505 relation-subscript operator has the highest binding strength (as function call):
505 relation-subscript operator has the highest binding strength (as function call):
506
506
507 $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]'
507 $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]'
508 * parsed:
508 * parsed:
509 (range
509 (range
510 (symbol 'tip')
510 (symbol 'tip')
511 (relsubscript
511 (relsubscript
512 (parentpost
512 (parentpost
513 (symbol 'tip'))
513 (symbol 'tip'))
514 (symbol 'generations')
514 (symbol 'generations')
515 (negate
515 (negate
516 (symbol '1'))))
516 (symbol '1'))))
517 9
517 9
518 8
518 8
519 7
519 7
520 6
520 6
521 5
521 5
522 4
522 4
523
523
524 $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
524 $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
525 * parsed:
525 * parsed:
526 (not
526 (not
527 (relsubscript
527 (relsubscript
528 (func
528 (func
529 (symbol 'public')
529 (symbol 'public')
530 None)
530 None)
531 (symbol 'generations')
531 (symbol 'generations')
532 (symbol '0')))
532 (symbol '0')))
533
533
534 left-hand side of relation-subscript operator should be optimized recursively:
534 left-hand side of relation-subscript operator should be optimized recursively:
535
535
536 $ hg debugrevspec -p analyzed -p optimized --no-show-revs \
536 $ hg debugrevspec -p analyzed -p optimized --no-show-revs \
537 > '(not public())#generations[0]'
537 > '(not public())#generations[0]'
538 * analyzed:
538 * analyzed:
539 (relsubscript
539 (relsubscript
540 (not
540 (not
541 (func
541 (func
542 (symbol 'public')
542 (symbol 'public')
543 None))
543 None))
544 (symbol 'generations')
544 (symbol 'generations')
545 (symbol '0'))
545 (symbol '0'))
546 * optimized:
546 * optimized:
547 (relsubscript
547 (relsubscript
548 (func
548 (func
549 (symbol '_notpublic')
549 (symbol '_notpublic')
550 None)
550 None)
551 (symbol 'generations')
551 (symbol 'generations')
552 (symbol '0'))
552 (symbol '0'))
553
553
554 resolution of subscript and relation-subscript ternary operators:
554 resolution of subscript and relation-subscript ternary operators:
555
555
556 $ hg debugrevspec -p analyzed 'tip[0]'
556 $ hg debugrevspec -p analyzed 'tip[0]'
557 * analyzed:
557 * analyzed:
558 (subscript
558 (subscript
559 (symbol 'tip')
559 (symbol 'tip')
560 (symbol '0'))
560 (symbol '0'))
561 hg: parse error: can't use a subscript in this context
561 hg: parse error: can't use a subscript in this context
562 [255]
562 [255]
563
563
564 $ hg debugrevspec -p analyzed 'tip#rel[0]'
564 $ hg debugrevspec -p analyzed 'tip#rel[0]'
565 * analyzed:
565 * analyzed:
566 (relsubscript
566 (relsubscript
567 (symbol 'tip')
567 (symbol 'tip')
568 (symbol 'rel')
568 (symbol 'rel')
569 (symbol '0'))
569 (symbol '0'))
570 hg: parse error: unknown identifier: rel
570 hg: parse error: unknown identifier: rel
571 [255]
571 [255]
572
572
573 $ hg debugrevspec -p analyzed '(tip#rel)[0]'
573 $ hg debugrevspec -p analyzed '(tip#rel)[0]'
574 * analyzed:
574 * analyzed:
575 (subscript
575 (subscript
576 (relation
576 (relation
577 (symbol 'tip')
577 (symbol 'tip')
578 (symbol 'rel'))
578 (symbol 'rel'))
579 (symbol '0'))
579 (symbol '0'))
580 hg: parse error: can't use a subscript in this context
580 hg: parse error: can't use a subscript in this context
581 [255]
581 [255]
582
582
583 $ hg debugrevspec -p analyzed 'tip#rel[0][1]'
583 $ hg debugrevspec -p analyzed 'tip#rel[0][1]'
584 * analyzed:
584 * analyzed:
585 (subscript
585 (subscript
586 (relsubscript
586 (relsubscript
587 (symbol 'tip')
587 (symbol 'tip')
588 (symbol 'rel')
588 (symbol 'rel')
589 (symbol '0'))
589 (symbol '0'))
590 (symbol '1'))
590 (symbol '1'))
591 hg: parse error: can't use a subscript in this context
591 hg: parse error: can't use a subscript in this context
592 [255]
592 [255]
593
593
594 $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'
594 $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'
595 * analyzed:
595 * analyzed:
596 (relsubscript
596 (relsubscript
597 (relation
597 (relation
598 (symbol 'tip')
598 (symbol 'tip')
599 (symbol 'rel0'))
599 (symbol 'rel0'))
600 (symbol 'rel1')
600 (symbol 'rel1')
601 (symbol '1'))
601 (symbol '1'))
602 hg: parse error: unknown identifier: rel1
602 hg: parse error: unknown identifier: rel1
603 [255]
603 [255]
604
604
605 $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
605 $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
606 * analyzed:
606 * analyzed:
607 (relsubscript
607 (relsubscript
608 (relsubscript
608 (relsubscript
609 (symbol 'tip')
609 (symbol 'tip')
610 (symbol 'rel0')
610 (symbol 'rel0')
611 (symbol '0'))
611 (symbol '0'))
612 (symbol 'rel1')
612 (symbol 'rel1')
613 (symbol '1'))
613 (symbol '1'))
614 hg: parse error: unknown identifier: rel1
614 hg: parse error: unknown identifier: rel1
615 [255]
615 [255]
616
616
617 parse errors of relation, subscript and relation-subscript operators:
617 parse errors of relation, subscript and relation-subscript operators:
618
618
619 $ hg debugrevspec '[0]'
619 $ hg debugrevspec '[0]'
620 hg: parse error at 0: not a prefix: [
620 hg: parse error at 0: not a prefix: [
621 ([0]
621 ([0]
622 ^ here)
622 ^ here)
623 [255]
623 [255]
624 $ hg debugrevspec '.#'
624 $ hg debugrevspec '.#'
625 hg: parse error at 2: not a prefix: end
625 hg: parse error at 2: not a prefix: end
626 (.#
626 (.#
627 ^ here)
627 ^ here)
628 [255]
628 [255]
629 $ hg debugrevspec '#rel'
629 $ hg debugrevspec '#rel'
630 hg: parse error at 0: not a prefix: #
630 hg: parse error at 0: not a prefix: #
631 (#rel
631 (#rel
632 ^ here)
632 ^ here)
633 [255]
633 [255]
634 $ hg debugrevspec '.#rel[0'
634 $ hg debugrevspec '.#rel[0'
635 hg: parse error at 7: unexpected token: end
635 hg: parse error at 7: unexpected token: end
636 (.#rel[0
636 (.#rel[0
637 ^ here)
637 ^ here)
638 [255]
638 [255]
639 $ hg debugrevspec '.]'
639 $ hg debugrevspec '.]'
640 hg: parse error at 1: invalid token
640 hg: parse error at 1: invalid token
641 (.]
641 (.]
642 ^ here)
642 ^ here)
643 [255]
643 [255]
644
644
645 $ hg debugrevspec '.#generations[a]'
645 $ hg debugrevspec '.#generations[a]'
646 hg: parse error: relation subscript must be an integer
646 hg: parse error: relation subscript must be an integer
647 [255]
647 [255]
648 $ hg debugrevspec '.#generations[1-2]'
648 $ hg debugrevspec '.#generations[1-2]'
649 hg: parse error: relation subscript must be an integer
649 hg: parse error: relation subscript must be an integer
650 [255]
650 [255]
651
651
652 parsed tree at stages:
652 parsed tree at stages:
653
653
654 $ hg debugrevspec -p all '()'
654 $ hg debugrevspec -p all '()'
655 * parsed:
655 * parsed:
656 (group
656 (group
657 None)
657 None)
658 * expanded:
658 * expanded:
659 (group
659 (group
660 None)
660 None)
661 * concatenated:
661 * concatenated:
662 (group
662 (group
663 None)
663 None)
664 * analyzed:
664 * analyzed:
665 None
665 None
666 * optimized:
666 * optimized:
667 None
667 None
668 hg: parse error: missing argument
668 hg: parse error: missing argument
669 [255]
669 [255]
670
670
671 $ hg debugrevspec --no-optimized -p all '()'
671 $ hg debugrevspec --no-optimized -p all '()'
672 * parsed:
672 * parsed:
673 (group
673 (group
674 None)
674 None)
675 * expanded:
675 * expanded:
676 (group
676 (group
677 None)
677 None)
678 * concatenated:
678 * concatenated:
679 (group
679 (group
680 None)
680 None)
681 * analyzed:
681 * analyzed:
682 None
682 None
683 hg: parse error: missing argument
683 hg: parse error: missing argument
684 [255]
684 [255]
685
685
686 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
686 $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'
687 * parsed:
687 * parsed:
688 (minus
688 (minus
689 (group
689 (group
690 (or
690 (or
691 (list
691 (list
692 (symbol '0')
692 (symbol '0')
693 (symbol '1'))))
693 (symbol '1'))))
694 (symbol '1'))
694 (symbol '1'))
695 * analyzed:
695 * analyzed:
696 (and
696 (and
697 (or
697 (or
698 (list
698 (list
699 (symbol '0')
699 (symbol '0')
700 (symbol '1')))
700 (symbol '1')))
701 (not
701 (not
702 (symbol '1')))
702 (symbol '1')))
703 * optimized:
703 * optimized:
704 (difference
704 (difference
705 (func
705 (func
706 (symbol '_list')
706 (symbol '_list')
707 (string '0\x001'))
707 (string '0\x001'))
708 (symbol '1'))
708 (symbol '1'))
709 0
709 0
710
710
711 $ hg debugrevspec -p unknown '0'
711 $ hg debugrevspec -p unknown '0'
712 abort: invalid stage name: unknown
712 abort: invalid stage name: unknown
713 [255]
713 [255]
714
714
715 $ hg debugrevspec -p all --optimize '0'
715 $ hg debugrevspec -p all --optimize '0'
716 abort: cannot use --optimize with --show-stage
716 abort: cannot use --optimize with --show-stage
717 [255]
717 [255]
718
718
719 verify optimized tree:
719 verify optimized tree:
720
720
721 $ hg debugrevspec --verify '0|1'
721 $ hg debugrevspec --verify '0|1'
722
722
723 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
723 $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
724 * analyzed:
724 * analyzed:
725 (and
725 (and
726 (func
726 (func
727 (symbol 'r3232')
727 (symbol 'r3232')
728 None)
728 None)
729 (symbol '2'))
729 (symbol '2'))
730 * optimized:
730 * optimized:
731 (andsmally
731 (andsmally
732 (func
732 (func
733 (symbol 'r3232')
733 (symbol 'r3232')
734 None)
734 None)
735 (symbol '2'))
735 (symbol '2'))
736 * analyzed set:
736 * analyzed set:
737 <baseset [2]>
737 <baseset [2]>
738 * optimized set:
738 * optimized set:
739 <baseset [2, 2]>
739 <baseset [2, 2]>
740 --- analyzed
740 --- analyzed
741 +++ optimized
741 +++ optimized
742 2
742 2
743 +2
743 +2
744 [1]
744 [1]
745
745
746 $ hg debugrevspec --no-optimized --verify-optimized '0'
746 $ hg debugrevspec --no-optimized --verify-optimized '0'
747 abort: cannot use --verify-optimized with --no-optimized
747 abort: cannot use --verify-optimized with --no-optimized
748 [255]
748 [255]
749
749
750 Test that symbols only get parsed as functions if there's an opening
750 Test that symbols only get parsed as functions if there's an opening
751 parenthesis.
751 parenthesis.
752
752
753 $ hg book only -r 9
753 $ hg book only -r 9
754 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
754 $ log 'only(only)' # Outer "only" is a function, inner "only" is the bookmark
755 8
755 8
756 9
756 9
757
757
758 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
758 ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
759 may be hidden (issue5385)
759 may be hidden (issue5385)
760
760
761 $ try -p parsed -p analyzed ':'
761 $ try -p parsed -p analyzed ':'
762 * parsed:
762 * parsed:
763 (rangeall
763 (rangeall
764 None)
764 None)
765 * analyzed:
765 * analyzed:
766 (rangeall
766 (rangeall
767 None)
767 None)
768 * set:
768 * set:
769 <spanset+ 0:10>
769 <spanset+ 0:10>
770 0
770 0
771 1
771 1
772 2
772 2
773 3
773 3
774 4
774 4
775 5
775 5
776 6
776 6
777 7
777 7
778 8
778 8
779 9
779 9
780 $ try -p analyzed ':1'
780 $ try -p analyzed ':1'
781 * analyzed:
781 * analyzed:
782 (rangepre
782 (rangepre
783 (symbol '1'))
783 (symbol '1'))
784 * set:
784 * set:
785 <spanset+ 0:2>
785 <spanset+ 0:2>
786 0
786 0
787 1
787 1
788 $ try -p analyzed ':(1|2)'
788 $ try -p analyzed ':(1|2)'
789 * analyzed:
789 * analyzed:
790 (rangepre
790 (rangepre
791 (or
791 (or
792 (list
792 (list
793 (symbol '1')
793 (symbol '1')
794 (symbol '2'))))
794 (symbol '2'))))
795 * set:
795 * set:
796 <spanset+ 0:3>
796 <spanset+ 0:3>
797 0
797 0
798 1
798 1
799 2
799 2
800 $ try -p analyzed ':(1&2)'
800 $ try -p analyzed ':(1&2)'
801 * analyzed:
801 * analyzed:
802 (rangepre
802 (rangepre
803 (and
803 (and
804 (symbol '1')
804 (symbol '1')
805 (symbol '2')))
805 (symbol '2')))
806 * set:
806 * set:
807 <baseset []>
807 <baseset []>
808
808
809 infix/suffix resolution of ^ operator (issue2884, issue5764):
809 infix/suffix resolution of ^ operator (issue2884, issue5764):
810
810
811 x^:y means (x^):y
811 x^:y means (x^):y
812
812
813 $ try '1^:2'
813 $ try '1^:2'
814 (range
814 (range
815 (parentpost
815 (parentpost
816 (symbol '1'))
816 (symbol '1'))
817 (symbol '2'))
817 (symbol '2'))
818 * set:
818 * set:
819 <spanset+ 0:3>
819 <spanset+ 0:3>
820 0
820 0
821 1
821 1
822 2
822 2
823
823
824 $ try '1^::2'
824 $ try '1^::2'
825 (dagrange
825 (dagrange
826 (parentpost
826 (parentpost
827 (symbol '1'))
827 (symbol '1'))
828 (symbol '2'))
828 (symbol '2'))
829 * set:
829 * set:
830 <baseset+ [0, 1, 2]>
830 <baseset+ [0, 1, 2]>
831 0
831 0
832 1
832 1
833 2
833 2
834
834
835 $ try '1^..2'
835 $ try '1^..2'
836 (dagrange
836 (dagrange
837 (parentpost
837 (parentpost
838 (symbol '1'))
838 (symbol '1'))
839 (symbol '2'))
839 (symbol '2'))
840 * set:
840 * set:
841 <baseset+ [0, 1, 2]>
841 <baseset+ [0, 1, 2]>
842 0
842 0
843 1
843 1
844 2
844 2
845
845
846 $ try '9^:'
846 $ try '9^:'
847 (rangepost
847 (rangepost
848 (parentpost
848 (parentpost
849 (symbol '9')))
849 (symbol '9')))
850 * set:
850 * set:
851 <spanset+ 8:10>
851 <spanset+ 8:10>
852 8
852 8
853 9
853 9
854
854
855 $ try '9^::'
855 $ try '9^::'
856 (dagrangepost
856 (dagrangepost
857 (parentpost
857 (parentpost
858 (symbol '9')))
858 (symbol '9')))
859 * set:
859 * set:
860 <generatorsetasc+>
860 <generatorsetasc+>
861 8
861 8
862 9
862 9
863
863
864 $ try '9^..'
864 $ try '9^..'
865 (dagrangepost
865 (dagrangepost
866 (parentpost
866 (parentpost
867 (symbol '9')))
867 (symbol '9')))
868 * set:
868 * set:
869 <generatorsetasc+>
869 <generatorsetasc+>
870 8
870 8
871 9
871 9
872
872
873 x^:y should be resolved before omitting group operators
873 x^:y should be resolved before omitting group operators
874
874
875 $ try '1^(:2)'
875 $ try '1^(:2)'
876 (parent
876 (parent
877 (symbol '1')
877 (symbol '1')
878 (group
878 (group
879 (rangepre
879 (rangepre
880 (symbol '2'))))
880 (symbol '2'))))
881 hg: parse error: ^ expects a number 0, 1, or 2
881 hg: parse error: ^ expects a number 0, 1, or 2
882 [255]
882 [255]
883
883
884 x^:y should be resolved recursively
884 x^:y should be resolved recursively
885
885
886 $ try 'sort(1^:2)'
886 $ try 'sort(1^:2)'
887 (func
887 (func
888 (symbol 'sort')
888 (symbol 'sort')
889 (range
889 (range
890 (parentpost
890 (parentpost
891 (symbol '1'))
891 (symbol '1'))
892 (symbol '2')))
892 (symbol '2')))
893 * set:
893 * set:
894 <spanset+ 0:3>
894 <spanset+ 0:3>
895 0
895 0
896 1
896 1
897 2
897 2
898
898
899 $ try '(3^:4)^:2'
899 $ try '(3^:4)^:2'
900 (range
900 (range
901 (parentpost
901 (parentpost
902 (group
902 (group
903 (range
903 (range
904 (parentpost
904 (parentpost
905 (symbol '3'))
905 (symbol '3'))
906 (symbol '4'))))
906 (symbol '4'))))
907 (symbol '2'))
907 (symbol '2'))
908 * set:
908 * set:
909 <spanset+ 0:3>
909 <spanset+ 0:3>
910 0
910 0
911 1
911 1
912 2
912 2
913
913
914 $ try '(3^::4)^::2'
914 $ try '(3^::4)^::2'
915 (dagrange
915 (dagrange
916 (parentpost
916 (parentpost
917 (group
917 (group
918 (dagrange
918 (dagrange
919 (parentpost
919 (parentpost
920 (symbol '3'))
920 (symbol '3'))
921 (symbol '4'))))
921 (symbol '4'))))
922 (symbol '2'))
922 (symbol '2'))
923 * set:
923 * set:
924 <baseset+ [0, 1, 2]>
924 <baseset+ [0, 1, 2]>
925 0
925 0
926 1
926 1
927 2
927 2
928
928
929 $ try '(9^:)^:'
929 $ try '(9^:)^:'
930 (rangepost
930 (rangepost
931 (parentpost
931 (parentpost
932 (group
932 (group
933 (rangepost
933 (rangepost
934 (parentpost
934 (parentpost
935 (symbol '9'))))))
935 (symbol '9'))))))
936 * set:
936 * set:
937 <spanset+ 4:10>
937 <spanset+ 4:10>
938 4
938 4
939 5
939 5
940 6
940 6
941 7
941 7
942 8
942 8
943 9
943 9
944
944
945 x^ in alias should also be resolved
945 x^ in alias should also be resolved
946
946
947 $ try 'A' --config 'revsetalias.A=1^:2'
947 $ try 'A' --config 'revsetalias.A=1^:2'
948 (symbol 'A')
948 (symbol 'A')
949 * expanded:
949 * expanded:
950 (range
950 (range
951 (parentpost
951 (parentpost
952 (symbol '1'))
952 (symbol '1'))
953 (symbol '2'))
953 (symbol '2'))
954 * set:
954 * set:
955 <spanset+ 0:3>
955 <spanset+ 0:3>
956 0
956 0
957 1
957 1
958 2
958 2
959
959
960 $ try 'A:2' --config 'revsetalias.A=1^'
960 $ try 'A:2' --config 'revsetalias.A=1^'
961 (range
961 (range
962 (symbol 'A')
962 (symbol 'A')
963 (symbol '2'))
963 (symbol '2'))
964 * expanded:
964 * expanded:
965 (range
965 (range
966 (parentpost
966 (parentpost
967 (symbol '1'))
967 (symbol '1'))
968 (symbol '2'))
968 (symbol '2'))
969 * set:
969 * set:
970 <spanset+ 0:3>
970 <spanset+ 0:3>
971 0
971 0
972 1
972 1
973 2
973 2
974
974
975 but not beyond the boundary of alias expansion, because the resolution should
975 but not beyond the boundary of alias expansion, because the resolution should
976 be made at the parsing stage
976 be made at the parsing stage
977
977
978 $ try '1^A' --config 'revsetalias.A=:2'
978 $ try '1^A' --config 'revsetalias.A=:2'
979 (parent
979 (parent
980 (symbol '1')
980 (symbol '1')
981 (symbol 'A'))
981 (symbol 'A'))
982 * expanded:
982 * expanded:
983 (parent
983 (parent
984 (symbol '1')
984 (symbol '1')
985 (rangepre
985 (rangepre
986 (symbol '2')))
986 (symbol '2')))
987 hg: parse error: ^ expects a number 0, 1, or 2
987 hg: parse error: ^ expects a number 0, 1, or 2
988 [255]
988 [255]
989
989
990 '::' itself isn't a valid expression
990 '::' itself isn't a valid expression
991
991
992 $ try '::'
992 $ try '::'
993 (dagrangeall
993 (dagrangeall
994 None)
994 None)
995 hg: parse error: can't use '::' in this context
995 hg: parse error: can't use '::' in this context
996 [255]
996 [255]
997
997
998 ancestor can accept 0 or more arguments
998 ancestor can accept 0 or more arguments
999
999
1000 $ log 'ancestor()'
1000 $ log 'ancestor()'
1001 $ log 'ancestor(1)'
1001 $ log 'ancestor(1)'
1002 1
1002 1
1003 $ log 'ancestor(4,5)'
1003 $ log 'ancestor(4,5)'
1004 1
1004 1
1005 $ log 'ancestor(4,5) and 4'
1005 $ log 'ancestor(4,5) and 4'
1006 $ log 'ancestor(0,0,1,3)'
1006 $ log 'ancestor(0,0,1,3)'
1007 0
1007 0
1008 $ log 'ancestor(3,1,5,3,5,1)'
1008 $ log 'ancestor(3,1,5,3,5,1)'
1009 1
1009 1
1010 $ log 'ancestor(0,1,3,5)'
1010 $ log 'ancestor(0,1,3,5)'
1011 0
1011 0
1012 $ log 'ancestor(1,2,3,4,5)'
1012 $ log 'ancestor(1,2,3,4,5)'
1013 1
1013 1
1014
1014
1015 test ancestors
1015 test ancestors
1016
1016
1017 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1017 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1018 @ 9
1018 @ 9
1019 o 8
1019 o 8
1020 | o 7
1020 | o 7
1021 | o 6
1021 | o 6
1022 |/|
1022 |/|
1023 | o 5
1023 | o 5
1024 o | 4
1024 o | 4
1025 | o 3
1025 | o 3
1026 o | 2
1026 o | 2
1027 |/
1027 |/
1028 o 1
1028 o 1
1029 o 0
1029 o 0
1030
1030
1031 $ log 'ancestors(5)'
1031 $ log 'ancestors(5)'
1032 0
1032 0
1033 1
1033 1
1034 3
1034 3
1035 5
1035 5
1036 $ log 'ancestor(ancestors(5))'
1036 $ log 'ancestor(ancestors(5))'
1037 0
1037 0
1038 $ log '::r3232()'
1038 $ log '::r3232()'
1039 0
1039 0
1040 1
1040 1
1041 2
1041 2
1042 3
1042 3
1043
1043
1044 test ancestors with depth limit
1044 test ancestors with depth limit
1045
1045
1046 (depth=0 selects the node itself)
1046 (depth=0 selects the node itself)
1047
1047
1048 $ log 'reverse(ancestors(9, depth=0))'
1048 $ log 'reverse(ancestors(9, depth=0))'
1049 9
1049 9
1050
1050
1051 (interleaved: '4' would be missing if heap queue were higher depth first)
1051 (interleaved: '4' would be missing if heap queue were higher depth first)
1052
1052
1053 $ log 'reverse(ancestors(8:9, depth=1))'
1053 $ log 'reverse(ancestors(8:9, depth=1))'
1054 9
1054 9
1055 8
1055 8
1056 4
1056 4
1057
1057
1058 (interleaved: '2' would be missing if heap queue were higher depth first)
1058 (interleaved: '2' would be missing if heap queue were higher depth first)
1059
1059
1060 $ log 'reverse(ancestors(7+8, depth=2))'
1060 $ log 'reverse(ancestors(7+8, depth=2))'
1061 8
1061 8
1062 7
1062 7
1063 6
1063 6
1064 5
1064 5
1065 4
1065 4
1066 2
1066 2
1067
1067
1068 (walk example above by separate queries)
1068 (walk example above by separate queries)
1069
1069
1070 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
1070 $ log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'
1071 8
1071 8
1072 4
1072 4
1073 2
1073 2
1074 7
1074 7
1075 6
1075 6
1076 5
1076 5
1077
1077
1078 (walk 2nd and 3rd ancestors)
1078 (walk 2nd and 3rd ancestors)
1079
1079
1080 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
1080 $ log 'reverse(ancestors(7, depth=3, startdepth=2))'
1081 5
1081 5
1082 4
1082 4
1083 3
1083 3
1084 2
1084 2
1085
1085
1086 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
1086 (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
1087
1087
1088 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
1088 $ log 'reverse(ancestors(7+8, depth=2, startdepth=2))'
1089 5
1089 5
1090 4
1090 4
1091 2
1091 2
1092
1092
1093 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
1093 (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
1094 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
1094 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
1095 multiple depths)
1095 multiple depths)
1096
1096
1097 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
1097 $ log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'
1098 5
1098 5
1099 2
1099 2
1100
1100
1101 test bad arguments passed to ancestors()
1101 test bad arguments passed to ancestors()
1102
1102
1103 $ log 'ancestors(., depth=-1)'
1103 $ log 'ancestors(., depth=-1)'
1104 hg: parse error: negative depth
1104 hg: parse error: negative depth
1105 [255]
1105 [255]
1106 $ log 'ancestors(., depth=foo)'
1106 $ log 'ancestors(., depth=foo)'
1107 hg: parse error: ancestors expects an integer depth
1107 hg: parse error: ancestors expects an integer depth
1108 [255]
1108 [255]
1109
1109
1110 test descendants
1110 test descendants
1111
1111
1112 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1112 $ hg log -G -T '{rev}\n' --config experimental.graphshorten=True
1113 @ 9
1113 @ 9
1114 o 8
1114 o 8
1115 | o 7
1115 | o 7
1116 | o 6
1116 | o 6
1117 |/|
1117 |/|
1118 | o 5
1118 | o 5
1119 o | 4
1119 o | 4
1120 | o 3
1120 | o 3
1121 o | 2
1121 o | 2
1122 |/
1122 |/
1123 o 1
1123 o 1
1124 o 0
1124 o 0
1125
1125
1126 (null is ultimate root and has optimized path)
1126 (null is ultimate root and has optimized path)
1127
1127
1128 $ log 'null:4 & descendants(null)'
1128 $ log 'null:4 & descendants(null)'
1129 -1
1129 -1
1130 0
1130 0
1131 1
1131 1
1132 2
1132 2
1133 3
1133 3
1134 4
1134 4
1135
1135
1136 (including merge)
1136 (including merge)
1137
1137
1138 $ log ':8 & descendants(2)'
1138 $ log ':8 & descendants(2)'
1139 2
1139 2
1140 4
1140 4
1141 6
1141 6
1142 7
1142 7
1143 8
1143 8
1144
1144
1145 (multiple roots)
1145 (multiple roots)
1146
1146
1147 $ log ':8 & descendants(2+5)'
1147 $ log ':8 & descendants(2+5)'
1148 2
1148 2
1149 4
1149 4
1150 5
1150 5
1151 6
1151 6
1152 7
1152 7
1153 8
1153 8
1154
1154
1155 test descendants with depth limit
1155 test descendants with depth limit
1156
1156
1157 (depth=0 selects the node itself)
1157 (depth=0 selects the node itself)
1158
1158
1159 $ log 'descendants(0, depth=0)'
1159 $ log 'descendants(0, depth=0)'
1160 0
1160 0
1161 $ log 'null: & descendants(null, depth=0)'
1161 $ log 'null: & descendants(null, depth=0)'
1162 -1
1162 -1
1163
1163
1164 (p2 = null should be ignored)
1164 (p2 = null should be ignored)
1165
1165
1166 $ log 'null: & descendants(null, depth=2)'
1166 $ log 'null: & descendants(null, depth=2)'
1167 -1
1167 -1
1168 0
1168 0
1169 1
1169 1
1170
1170
1171 (multiple paths: depth(6) = (2, 3))
1171 (multiple paths: depth(6) = (2, 3))
1172
1172
1173 $ log 'descendants(1+3, depth=2)'
1173 $ log 'descendants(1+3, depth=2)'
1174 1
1174 1
1175 2
1175 2
1176 3
1176 3
1177 4
1177 4
1178 5
1178 5
1179 6
1179 6
1180
1180
1181 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1181 (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
1182
1182
1183 $ log 'descendants(3+1, depth=2, startdepth=2)'
1183 $ log 'descendants(3+1, depth=2, startdepth=2)'
1184 4
1184 4
1185 5
1185 5
1186 6
1186 6
1187
1187
1188 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1188 (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
1189
1189
1190 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1190 $ log 'descendants(0+3+6, depth=3, startdepth=1)'
1191 1
1191 1
1192 2
1192 2
1193 3
1193 3
1194 4
1194 4
1195 5
1195 5
1196 6
1196 6
1197 7
1197 7
1198
1198
1199 (multiple depths: depth(6) = (0, 4), no match)
1199 (multiple depths: depth(6) = (0, 4), no match)
1200
1200
1201 $ log 'descendants(0+6, depth=3, startdepth=1)'
1201 $ log 'descendants(0+6, depth=3, startdepth=1)'
1202 1
1202 1
1203 2
1203 2
1204 3
1204 3
1205 4
1205 4
1206 5
1206 5
1207 7
1207 7
1208
1208
1209 test ancestors/descendants relation subscript:
1209 test ancestors/descendants relation subscript:
1210
1210
1211 $ log 'tip#generations[0]'
1211 $ log 'tip#generations[0]'
1212 9
1212 9
1213 $ log '.#generations[-1]'
1213 $ log '.#generations[-1]'
1214 8
1214 8
1215 $ log '.#g[(-1)]'
1215 $ log '.#g[(-1)]'
1216 8
1216 8
1217
1217
1218 $ hg debugrevspec -p parsed 'roots(:)#g[2]'
1218 $ hg debugrevspec -p parsed 'roots(:)#g[2]'
1219 * parsed:
1219 * parsed:
1220 (relsubscript
1220 (relsubscript
1221 (func
1221 (func
1222 (symbol 'roots')
1222 (symbol 'roots')
1223 (rangeall
1223 (rangeall
1224 None))
1224 None))
1225 (symbol 'g')
1225 (symbol 'g')
1226 (symbol '2'))
1226 (symbol '2'))
1227 2
1227 2
1228 3
1228 3
1229
1229
1230 test author
1230 test author
1231
1231
1232 $ log 'author(bob)'
1232 $ log 'author(bob)'
1233 2
1233 2
1234 $ log 'author("re:bob|test")'
1234 $ log 'author("re:bob|test")'
1235 0
1235 0
1236 1
1236 1
1237 2
1237 2
1238 3
1238 3
1239 4
1239 4
1240 5
1240 5
1241 6
1241 6
1242 7
1242 7
1243 8
1243 8
1244 9
1244 9
1245 $ log 'author(r"re:\S")'
1245 $ log 'author(r"re:\S")'
1246 0
1246 0
1247 1
1247 1
1248 2
1248 2
1249 3
1249 3
1250 4
1250 4
1251 5
1251 5
1252 6
1252 6
1253 7
1253 7
1254 8
1254 8
1255 9
1255 9
1256 $ log 'branch(Γ©)'
1256 $ log 'branch(Γ©)'
1257 8
1257 8
1258 9
1258 9
1259 $ log 'branch(a)'
1259 $ log 'branch(a)'
1260 0
1260 0
1261 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1261 $ hg log -r 'branch("re:a")' --template '{rev} {branch}\n'
1262 0 a
1262 0 a
1263 2 a-b-c-
1263 2 a-b-c-
1264 3 +a+b+c+
1264 3 +a+b+c+
1265 4 -a-b-c-
1265 4 -a-b-c-
1266 5 !a/b/c/
1266 5 !a/b/c/
1267 6 _a_b_c_
1267 6 _a_b_c_
1268 7 .a.b.c.
1268 7 .a.b.c.
1269 $ log 'children(ancestor(4,5))'
1269 $ log 'children(ancestor(4,5))'
1270 2
1270 2
1271 3
1271 3
1272
1272
1273 $ log 'children(4)'
1273 $ log 'children(4)'
1274 6
1274 6
1275 8
1275 8
1276 $ log 'children(null)'
1276 $ log 'children(null)'
1277 0
1277 0
1278
1278
1279 $ log 'closed()'
1279 $ log 'closed()'
1280 $ log 'contains(a)'
1280 $ log 'contains(a)'
1281 0
1281 0
1282 1
1282 1
1283 3
1283 3
1284 5
1284 5
1285 $ log 'contains("../repo/a")'
1285 $ log 'contains("../repo/a")'
1286 0
1286 0
1287 1
1287 1
1288 3
1288 3
1289 5
1289 5
1290 $ log 'desc(B)'
1290 $ log 'desc(B)'
1291 5
1291 5
1292 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1292 $ hg log -r 'desc(r"re:S?u")' --template "{rev} {desc|firstline}\n"
1293 5 5 bug
1293 5 5 bug
1294 6 6 issue619
1294 6 6 issue619
1295 $ log 'descendants(2 or 3)'
1295 $ log 'descendants(2 or 3)'
1296 2
1296 2
1297 3
1297 3
1298 4
1298 4
1299 5
1299 5
1300 6
1300 6
1301 7
1301 7
1302 8
1302 8
1303 9
1303 9
1304 $ log 'file("b*")'
1304 $ log 'file("b*")'
1305 1
1305 1
1306 4
1306 4
1307 $ log 'filelog("b")'
1307 $ log 'filelog("b")'
1308 1
1308 1
1309 4
1309 4
1310 $ log 'filelog("../repo/b")'
1310 $ log 'filelog("../repo/b")'
1311 1
1311 1
1312 4
1312 4
1313 $ log 'follow()'
1313 $ log 'follow()'
1314 0
1314 0
1315 1
1315 1
1316 2
1316 2
1317 4
1317 4
1318 8
1318 8
1319 9
1319 9
1320 $ log 'grep("issue\d+")'
1320 $ log 'grep("issue\d+")'
1321 6
1321 6
1322 $ try 'grep("(")' # invalid regular expression
1322 $ try 'grep("(")' # invalid regular expression
1323 (func
1323 (func
1324 (symbol 'grep')
1324 (symbol 'grep')
1325 (string '('))
1325 (string '('))
1326 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \),.*) (re)
1326 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \),.*) (re)
1327 [255]
1327 [255]
1328 $ try 'grep("\bissue\d+")'
1328 $ try 'grep("\bissue\d+")'
1329 (func
1329 (func
1330 (symbol 'grep')
1330 (symbol 'grep')
1331 (string '\x08issue\\d+'))
1331 (string '\x08issue\\d+'))
1332 * set:
1332 * set:
1333 <filteredset
1333 <filteredset
1334 <fullreposet+ 0:10>,
1334 <fullreposet+ 0:10>,
1335 <grep '\x08issue\\d+'>>
1335 <grep '\x08issue\\d+'>>
1336 $ try 'grep(r"\bissue\d+")'
1336 $ try 'grep(r"\bissue\d+")'
1337 (func
1337 (func
1338 (symbol 'grep')
1338 (symbol 'grep')
1339 (string '\\bissue\\d+'))
1339 (string '\\bissue\\d+'))
1340 * set:
1340 * set:
1341 <filteredset
1341 <filteredset
1342 <fullreposet+ 0:10>,
1342 <fullreposet+ 0:10>,
1343 <grep '\\bissue\\d+'>>
1343 <grep '\\bissue\\d+'>>
1344 6
1344 6
1345 $ try 'grep(r"\")'
1345 $ try 'grep(r"\")'
1346 hg: parse error at 7: unterminated string
1346 hg: parse error at 7: unterminated string
1347 (grep(r"\")
1347 (grep(r"\")
1348 ^ here)
1348 ^ here)
1349 [255]
1349 [255]
1350 $ log 'head()'
1350 $ log 'head()'
1351 0
1351 0
1352 1
1352 1
1353 2
1353 2
1354 3
1354 3
1355 4
1355 4
1356 5
1356 5
1357 6
1357 6
1358 7
1358 7
1359 9
1359 9
1360 $ log 'heads(6::)'
1360 $ log 'heads(6::)'
1361 7
1361 7
1362 $ log 'keyword(issue)'
1362 $ log 'keyword(issue)'
1363 6
1363 6
1364 $ log 'keyword("test a")'
1364 $ log 'keyword("test a")'
1365
1365
1366 Test first (=limit) and last
1366 Test first (=limit) and last
1367
1367
1368 $ log 'limit(head(), 1)'
1368 $ log 'limit(head(), 1)'
1369 0
1369 0
1370 $ log 'limit(author("re:bob|test"), 3, 5)'
1370 $ log 'limit(author("re:bob|test"), 3, 5)'
1371 5
1371 5
1372 6
1372 6
1373 7
1373 7
1374 $ log 'limit(author("re:bob|test"), offset=6)'
1374 $ log 'limit(author("re:bob|test"), offset=6)'
1375 6
1375 6
1376 $ log 'limit(author("re:bob|test"), offset=10)'
1376 $ log 'limit(author("re:bob|test"), offset=10)'
1377 $ log 'limit(all(), 1, -1)'
1377 $ log 'limit(all(), 1, -1)'
1378 hg: parse error: negative offset
1378 hg: parse error: negative offset
1379 [255]
1379 [255]
1380 $ log 'limit(all(), -1)'
1380 $ log 'limit(all(), -1)'
1381 hg: parse error: negative number to select
1381 hg: parse error: negative number to select
1382 [255]
1382 [255]
1383 $ log 'limit(all(), 0)'
1383 $ log 'limit(all(), 0)'
1384
1384
1385 $ log 'last(all(), -1)'
1385 $ log 'last(all(), -1)'
1386 hg: parse error: negative number to select
1386 hg: parse error: negative number to select
1387 [255]
1387 [255]
1388 $ log 'last(all(), 0)'
1388 $ log 'last(all(), 0)'
1389 $ log 'last(all(), 1)'
1389 $ log 'last(all(), 1)'
1390 9
1390 9
1391 $ log 'last(all(), 2)'
1391 $ log 'last(all(), 2)'
1392 8
1392 8
1393 9
1393 9
1394
1394
1395 Test smartset.slice() by first/last()
1395 Test smartset.slice() by first/last()
1396
1396
1397 (using unoptimized set, filteredset as example)
1397 (using unoptimized set, filteredset as example)
1398
1398
1399 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1399 $ hg debugrevspec --no-show-revs -s '0:7 & branch("re:")'
1400 * set:
1400 * set:
1401 <filteredset
1401 <filteredset
1402 <spanset+ 0:8>,
1402 <spanset+ 0:8>,
1403 <branch 're:'>>
1403 <branch 're:'>>
1404 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1404 $ log 'limit(0:7 & branch("re:"), 3, 4)'
1405 4
1405 4
1406 5
1406 5
1407 6
1407 6
1408 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1408 $ log 'limit(7:0 & branch("re:"), 3, 4)'
1409 3
1409 3
1410 2
1410 2
1411 1
1411 1
1412 $ log 'last(0:7 & branch("re:"), 2)'
1412 $ log 'last(0:7 & branch("re:"), 2)'
1413 6
1413 6
1414 7
1414 7
1415
1415
1416 (using baseset)
1416 (using baseset)
1417
1417
1418 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1418 $ hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7
1419 * set:
1419 * set:
1420 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1420 <baseset [0, 1, 2, 3, 4, 5, 6, 7]>
1421 $ hg debugrevspec --no-show-revs -s 0::7
1421 $ hg debugrevspec --no-show-revs -s 0::7
1422 * set:
1422 * set:
1423 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1423 <baseset+ [0, 1, 2, 3, 4, 5, 6, 7]>
1424 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1424 $ log 'limit(0+1+2+3+4+5+6+7, 3, 4)'
1425 4
1425 4
1426 5
1426 5
1427 6
1427 6
1428 $ log 'limit(sort(0::7, rev), 3, 4)'
1428 $ log 'limit(sort(0::7, rev), 3, 4)'
1429 4
1429 4
1430 5
1430 5
1431 6
1431 6
1432 $ log 'limit(sort(0::7, -rev), 3, 4)'
1432 $ log 'limit(sort(0::7, -rev), 3, 4)'
1433 3
1433 3
1434 2
1434 2
1435 1
1435 1
1436 $ log 'last(sort(0::7, rev), 2)'
1436 $ log 'last(sort(0::7, rev), 2)'
1437 6
1437 6
1438 7
1438 7
1439 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1439 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'
1440 * set:
1440 * set:
1441 <baseset+ [6, 7]>
1441 <baseset+ [6, 7]>
1442 6
1442 6
1443 7
1443 7
1444 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1444 $ hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'
1445 * set:
1445 * set:
1446 <baseset+ []>
1446 <baseset+ []>
1447 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1447 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'
1448 * set:
1448 * set:
1449 <baseset- [0, 1]>
1449 <baseset- [0, 1]>
1450 1
1450 1
1451 0
1451 0
1452 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1452 $ hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'
1453 * set:
1453 * set:
1454 <baseset- []>
1454 <baseset- []>
1455 $ hg debugrevspec -s 'limit(0::7, 0)'
1455 $ hg debugrevspec -s 'limit(0::7, 0)'
1456 * set:
1456 * set:
1457 <baseset+ []>
1457 <baseset+ []>
1458
1458
1459 (using spanset)
1459 (using spanset)
1460
1460
1461 $ hg debugrevspec --no-show-revs -s 0:7
1461 $ hg debugrevspec --no-show-revs -s 0:7
1462 * set:
1462 * set:
1463 <spanset+ 0:8>
1463 <spanset+ 0:8>
1464 $ log 'limit(0:7, 3, 4)'
1464 $ log 'limit(0:7, 3, 4)'
1465 4
1465 4
1466 5
1466 5
1467 6
1467 6
1468 $ log 'limit(7:0, 3, 4)'
1468 $ log 'limit(7:0, 3, 4)'
1469 3
1469 3
1470 2
1470 2
1471 1
1471 1
1472 $ log 'limit(0:7, 3, 6)'
1472 $ log 'limit(0:7, 3, 6)'
1473 6
1473 6
1474 7
1474 7
1475 $ log 'limit(7:0, 3, 6)'
1475 $ log 'limit(7:0, 3, 6)'
1476 1
1476 1
1477 0
1477 0
1478 $ log 'last(0:7, 2)'
1478 $ log 'last(0:7, 2)'
1479 6
1479 6
1480 7
1480 7
1481 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1481 $ hg debugrevspec -s 'limit(0:7, 3, 6)'
1482 * set:
1482 * set:
1483 <spanset+ 6:8>
1483 <spanset+ 6:8>
1484 6
1484 6
1485 7
1485 7
1486 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1486 $ hg debugrevspec -s 'limit(0:7, 3, 9)'
1487 * set:
1487 * set:
1488 <spanset+ 8:8>
1488 <spanset+ 8:8>
1489 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1489 $ hg debugrevspec -s 'limit(7:0, 3, 6)'
1490 * set:
1490 * set:
1491 <spanset- 0:2>
1491 <spanset- 0:2>
1492 1
1492 1
1493 0
1493 0
1494 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1494 $ hg debugrevspec -s 'limit(7:0, 3, 9)'
1495 * set:
1495 * set:
1496 <spanset- 0:0>
1496 <spanset- 0:0>
1497 $ hg debugrevspec -s 'limit(0:7, 0)'
1497 $ hg debugrevspec -s 'limit(0:7, 0)'
1498 * set:
1498 * set:
1499 <spanset+ 0:0>
1499 <spanset+ 0:0>
1500
1500
1501 Test order of first/last revisions
1501 Test order of first/last revisions
1502
1502
1503 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1503 $ hg debugrevspec -s 'first(4:0, 3) & 3:'
1504 * set:
1504 * set:
1505 <filteredset
1505 <filteredset
1506 <spanset- 2:5>,
1506 <spanset- 2:5>,
1507 <spanset+ 3:10>>
1507 <spanset+ 3:10>>
1508 4
1508 4
1509 3
1509 3
1510
1510
1511 $ hg debugrevspec -s '3: & first(4:0, 3)'
1511 $ hg debugrevspec -s '3: & first(4:0, 3)'
1512 * set:
1512 * set:
1513 <filteredset
1513 <filteredset
1514 <spanset+ 3:10>,
1514 <spanset+ 3:10>,
1515 <spanset- 2:5>>
1515 <spanset- 2:5>>
1516 3
1516 3
1517 4
1517 4
1518
1518
1519 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1519 $ hg debugrevspec -s 'last(4:0, 3) & :1'
1520 * set:
1520 * set:
1521 <filteredset
1521 <filteredset
1522 <spanset- 0:3>,
1522 <spanset- 0:3>,
1523 <spanset+ 0:2>>
1523 <spanset+ 0:2>>
1524 1
1524 1
1525 0
1525 0
1526
1526
1527 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1527 $ hg debugrevspec -s ':1 & last(4:0, 3)'
1528 * set:
1528 * set:
1529 <filteredset
1529 <filteredset
1530 <spanset+ 0:2>,
1530 <spanset+ 0:2>,
1531 <spanset+ 0:3>>
1531 <spanset+ 0:3>>
1532 0
1532 0
1533 1
1533 1
1534
1534
1535 Test scmutil.revsingle() should return the last revision
1535 Test scmutil.revsingle() should return the last revision
1536
1536
1537 $ hg debugrevspec -s 'last(0::)'
1537 $ hg debugrevspec -s 'last(0::)'
1538 * set:
1538 * set:
1539 <baseset slice=0:1
1539 <baseset slice=0:1
1540 <generatorsetasc->>
1540 <generatorsetasc->>
1541 9
1541 9
1542 $ hg identify -r '0::' --num
1542 $ hg identify -r '0::' --num
1543 9
1543 9
1544
1544
1545 Test matching
1545 Test matching
1546
1546
1547 $ log 'matching(6)'
1547 $ log 'matching(6)'
1548 6
1548 6
1549 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1549 $ log 'matching(6:7, "phase parents user date branch summary files description substate")'
1550 6
1550 6
1551 7
1551 7
1552
1552
1553 Testing min and max
1553 Testing min and max
1554
1554
1555 max: simple
1555 max: simple
1556
1556
1557 $ log 'max(contains(a))'
1557 $ log 'max(contains(a))'
1558 5
1558 5
1559
1559
1560 max: simple on unordered set)
1560 max: simple on unordered set)
1561
1561
1562 $ log 'max((4+0+2+5+7) and contains(a))'
1562 $ log 'max((4+0+2+5+7) and contains(a))'
1563 5
1563 5
1564
1564
1565 max: no result
1565 max: no result
1566
1566
1567 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1567 $ log 'max(contains(stringthatdoesnotappearanywhere))'
1568
1568
1569 max: no result on unordered set
1569 max: no result on unordered set
1570
1570
1571 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1571 $ log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1572
1572
1573 min: simple
1573 min: simple
1574
1574
1575 $ log 'min(contains(a))'
1575 $ log 'min(contains(a))'
1576 0
1576 0
1577
1577
1578 min: simple on unordered set
1578 min: simple on unordered set
1579
1579
1580 $ log 'min((4+0+2+5+7) and contains(a))'
1580 $ log 'min((4+0+2+5+7) and contains(a))'
1581 0
1581 0
1582
1582
1583 min: empty
1583 min: empty
1584
1584
1585 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1585 $ log 'min(contains(stringthatdoesnotappearanywhere))'
1586
1586
1587 min: empty on unordered set
1587 min: empty on unordered set
1588
1588
1589 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1589 $ log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'
1590
1590
1591
1591
1592 $ log 'merge()'
1592 $ log 'merge()'
1593 6
1593 6
1594 $ log 'branchpoint()'
1594 $ log 'branchpoint()'
1595 1
1595 1
1596 4
1596 4
1597 $ log 'modifies(b)'
1597 $ log 'modifies(b)'
1598 4
1598 4
1599 $ log 'modifies("path:b")'
1599 $ log 'modifies("path:b")'
1600 4
1600 4
1601 $ log 'modifies("*")'
1601 $ log 'modifies("*")'
1602 4
1602 4
1603 6
1603 6
1604 $ log 'modifies("set:modified()")'
1604 $ log 'modifies("set:modified()")'
1605 4
1605 4
1606 $ log 'id(5)'
1606 $ log 'id(5)'
1607 2
1607 2
1608 $ log 'only(9)'
1608 $ log 'only(9)'
1609 8
1609 8
1610 9
1610 9
1611 $ log 'only(8)'
1611 $ log 'only(8)'
1612 8
1612 8
1613 $ log 'only(9, 5)'
1613 $ log 'only(9, 5)'
1614 2
1614 2
1615 4
1615 4
1616 8
1616 8
1617 9
1617 9
1618 $ log 'only(7 + 9, 5 + 2)'
1618 $ log 'only(7 + 9, 5 + 2)'
1619 4
1619 4
1620 6
1620 6
1621 7
1621 7
1622 8
1622 8
1623 9
1623 9
1624
1624
1625 Test empty set input
1625 Test empty set input
1626 $ log 'only(p2())'
1626 $ log 'only(p2())'
1627 $ log 'only(p1(), p2())'
1627 $ log 'only(p1(), p2())'
1628 0
1628 0
1629 1
1629 1
1630 2
1630 2
1631 4
1631 4
1632 8
1632 8
1633 9
1633 9
1634
1634
1635 Test '%' operator
1635 Test '%' operator
1636
1636
1637 $ log '9%'
1637 $ log '9%'
1638 8
1638 8
1639 9
1639 9
1640 $ log '9%5'
1640 $ log '9%5'
1641 2
1641 2
1642 4
1642 4
1643 8
1643 8
1644 9
1644 9
1645 $ log '(7 + 9)%(5 + 2)'
1645 $ log '(7 + 9)%(5 + 2)'
1646 4
1646 4
1647 6
1647 6
1648 7
1648 7
1649 8
1649 8
1650 9
1650 9
1651
1651
1652 Test operand of '%' is optimized recursively (issue4670)
1652 Test operand of '%' is optimized recursively (issue4670)
1653
1653
1654 $ try --optimize '8:9-8%'
1654 $ try --optimize '8:9-8%'
1655 (onlypost
1655 (onlypost
1656 (minus
1656 (minus
1657 (range
1657 (range
1658 (symbol '8')
1658 (symbol '8')
1659 (symbol '9'))
1659 (symbol '9'))
1660 (symbol '8')))
1660 (symbol '8')))
1661 * optimized:
1661 * optimized:
1662 (func
1662 (func
1663 (symbol 'only')
1663 (symbol 'only')
1664 (difference
1664 (difference
1665 (range
1665 (range
1666 (symbol '8')
1666 (symbol '8')
1667 (symbol '9'))
1667 (symbol '9'))
1668 (symbol '8')))
1668 (symbol '8')))
1669 * set:
1669 * set:
1670 <baseset+ [8, 9]>
1670 <baseset+ [8, 9]>
1671 8
1671 8
1672 9
1672 9
1673 $ try --optimize '(9)%(5)'
1673 $ try --optimize '(9)%(5)'
1674 (only
1674 (only
1675 (group
1675 (group
1676 (symbol '9'))
1676 (symbol '9'))
1677 (group
1677 (group
1678 (symbol '5')))
1678 (symbol '5')))
1679 * optimized:
1679 * optimized:
1680 (func
1680 (func
1681 (symbol 'only')
1681 (symbol 'only')
1682 (list
1682 (list
1683 (symbol '9')
1683 (symbol '9')
1684 (symbol '5')))
1684 (symbol '5')))
1685 * set:
1685 * set:
1686 <baseset+ [2, 4, 8, 9]>
1686 <baseset+ [2, 4, 8, 9]>
1687 2
1687 2
1688 4
1688 4
1689 8
1689 8
1690 9
1690 9
1691
1691
1692 Test the order of operations
1692 Test the order of operations
1693
1693
1694 $ log '7 + 9%5 + 2'
1694 $ log '7 + 9%5 + 2'
1695 7
1695 7
1696 2
1696 2
1697 4
1697 4
1698 8
1698 8
1699 9
1699 9
1700
1700
1701 Test explicit numeric revision
1701 Test explicit numeric revision
1702 $ log 'rev(-2)'
1702 $ log 'rev(-2)'
1703 $ log 'rev(-1)'
1703 $ log 'rev(-1)'
1704 -1
1704 -1
1705 $ log 'rev(0)'
1705 $ log 'rev(0)'
1706 0
1706 0
1707 $ log 'rev(9)'
1707 $ log 'rev(9)'
1708 9
1708 9
1709 $ log 'rev(10)'
1709 $ log 'rev(10)'
1710 $ log 'rev(tip)'
1710 $ log 'rev(tip)'
1711 hg: parse error: rev expects a number
1711 hg: parse error: rev expects a number
1712 [255]
1712 [255]
1713
1713
1714 Test hexadecimal revision
1714 Test hexadecimal revision
1715 $ log 'id(2)'
1715 $ log 'id(2)'
1716 $ log 'id(23268)'
1716 $ log 'id(23268)'
1717 4
1717 4
1718 $ log 'id(2785f51eece)'
1718 $ log 'id(2785f51eece)'
1719 0
1719 0
1720 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1720 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'
1721 8
1721 8
1722 $ log 'id(d5d0dcbdc4a)'
1722 $ log 'id(d5d0dcbdc4a)'
1723 $ log 'id(d5d0dcbdc4w)'
1723 $ log 'id(d5d0dcbdc4w)'
1724 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1724 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'
1725 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1725 $ log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'
1726 $ log 'id(1.0)'
1726 $ log 'id(1.0)'
1727 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1727 $ log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'
1728
1728
1729 Test null revision
1729 Test null revision
1730 $ log '(null)'
1730 $ log '(null)'
1731 -1
1731 -1
1732 $ log '(null:0)'
1732 $ log '(null:0)'
1733 -1
1733 -1
1734 0
1734 0
1735 $ log '(0:null)'
1735 $ log '(0:null)'
1736 0
1736 0
1737 -1
1737 -1
1738 $ log 'null::0'
1738 $ log 'null::0'
1739 -1
1739 -1
1740 0
1740 0
1741 $ log 'null:tip - 0:'
1741 $ log 'null:tip - 0:'
1742 -1
1742 -1
1743 $ log 'null: and null::' | head -1
1743 $ log 'null: and null::' | head -1
1744 -1
1744 -1
1745 $ log 'null: or 0:' | head -2
1745 $ log 'null: or 0:' | head -2
1746 -1
1746 -1
1747 0
1747 0
1748 $ log 'ancestors(null)'
1748 $ log 'ancestors(null)'
1749 -1
1749 -1
1750 $ log 'reverse(null:)' | tail -2
1750 $ log 'reverse(null:)' | tail -2
1751 0
1751 0
1752 -1
1752 -1
1753 $ log 'first(null:)'
1753 $ log 'first(null:)'
1754 -1
1754 -1
1755 $ log 'min(null:)'
1755 $ log 'min(null:)'
1756 BROKEN: should be '-1'
1756 BROKEN: should be '-1'
1757 $ log 'tip:null and all()' | tail -2
1757 $ log 'tip:null and all()' | tail -2
1758 1
1758 1
1759 0
1759 0
1760
1760
1761 Test working-directory revision
1761 Test working-directory revision
1762 $ hg debugrevspec 'wdir()'
1762 $ hg debugrevspec 'wdir()'
1763 2147483647
1763 2147483647
1764 $ hg debugrevspec 'wdir()^'
1764 $ hg debugrevspec 'wdir()^'
1765 9
1765 9
1766 $ hg up 7
1766 $ hg up 7
1767 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1767 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1768 $ hg debugrevspec 'wdir()^'
1768 $ hg debugrevspec 'wdir()^'
1769 7
1769 7
1770 $ hg debugrevspec 'wdir()^0'
1770 $ hg debugrevspec 'wdir()^0'
1771 2147483647
1771 2147483647
1772 $ hg debugrevspec 'wdir()~3'
1772 $ hg debugrevspec 'wdir()~3'
1773 5
1773 5
1774 $ hg debugrevspec 'ancestors(wdir())'
1774 $ hg debugrevspec 'ancestors(wdir())'
1775 0
1775 0
1776 1
1776 1
1777 2
1777 2
1778 3
1778 3
1779 4
1779 4
1780 5
1780 5
1781 6
1781 6
1782 7
1782 7
1783 2147483647
1783 2147483647
1784 $ hg debugrevspec 'wdir()~0'
1784 $ hg debugrevspec 'wdir()~0'
1785 2147483647
1785 2147483647
1786 $ hg debugrevspec 'p1(wdir())'
1786 $ hg debugrevspec 'p1(wdir())'
1787 7
1787 7
1788 $ hg debugrevspec 'p2(wdir())'
1788 $ hg debugrevspec 'p2(wdir())'
1789 $ hg debugrevspec 'parents(wdir())'
1789 $ hg debugrevspec 'parents(wdir())'
1790 7
1790 7
1791 $ hg debugrevspec 'wdir()^1'
1791 $ hg debugrevspec 'wdir()^1'
1792 7
1792 7
1793 $ hg debugrevspec 'wdir()^2'
1793 $ hg debugrevspec 'wdir()^2'
1794 $ hg debugrevspec 'wdir()^3'
1794 $ hg debugrevspec 'wdir()^3'
1795 hg: parse error: ^ expects a number 0, 1, or 2
1795 hg: parse error: ^ expects a number 0, 1, or 2
1796 [255]
1796 [255]
1797 For tests consistency
1797 For tests consistency
1798 $ hg up 9
1798 $ hg up 9
1799 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1799 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1800 $ hg debugrevspec 'tip or wdir()'
1800 $ hg debugrevspec 'tip or wdir()'
1801 9
1801 9
1802 2147483647
1802 2147483647
1803 $ hg debugrevspec '0:tip and wdir()'
1803 $ hg debugrevspec '0:tip and wdir()'
1804 $ log '0:wdir()' | tail -3
1804 $ log '0:wdir()' | tail -3
1805 8
1805 8
1806 9
1806 9
1807 2147483647
1807 2147483647
1808 $ log 'wdir():0' | head -3
1808 $ log 'wdir():0' | head -3
1809 2147483647
1809 2147483647
1810 9
1810 9
1811 8
1811 8
1812 $ log 'wdir():wdir()'
1812 $ log 'wdir():wdir()'
1813 2147483647
1813 2147483647
1814 $ log '(all() + wdir()) & min(. + wdir())'
1814 $ log '(all() + wdir()) & min(. + wdir())'
1815 9
1815 9
1816 $ log '(all() + wdir()) & max(. + wdir())'
1816 $ log '(all() + wdir()) & max(. + wdir())'
1817 2147483647
1817 2147483647
1818 $ log 'first(wdir() + .)'
1818 $ log 'first(wdir() + .)'
1819 2147483647
1819 2147483647
1820 $ log 'last(. + wdir())'
1820 $ log 'last(. + wdir())'
1821 2147483647
1821 2147483647
1822
1822
1823 Test working-directory integer revision and node id
1823 Test working-directory integer revision and node id
1824 (BUG: '0:wdir()' is still needed to populate wdir revision)
1824 (BUG: '0:wdir()' is still needed to populate wdir revision)
1825
1825
1826 $ hg debugrevspec '0:wdir() & 2147483647'
1826 $ hg debugrevspec '0:wdir() & 2147483647'
1827 2147483647
1827 2147483647
1828 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1828 $ hg debugrevspec '0:wdir() & rev(2147483647)'
1829 2147483647
1829 2147483647
1830 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1830 $ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
1831 2147483647
1831 2147483647
1832 $ hg debugrevspec '0:wdir() & ffffffffffff'
1832 $ hg debugrevspec '0:wdir() & ffffffffffff'
1833 2147483647
1833 2147483647
1834 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1834 $ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
1835 2147483647
1835 2147483647
1836 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1836 $ hg debugrevspec '0:wdir() & id(ffffffffffff)'
1837 2147483647
1837 2147483647
1838
1838
1839 $ cd ..
1839 $ cd ..
1840
1840
1841 Test short 'ff...' hash collision
1841 Test short 'ff...' hash collision
1842 (BUG: '0:wdir()' is still needed to populate wdir revision)
1842 (BUG: '0:wdir()' is still needed to populate wdir revision)
1843
1843
1844 $ hg init wdir-hashcollision
1844 $ hg init wdir-hashcollision
1845 $ cd wdir-hashcollision
1845 $ cd wdir-hashcollision
1846 $ cat <<EOF >> .hg/hgrc
1846 $ cat <<EOF >> .hg/hgrc
1847 > [experimental]
1847 > [experimental]
1848 > evolution.createmarkers=True
1848 > evolution.createmarkers=True
1849 > EOF
1849 > EOF
1850 $ echo 0 > a
1850 $ echo 0 > a
1851 $ hg ci -qAm 0
1851 $ hg ci -qAm 0
1852 $ for i in 2463 2961 6726 78127; do
1852 $ for i in 2463 2961 6726 78127; do
1853 > hg up -q 0
1853 > hg up -q 0
1854 > echo $i > a
1854 > echo $i > a
1855 > hg ci -qm $i
1855 > hg ci -qm $i
1856 > done
1856 > done
1857 $ hg up -q null
1857 $ hg up -q null
1858 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1858 $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
1859 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1859 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
1860 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1860 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
1861 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1861 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
1862 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1862 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
1863 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1863 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
1864 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1864 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
1865 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1865 $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
1866 obsoleted 1 changesets
1866 obsoleted 1 changesets
1867
1867
1868 $ hg debugrevspec '0:wdir() & fff'
1868 $ hg debugrevspec '0:wdir() & fff'
1869 abort: 00changelog.i@fff: ambiguous identifier!
1869 abort: 00changelog.i@fff: ambiguous identifier!
1870 [255]
1870 [255]
1871 $ hg debugrevspec '0:wdir() & ffff'
1871 $ hg debugrevspec '0:wdir() & ffff'
1872 abort: 00changelog.i@ffff: ambiguous identifier!
1872 abort: 00changelog.i@ffff: ambiguous identifier!
1873 [255]
1873 [255]
1874 $ hg debugrevspec '0:wdir() & fffb'
1874 $ hg debugrevspec '0:wdir() & fffb'
1875 abort: 00changelog.i@fffb: ambiguous identifier!
1875 abort: 00changelog.i@fffb: ambiguous identifier!
1876 [255]
1876 [255]
1877 BROKEN should be '2' (node lookup uses unfiltered repo)
1877 BROKEN should be '2' (node lookup uses unfiltered repo)
1878 $ hg debugrevspec '0:wdir() & id(fffb)'
1878 $ hg debugrevspec '0:wdir() & id(fffb)'
1879 BROKEN should be '2' (node lookup uses unfiltered repo)
1879 BROKEN should be '2' (node lookup uses unfiltered repo)
1880 $ hg debugrevspec '0:wdir() & ffff8'
1880 $ hg debugrevspec '0:wdir() & ffff8'
1881 4
1881 4
1882 $ hg debugrevspec '0:wdir() & fffff'
1882 $ hg debugrevspec '0:wdir() & fffff'
1883 2147483647
1883 2147483647
1884
1884
1885 $ cd ..
1885 $ cd ..
1886
1886
1887 Test branch() with wdir()
1887 Test branch() with wdir()
1888
1888
1889 $ cd repo
1889 $ cd repo
1890
1890
1891 $ log '0:wdir() & branch("literal:Γ©")'
1891 $ log '0:wdir() & branch("literal:Γ©")'
1892 8
1892 8
1893 9
1893 9
1894 2147483647
1894 2147483647
1895 $ log '0:wdir() & branch("re:Γ©")'
1895 $ log '0:wdir() & branch("re:Γ©")'
1896 8
1896 8
1897 9
1897 9
1898 2147483647
1898 2147483647
1899 $ log '0:wdir() & branch("re:^a")'
1899 $ log '0:wdir() & branch("re:^a")'
1900 0
1900 0
1901 2
1901 2
1902 $ log '0:wdir() & branch(8)'
1902 $ log '0:wdir() & branch(8)'
1903 8
1903 8
1904 9
1904 9
1905 2147483647
1905 2147483647
1906
1906
1907 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1907 branch(wdir()) returns all revisions belonging to the working branch. The wdir
1908 itself isn't returned unless it is explicitly populated.
1908 itself isn't returned unless it is explicitly populated.
1909
1909
1910 $ log 'branch(wdir())'
1910 $ log 'branch(wdir())'
1911 8
1911 8
1912 9
1912 9
1913 $ log '0:wdir() & branch(wdir())'
1913 $ log '0:wdir() & branch(wdir())'
1914 8
1914 8
1915 9
1915 9
1916 2147483647
1916 2147483647
1917
1917
1918 $ log 'outgoing()'
1918 $ log 'outgoing()'
1919 8
1919 8
1920 9
1920 9
1921 $ log 'outgoing("../remote1")'
1921 $ log 'outgoing("../remote1")'
1922 8
1922 8
1923 9
1923 9
1924 $ log 'outgoing("../remote2")'
1924 $ log 'outgoing("../remote2")'
1925 3
1925 3
1926 5
1926 5
1927 6
1927 6
1928 7
1928 7
1929 9
1929 9
1930 $ log 'p1(merge())'
1930 $ log 'p1(merge())'
1931 5
1931 5
1932 $ log 'p2(merge())'
1932 $ log 'p2(merge())'
1933 4
1933 4
1934 $ log 'parents(merge())'
1934 $ log 'parents(merge())'
1935 4
1935 4
1936 5
1936 5
1937 $ log 'p1(branchpoint())'
1937 $ log 'p1(branchpoint())'
1938 0
1938 0
1939 2
1939 2
1940 $ log 'p2(branchpoint())'
1940 $ log 'p2(branchpoint())'
1941 $ log 'parents(branchpoint())'
1941 $ log 'parents(branchpoint())'
1942 0
1942 0
1943 2
1943 2
1944 $ log 'removes(a)'
1944 $ log 'removes(a)'
1945 2
1945 2
1946 6
1946 6
1947 $ log 'roots(all())'
1947 $ log 'roots(all())'
1948 0
1948 0
1949 $ log 'reverse(2 or 3 or 4 or 5)'
1949 $ log 'reverse(2 or 3 or 4 or 5)'
1950 5
1950 5
1951 4
1951 4
1952 3
1952 3
1953 2
1953 2
1954 $ log 'reverse(all())'
1954 $ log 'reverse(all())'
1955 9
1955 9
1956 8
1956 8
1957 7
1957 7
1958 6
1958 6
1959 5
1959 5
1960 4
1960 4
1961 3
1961 3
1962 2
1962 2
1963 1
1963 1
1964 0
1964 0
1965 $ log 'reverse(all()) & filelog(b)'
1965 $ log 'reverse(all()) & filelog(b)'
1966 4
1966 4
1967 1
1967 1
1968 $ log 'rev(5)'
1968 $ log 'rev(5)'
1969 5
1969 5
1970 $ log 'sort(limit(reverse(all()), 3))'
1970 $ log 'sort(limit(reverse(all()), 3))'
1971 7
1971 7
1972 8
1972 8
1973 9
1973 9
1974 $ log 'sort(2 or 3 or 4 or 5, date)'
1974 $ log 'sort(2 or 3 or 4 or 5, date)'
1975 2
1975 2
1976 3
1976 3
1977 5
1977 5
1978 4
1978 4
1979 $ log 'tagged()'
1979 $ log 'tagged()'
1980 6
1980 6
1981 $ log 'tag()'
1981 $ log 'tag()'
1982 6
1982 6
1983 $ log 'tag(1.0)'
1983 $ log 'tag(1.0)'
1984 6
1984 6
1985 $ log 'tag(tip)'
1985 $ log 'tag(tip)'
1986 9
1986 9
1987
1987
1988 Test order of revisions in compound expression
1988 Test order of revisions in compound expression
1989 ----------------------------------------------
1989 ----------------------------------------------
1990
1990
1991 The general rule is that only the outermost (= leftmost) predicate can
1991 The general rule is that only the outermost (= leftmost) predicate can
1992 enforce its ordering requirement. The other predicates should take the
1992 enforce its ordering requirement. The other predicates should take the
1993 ordering defined by it.
1993 ordering defined by it.
1994
1994
1995 'A & B' should follow the order of 'A':
1995 'A & B' should follow the order of 'A':
1996
1996
1997 $ log '2:0 & 0::2'
1997 $ log '2:0 & 0::2'
1998 2
1998 2
1999 1
1999 1
2000 0
2000 0
2001
2001
2002 'head()' combines sets in right order:
2002 'head()' combines sets in right order:
2003
2003
2004 $ log '2:0 & head()'
2004 $ log '2:0 & head()'
2005 2
2005 2
2006 1
2006 1
2007 0
2007 0
2008
2008
2009 'x:y' takes ordering parameter into account:
2009 'x:y' takes ordering parameter into account:
2010
2010
2011 $ try -p optimized '3:0 & 0:3 & not 2:1'
2011 $ try -p optimized '3:0 & 0:3 & not 2:1'
2012 * optimized:
2012 * optimized:
2013 (difference
2013 (difference
2014 (and
2014 (and
2015 (range
2015 (range
2016 (symbol '3')
2016 (symbol '3')
2017 (symbol '0'))
2017 (symbol '0'))
2018 (range
2018 (range
2019 (symbol '0')
2019 (symbol '0')
2020 (symbol '3')))
2020 (symbol '3')))
2021 (range
2021 (range
2022 (symbol '2')
2022 (symbol '2')
2023 (symbol '1')))
2023 (symbol '1')))
2024 * set:
2024 * set:
2025 <filteredset
2025 <filteredset
2026 <filteredset
2026 <filteredset
2027 <spanset- 0:4>,
2027 <spanset- 0:4>,
2028 <spanset+ 0:4>>,
2028 <spanset+ 0:4>>,
2029 <not
2029 <not
2030 <spanset+ 1:3>>>
2030 <spanset+ 1:3>>>
2031 3
2031 3
2032 0
2032 0
2033
2033
2034 'a + b', which is optimized to '_list(a b)', should take the ordering of
2034 'a + b', which is optimized to '_list(a b)', should take the ordering of
2035 the left expression:
2035 the left expression:
2036
2036
2037 $ try --optimize '2:0 & (0 + 1 + 2)'
2037 $ try --optimize '2:0 & (0 + 1 + 2)'
2038 (and
2038 (and
2039 (range
2039 (range
2040 (symbol '2')
2040 (symbol '2')
2041 (symbol '0'))
2041 (symbol '0'))
2042 (group
2042 (group
2043 (or
2043 (or
2044 (list
2044 (list
2045 (symbol '0')
2045 (symbol '0')
2046 (symbol '1')
2046 (symbol '1')
2047 (symbol '2')))))
2047 (symbol '2')))))
2048 * optimized:
2048 * optimized:
2049 (and
2049 (and
2050 (range
2050 (range
2051 (symbol '2')
2051 (symbol '2')
2052 (symbol '0'))
2052 (symbol '0'))
2053 (func
2053 (func
2054 (symbol '_list')
2054 (symbol '_list')
2055 (string '0\x001\x002')))
2055 (string '0\x001\x002')))
2056 * set:
2056 * set:
2057 <filteredset
2057 <filteredset
2058 <spanset- 0:3>,
2058 <spanset- 0:3>,
2059 <baseset [0, 1, 2]>>
2059 <baseset [0, 1, 2]>>
2060 2
2060 2
2061 1
2061 1
2062 0
2062 0
2063
2063
2064 'A + B' should take the ordering of the left expression:
2064 'A + B' should take the ordering of the left expression:
2065
2065
2066 $ try --optimize '2:0 & (0:1 + 2)'
2066 $ try --optimize '2:0 & (0:1 + 2)'
2067 (and
2067 (and
2068 (range
2068 (range
2069 (symbol '2')
2069 (symbol '2')
2070 (symbol '0'))
2070 (symbol '0'))
2071 (group
2071 (group
2072 (or
2072 (or
2073 (list
2073 (list
2074 (range
2074 (range
2075 (symbol '0')
2075 (symbol '0')
2076 (symbol '1'))
2076 (symbol '1'))
2077 (symbol '2')))))
2077 (symbol '2')))))
2078 * optimized:
2078 * optimized:
2079 (and
2079 (and
2080 (range
2080 (range
2081 (symbol '2')
2081 (symbol '2')
2082 (symbol '0'))
2082 (symbol '0'))
2083 (or
2083 (or
2084 (list
2084 (list
2085 (range
2085 (range
2086 (symbol '0')
2086 (symbol '0')
2087 (symbol '1'))
2087 (symbol '1'))
2088 (symbol '2'))))
2088 (symbol '2'))))
2089 * set:
2089 * set:
2090 <filteredset
2090 <filteredset
2091 <spanset- 0:3>,
2091 <spanset- 0:3>,
2092 <addset
2092 <addset
2093 <spanset+ 0:2>,
2093 <spanset+ 0:2>,
2094 <baseset [2]>>>
2094 <baseset [2]>>>
2095 2
2095 2
2096 1
2096 1
2097 0
2097 0
2098
2098
2099 '_intlist(a b)' should behave like 'a + b':
2099 '_intlist(a b)' should behave like 'a + b':
2100
2100
2101 $ trylist --optimize '2:0 & %ld' 0 1 2
2101 $ trylist --optimize '2:0 & %ld' 0 1 2
2102 (and
2102 (and
2103 (range
2103 (range
2104 (symbol '2')
2104 (symbol '2')
2105 (symbol '0'))
2105 (symbol '0'))
2106 (func
2106 (func
2107 (symbol '_intlist')
2107 (symbol '_intlist')
2108 (string '0\x001\x002')))
2108 (string '0\x001\x002')))
2109 * optimized:
2109 * optimized:
2110 (andsmally
2110 (andsmally
2111 (range
2111 (range
2112 (symbol '2')
2112 (symbol '2')
2113 (symbol '0'))
2113 (symbol '0'))
2114 (func
2114 (func
2115 (symbol '_intlist')
2115 (symbol '_intlist')
2116 (string '0\x001\x002')))
2116 (string '0\x001\x002')))
2117 * set:
2117 * set:
2118 <filteredset
2118 <filteredset
2119 <spanset- 0:3>,
2119 <spanset- 0:3>,
2120 <baseset+ [0, 1, 2]>>
2120 <baseset+ [0, 1, 2]>>
2121 2
2121 2
2122 1
2122 1
2123 0
2123 0
2124
2124
2125 $ trylist --optimize '%ld & 2:0' 0 2 1
2125 $ trylist --optimize '%ld & 2:0' 0 2 1
2126 (and
2126 (and
2127 (func
2127 (func
2128 (symbol '_intlist')
2128 (symbol '_intlist')
2129 (string '0\x002\x001'))
2129 (string '0\x002\x001'))
2130 (range
2130 (range
2131 (symbol '2')
2131 (symbol '2')
2132 (symbol '0')))
2132 (symbol '0')))
2133 * optimized:
2133 * optimized:
2134 (and
2134 (and
2135 (func
2135 (func
2136 (symbol '_intlist')
2136 (symbol '_intlist')
2137 (string '0\x002\x001'))
2137 (string '0\x002\x001'))
2138 (range
2138 (range
2139 (symbol '2')
2139 (symbol '2')
2140 (symbol '0')))
2140 (symbol '0')))
2141 * set:
2141 * set:
2142 <filteredset
2142 <filteredset
2143 <baseset [0, 2, 1]>,
2143 <baseset [0, 2, 1]>,
2144 <spanset- 0:3>>
2144 <spanset- 0:3>>
2145 0
2145 0
2146 2
2146 2
2147 1
2147 1
2148
2148
2149 '_hexlist(a b)' should behave like 'a + b':
2149 '_hexlist(a b)' should behave like 'a + b':
2150
2150
2151 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
2151 $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
2152 (and
2152 (and
2153 (range
2153 (range
2154 (symbol '2')
2154 (symbol '2')
2155 (symbol '0'))
2155 (symbol '0'))
2156 (func
2156 (func
2157 (symbol '_hexlist')
2157 (symbol '_hexlist')
2158 (string '*'))) (glob)
2158 (string '*'))) (glob)
2159 * optimized:
2159 * optimized:
2160 (and
2160 (and
2161 (range
2161 (range
2162 (symbol '2')
2162 (symbol '2')
2163 (symbol '0'))
2163 (symbol '0'))
2164 (func
2164 (func
2165 (symbol '_hexlist')
2165 (symbol '_hexlist')
2166 (string '*'))) (glob)
2166 (string '*'))) (glob)
2167 * set:
2167 * set:
2168 <filteredset
2168 <filteredset
2169 <spanset- 0:3>,
2169 <spanset- 0:3>,
2170 <baseset [0, 1, 2]>>
2170 <baseset [0, 1, 2]>>
2171 2
2171 2
2172 1
2172 1
2173 0
2173 0
2174
2174
2175 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2175 $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
2176 (and
2176 (and
2177 (func
2177 (func
2178 (symbol '_hexlist')
2178 (symbol '_hexlist')
2179 (string '*')) (glob)
2179 (string '*')) (glob)
2180 (range
2180 (range
2181 (symbol '2')
2181 (symbol '2')
2182 (symbol '0')))
2182 (symbol '0')))
2183 * optimized:
2183 * optimized:
2184 (andsmally
2184 (andsmally
2185 (func
2185 (func
2186 (symbol '_hexlist')
2186 (symbol '_hexlist')
2187 (string '*')) (glob)
2187 (string '*')) (glob)
2188 (range
2188 (range
2189 (symbol '2')
2189 (symbol '2')
2190 (symbol '0')))
2190 (symbol '0')))
2191 * set:
2191 * set:
2192 <baseset [0, 2, 1]>
2192 <baseset [0, 2, 1]>
2193 0
2193 0
2194 2
2194 2
2195 1
2195 1
2196
2196
2197 '_list' should not go through the slow follow-order path if order doesn't
2197 '_list' should not go through the slow follow-order path if order doesn't
2198 matter:
2198 matter:
2199
2199
2200 $ try -p optimized '2:0 & not (0 + 1)'
2200 $ try -p optimized '2:0 & not (0 + 1)'
2201 * optimized:
2201 * optimized:
2202 (difference
2202 (difference
2203 (range
2203 (range
2204 (symbol '2')
2204 (symbol '2')
2205 (symbol '0'))
2205 (symbol '0'))
2206 (func
2206 (func
2207 (symbol '_list')
2207 (symbol '_list')
2208 (string '0\x001')))
2208 (string '0\x001')))
2209 * set:
2209 * set:
2210 <filteredset
2210 <filteredset
2211 <spanset- 0:3>,
2211 <spanset- 0:3>,
2212 <not
2212 <not
2213 <baseset [0, 1]>>>
2213 <baseset [0, 1]>>>
2214 2
2214 2
2215
2215
2216 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2216 $ try -p optimized '2:0 & not (0:2 & (0 + 1))'
2217 * optimized:
2217 * optimized:
2218 (difference
2218 (difference
2219 (range
2219 (range
2220 (symbol '2')
2220 (symbol '2')
2221 (symbol '0'))
2221 (symbol '0'))
2222 (and
2222 (and
2223 (range
2223 (range
2224 (symbol '0')
2224 (symbol '0')
2225 (symbol '2'))
2225 (symbol '2'))
2226 (func
2226 (func
2227 (symbol '_list')
2227 (symbol '_list')
2228 (string '0\x001'))))
2228 (string '0\x001'))))
2229 * set:
2229 * set:
2230 <filteredset
2230 <filteredset
2231 <spanset- 0:3>,
2231 <spanset- 0:3>,
2232 <not
2232 <not
2233 <baseset [0, 1]>>>
2233 <baseset [0, 1]>>>
2234 2
2234 2
2235
2235
2236 because 'present()' does nothing other than suppressing an error, the
2236 because 'present()' does nothing other than suppressing an error, the
2237 ordering requirement should be forwarded to the nested expression
2237 ordering requirement should be forwarded to the nested expression
2238
2238
2239 $ try -p optimized 'present(2 + 0 + 1)'
2239 $ try -p optimized 'present(2 + 0 + 1)'
2240 * optimized:
2240 * optimized:
2241 (func
2241 (func
2242 (symbol 'present')
2242 (symbol 'present')
2243 (func
2243 (func
2244 (symbol '_list')
2244 (symbol '_list')
2245 (string '2\x000\x001')))
2245 (string '2\x000\x001')))
2246 * set:
2246 * set:
2247 <baseset [2, 0, 1]>
2247 <baseset [2, 0, 1]>
2248 2
2248 2
2249 0
2249 0
2250 1
2250 1
2251
2251
2252 $ try --optimize '2:0 & present(0 + 1 + 2)'
2252 $ try --optimize '2:0 & present(0 + 1 + 2)'
2253 (and
2253 (and
2254 (range
2254 (range
2255 (symbol '2')
2255 (symbol '2')
2256 (symbol '0'))
2256 (symbol '0'))
2257 (func
2257 (func
2258 (symbol 'present')
2258 (symbol 'present')
2259 (or
2259 (or
2260 (list
2260 (list
2261 (symbol '0')
2261 (symbol '0')
2262 (symbol '1')
2262 (symbol '1')
2263 (symbol '2')))))
2263 (symbol '2')))))
2264 * optimized:
2264 * optimized:
2265 (and
2265 (and
2266 (range
2266 (range
2267 (symbol '2')
2267 (symbol '2')
2268 (symbol '0'))
2268 (symbol '0'))
2269 (func
2269 (func
2270 (symbol 'present')
2270 (symbol 'present')
2271 (func
2271 (func
2272 (symbol '_list')
2272 (symbol '_list')
2273 (string '0\x001\x002'))))
2273 (string '0\x001\x002'))))
2274 * set:
2274 * set:
2275 <filteredset
2275 <filteredset
2276 <spanset- 0:3>,
2276 <spanset- 0:3>,
2277 <baseset [0, 1, 2]>>
2277 <baseset [0, 1, 2]>>
2278 2
2278 2
2279 1
2279 1
2280 0
2280 0
2281
2281
2282 'reverse()' should take effect only if it is the outermost expression:
2282 'reverse()' should take effect only if it is the outermost expression:
2283
2283
2284 $ try --optimize '0:2 & reverse(all())'
2284 $ try --optimize '0:2 & reverse(all())'
2285 (and
2285 (and
2286 (range
2286 (range
2287 (symbol '0')
2287 (symbol '0')
2288 (symbol '2'))
2288 (symbol '2'))
2289 (func
2289 (func
2290 (symbol 'reverse')
2290 (symbol 'reverse')
2291 (func
2291 (func
2292 (symbol 'all')
2292 (symbol 'all')
2293 None)))
2293 None)))
2294 * optimized:
2294 * optimized:
2295 (and
2295 (and
2296 (range
2296 (range
2297 (symbol '0')
2297 (symbol '0')
2298 (symbol '2'))
2298 (symbol '2'))
2299 (func
2299 (func
2300 (symbol 'reverse')
2300 (symbol 'reverse')
2301 (func
2301 (func
2302 (symbol 'all')
2302 (symbol 'all')
2303 None)))
2303 None)))
2304 * set:
2304 * set:
2305 <filteredset
2305 <filteredset
2306 <spanset+ 0:3>,
2306 <spanset+ 0:3>,
2307 <spanset+ 0:10>>
2307 <spanset+ 0:10>>
2308 0
2308 0
2309 1
2309 1
2310 2
2310 2
2311
2311
2312 'sort()' should take effect only if it is the outermost expression:
2312 'sort()' should take effect only if it is the outermost expression:
2313
2313
2314 $ try --optimize '0:2 & sort(all(), -rev)'
2314 $ try --optimize '0:2 & sort(all(), -rev)'
2315 (and
2315 (and
2316 (range
2316 (range
2317 (symbol '0')
2317 (symbol '0')
2318 (symbol '2'))
2318 (symbol '2'))
2319 (func
2319 (func
2320 (symbol 'sort')
2320 (symbol 'sort')
2321 (list
2321 (list
2322 (func
2322 (func
2323 (symbol 'all')
2323 (symbol 'all')
2324 None)
2324 None)
2325 (negate
2325 (negate
2326 (symbol 'rev')))))
2326 (symbol 'rev')))))
2327 * optimized:
2327 * optimized:
2328 (and
2328 (and
2329 (range
2329 (range
2330 (symbol '0')
2330 (symbol '0')
2331 (symbol '2'))
2331 (symbol '2'))
2332 (func
2332 (func
2333 (symbol 'sort')
2333 (symbol 'sort')
2334 (list
2334 (list
2335 (func
2335 (func
2336 (symbol 'all')
2336 (symbol 'all')
2337 None)
2337 None)
2338 (string '-rev'))))
2338 (string '-rev'))))
2339 * set:
2339 * set:
2340 <filteredset
2340 <filteredset
2341 <spanset+ 0:3>,
2341 <spanset+ 0:3>,
2342 <spanset+ 0:10>>
2342 <spanset+ 0:10>>
2343 0
2343 0
2344 1
2344 1
2345 2
2345 2
2346
2346
2347 invalid argument passed to noop sort():
2347 invalid argument passed to noop sort():
2348
2348
2349 $ log '0:2 & sort()'
2349 $ log '0:2 & sort()'
2350 hg: parse error: sort requires one or two arguments
2350 hg: parse error: sort requires one or two arguments
2351 [255]
2351 [255]
2352 $ log '0:2 & sort(all(), -invalid)'
2352 $ log '0:2 & sort(all(), -invalid)'
2353 hg: parse error: unknown sort key '-invalid'
2353 hg: parse error: unknown sort key '-invalid'
2354 [255]
2354 [255]
2355
2355
2356 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2356 for 'A & f(B)', 'B' should not be affected by the order of 'A':
2357
2357
2358 $ try --optimize '2:0 & first(1 + 0 + 2)'
2358 $ try --optimize '2:0 & first(1 + 0 + 2)'
2359 (and
2359 (and
2360 (range
2360 (range
2361 (symbol '2')
2361 (symbol '2')
2362 (symbol '0'))
2362 (symbol '0'))
2363 (func
2363 (func
2364 (symbol 'first')
2364 (symbol 'first')
2365 (or
2365 (or
2366 (list
2366 (list
2367 (symbol '1')
2367 (symbol '1')
2368 (symbol '0')
2368 (symbol '0')
2369 (symbol '2')))))
2369 (symbol '2')))))
2370 * optimized:
2370 * optimized:
2371 (and
2371 (and
2372 (range
2372 (range
2373 (symbol '2')
2373 (symbol '2')
2374 (symbol '0'))
2374 (symbol '0'))
2375 (func
2375 (func
2376 (symbol 'first')
2376 (symbol 'first')
2377 (func
2377 (func
2378 (symbol '_list')
2378 (symbol '_list')
2379 (string '1\x000\x002'))))
2379 (string '1\x000\x002'))))
2380 * set:
2380 * set:
2381 <filteredset
2381 <filteredset
2382 <baseset [1]>,
2382 <baseset [1]>,
2383 <spanset- 0:3>>
2383 <spanset- 0:3>>
2384 1
2384 1
2385
2385
2386 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2386 $ try --optimize '2:0 & not last(0 + 2 + 1)'
2387 (and
2387 (and
2388 (range
2388 (range
2389 (symbol '2')
2389 (symbol '2')
2390 (symbol '0'))
2390 (symbol '0'))
2391 (not
2391 (not
2392 (func
2392 (func
2393 (symbol 'last')
2393 (symbol 'last')
2394 (or
2394 (or
2395 (list
2395 (list
2396 (symbol '0')
2396 (symbol '0')
2397 (symbol '2')
2397 (symbol '2')
2398 (symbol '1'))))))
2398 (symbol '1'))))))
2399 * optimized:
2399 * optimized:
2400 (difference
2400 (difference
2401 (range
2401 (range
2402 (symbol '2')
2402 (symbol '2')
2403 (symbol '0'))
2403 (symbol '0'))
2404 (func
2404 (func
2405 (symbol 'last')
2405 (symbol 'last')
2406 (func
2406 (func
2407 (symbol '_list')
2407 (symbol '_list')
2408 (string '0\x002\x001'))))
2408 (string '0\x002\x001'))))
2409 * set:
2409 * set:
2410 <filteredset
2410 <filteredset
2411 <spanset- 0:3>,
2411 <spanset- 0:3>,
2412 <not
2412 <not
2413 <baseset [1]>>>
2413 <baseset [1]>>>
2414 2
2414 2
2415 0
2415 0
2416
2416
2417 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2417 for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
2418
2418
2419 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2419 $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
2420 (and
2420 (and
2421 (range
2421 (range
2422 (symbol '2')
2422 (symbol '2')
2423 (symbol '0'))
2423 (symbol '0'))
2424 (range
2424 (range
2425 (group
2425 (group
2426 (or
2426 (or
2427 (list
2427 (list
2428 (symbol '1')
2428 (symbol '1')
2429 (symbol '0')
2429 (symbol '0')
2430 (symbol '2'))))
2430 (symbol '2'))))
2431 (group
2431 (group
2432 (or
2432 (or
2433 (list
2433 (list
2434 (symbol '0')
2434 (symbol '0')
2435 (symbol '2')
2435 (symbol '2')
2436 (symbol '1'))))))
2436 (symbol '1'))))))
2437 * optimized:
2437 * optimized:
2438 (and
2438 (and
2439 (range
2439 (range
2440 (symbol '2')
2440 (symbol '2')
2441 (symbol '0'))
2441 (symbol '0'))
2442 (range
2442 (range
2443 (func
2443 (func
2444 (symbol '_list')
2444 (symbol '_list')
2445 (string '1\x000\x002'))
2445 (string '1\x000\x002'))
2446 (func
2446 (func
2447 (symbol '_list')
2447 (symbol '_list')
2448 (string '0\x002\x001'))))
2448 (string '0\x002\x001'))))
2449 * set:
2449 * set:
2450 <filteredset
2450 <filteredset
2451 <spanset- 0:3>,
2451 <spanset- 0:3>,
2452 <baseset [1]>>
2452 <baseset [1]>>
2453 1
2453 1
2454
2454
2455 'A & B' can be rewritten as 'flipand(B, A)' by weight.
2455 'A & B' can be rewritten as 'flipand(B, A)' by weight.
2456
2456
2457 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2457 $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
2458 (and
2458 (and
2459 (func
2459 (func
2460 (symbol 'contains')
2460 (symbol 'contains')
2461 (string 'glob:*'))
2461 (string 'glob:*'))
2462 (group
2462 (group
2463 (or
2463 (or
2464 (list
2464 (list
2465 (symbol '2')
2465 (symbol '2')
2466 (symbol '0')
2466 (symbol '0')
2467 (symbol '1')))))
2467 (symbol '1')))))
2468 * optimized:
2468 * optimized:
2469 (andsmally
2469 (andsmally
2470 (func
2470 (func
2471 (symbol 'contains')
2471 (symbol 'contains')
2472 (string 'glob:*'))
2472 (string 'glob:*'))
2473 (func
2473 (func
2474 (symbol '_list')
2474 (symbol '_list')
2475 (string '2\x000\x001')))
2475 (string '2\x000\x001')))
2476 * set:
2476 * set:
2477 <filteredset
2477 <filteredset
2478 <baseset+ [0, 1, 2]>,
2478 <baseset+ [0, 1, 2]>,
2479 <contains 'glob:*'>>
2479 <contains 'glob:*'>>
2480 0
2480 0
2481 1
2481 1
2482 2
2482 2
2483
2483
2484 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2484 and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
2485 the order appropriately:
2485 the order appropriately:
2486
2486
2487 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2487 $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
2488 (and
2488 (and
2489 (func
2489 (func
2490 (symbol 'reverse')
2490 (symbol 'reverse')
2491 (func
2491 (func
2492 (symbol 'contains')
2492 (symbol 'contains')
2493 (string 'glob:*')))
2493 (string 'glob:*')))
2494 (group
2494 (group
2495 (or
2495 (or
2496 (list
2496 (list
2497 (symbol '0')
2497 (symbol '0')
2498 (symbol '2')
2498 (symbol '2')
2499 (symbol '1')))))
2499 (symbol '1')))))
2500 * optimized:
2500 * optimized:
2501 (andsmally
2501 (andsmally
2502 (func
2502 (func
2503 (symbol 'reverse')
2503 (symbol 'reverse')
2504 (func
2504 (func
2505 (symbol 'contains')
2505 (symbol 'contains')
2506 (string 'glob:*')))
2506 (string 'glob:*')))
2507 (func
2507 (func
2508 (symbol '_list')
2508 (symbol '_list')
2509 (string '0\x002\x001')))
2509 (string '0\x002\x001')))
2510 * set:
2510 * set:
2511 <filteredset
2511 <filteredset
2512 <baseset- [0, 1, 2]>,
2512 <baseset- [0, 1, 2]>,
2513 <contains 'glob:*'>>
2513 <contains 'glob:*'>>
2514 2
2514 2
2515 1
2515 1
2516 0
2516 0
2517
2517
2518 test sort revset
2518 test sort revset
2519 --------------------------------------------
2519 --------------------------------------------
2520
2520
2521 test when adding two unordered revsets
2521 test when adding two unordered revsets
2522
2522
2523 $ log 'sort(keyword(issue) or modifies(b))'
2523 $ log 'sort(keyword(issue) or modifies(b))'
2524 4
2524 4
2525 6
2525 6
2526
2526
2527 test when sorting a reversed collection in the same way it is
2527 test when sorting a reversed collection in the same way it is
2528
2528
2529 $ log 'sort(reverse(all()), -rev)'
2529 $ log 'sort(reverse(all()), -rev)'
2530 9
2530 9
2531 8
2531 8
2532 7
2532 7
2533 6
2533 6
2534 5
2534 5
2535 4
2535 4
2536 3
2536 3
2537 2
2537 2
2538 1
2538 1
2539 0
2539 0
2540
2540
2541 test when sorting a reversed collection
2541 test when sorting a reversed collection
2542
2542
2543 $ log 'sort(reverse(all()), rev)'
2543 $ log 'sort(reverse(all()), rev)'
2544 0
2544 0
2545 1
2545 1
2546 2
2546 2
2547 3
2547 3
2548 4
2548 4
2549 5
2549 5
2550 6
2550 6
2551 7
2551 7
2552 8
2552 8
2553 9
2553 9
2554
2554
2555
2555
2556 test sorting two sorted collections in different orders
2556 test sorting two sorted collections in different orders
2557
2557
2558 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2558 $ log 'sort(outgoing() or reverse(removes(a)), rev)'
2559 2
2559 2
2560 6
2560 6
2561 8
2561 8
2562 9
2562 9
2563
2563
2564 test sorting two sorted collections in different orders backwards
2564 test sorting two sorted collections in different orders backwards
2565
2565
2566 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2566 $ log 'sort(outgoing() or reverse(removes(a)), -rev)'
2567 9
2567 9
2568 8
2568 8
2569 6
2569 6
2570 2
2570 2
2571
2571
2572 test empty sort key which is noop
2572 test empty sort key which is noop
2573
2573
2574 $ log 'sort(0 + 2 + 1, "")'
2574 $ log 'sort(0 + 2 + 1, "")'
2575 0
2575 0
2576 2
2576 2
2577 1
2577 1
2578
2578
2579 test invalid sort keys
2579 test invalid sort keys
2580
2580
2581 $ log 'sort(all(), -invalid)'
2581 $ log 'sort(all(), -invalid)'
2582 hg: parse error: unknown sort key '-invalid'
2582 hg: parse error: unknown sort key '-invalid'
2583 [255]
2583 [255]
2584
2584
2585 $ cd ..
2585 $ cd ..
2586
2586
2587 test sorting by multiple keys including variable-length strings
2587 test sorting by multiple keys including variable-length strings
2588
2588
2589 $ hg init sorting
2589 $ hg init sorting
2590 $ cd sorting
2590 $ cd sorting
2591 $ cat <<EOF >> .hg/hgrc
2591 $ cat <<EOF >> .hg/hgrc
2592 > [ui]
2592 > [ui]
2593 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2593 > logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
2594 > [templatealias]
2594 > [templatealias]
2595 > p5(s) = pad(s, 5)
2595 > p5(s) = pad(s, 5)
2596 > EOF
2596 > EOF
2597 $ hg branch -qf b12
2597 $ hg branch -qf b12
2598 $ hg ci -m m111 -u u112 -d '111 10800'
2598 $ hg ci -m m111 -u u112 -d '111 10800'
2599 $ hg branch -qf b11
2599 $ hg branch -qf b11
2600 $ hg ci -m m12 -u u111 -d '112 7200'
2600 $ hg ci -m m12 -u u111 -d '112 7200'
2601 $ hg branch -qf b111
2601 $ hg branch -qf b111
2602 $ hg ci -m m11 -u u12 -d '111 3600'
2602 $ hg ci -m m11 -u u12 -d '111 3600'
2603 $ hg branch -qf b112
2603 $ hg branch -qf b112
2604 $ hg ci -m m111 -u u11 -d '120 0'
2604 $ hg ci -m m111 -u u11 -d '120 0'
2605 $ hg branch -qf b111
2605 $ hg branch -qf b111
2606 $ hg ci -m m112 -u u111 -d '110 14400'
2606 $ hg ci -m m112 -u u111 -d '110 14400'
2607 created new head
2607 created new head
2608
2608
2609 compare revisions (has fast path):
2609 compare revisions (has fast path):
2610
2610
2611 $ hg log -r 'sort(all(), rev)'
2611 $ hg log -r 'sort(all(), rev)'
2612 0 b12 m111 u112 111 10800
2612 0 b12 m111 u112 111 10800
2613 1 b11 m12 u111 112 7200
2613 1 b11 m12 u111 112 7200
2614 2 b111 m11 u12 111 3600
2614 2 b111 m11 u12 111 3600
2615 3 b112 m111 u11 120 0
2615 3 b112 m111 u11 120 0
2616 4 b111 m112 u111 110 14400
2616 4 b111 m112 u111 110 14400
2617
2617
2618 $ hg log -r 'sort(all(), -rev)'
2618 $ hg log -r 'sort(all(), -rev)'
2619 4 b111 m112 u111 110 14400
2619 4 b111 m112 u111 110 14400
2620 3 b112 m111 u11 120 0
2620 3 b112 m111 u11 120 0
2621 2 b111 m11 u12 111 3600
2621 2 b111 m11 u12 111 3600
2622 1 b11 m12 u111 112 7200
2622 1 b11 m12 u111 112 7200
2623 0 b12 m111 u112 111 10800
2623 0 b12 m111 u112 111 10800
2624
2624
2625 compare variable-length strings (issue5218):
2625 compare variable-length strings (issue5218):
2626
2626
2627 $ hg log -r 'sort(all(), branch)'
2627 $ hg log -r 'sort(all(), branch)'
2628 1 b11 m12 u111 112 7200
2628 1 b11 m12 u111 112 7200
2629 2 b111 m11 u12 111 3600
2629 2 b111 m11 u12 111 3600
2630 4 b111 m112 u111 110 14400
2630 4 b111 m112 u111 110 14400
2631 3 b112 m111 u11 120 0
2631 3 b112 m111 u11 120 0
2632 0 b12 m111 u112 111 10800
2632 0 b12 m111 u112 111 10800
2633
2633
2634 $ hg log -r 'sort(all(), -branch)'
2634 $ hg log -r 'sort(all(), -branch)'
2635 0 b12 m111 u112 111 10800
2635 0 b12 m111 u112 111 10800
2636 3 b112 m111 u11 120 0
2636 3 b112 m111 u11 120 0
2637 2 b111 m11 u12 111 3600
2637 2 b111 m11 u12 111 3600
2638 4 b111 m112 u111 110 14400
2638 4 b111 m112 u111 110 14400
2639 1 b11 m12 u111 112 7200
2639 1 b11 m12 u111 112 7200
2640
2640
2641 $ hg log -r 'sort(all(), desc)'
2641 $ hg log -r 'sort(all(), desc)'
2642 2 b111 m11 u12 111 3600
2642 2 b111 m11 u12 111 3600
2643 0 b12 m111 u112 111 10800
2643 0 b12 m111 u112 111 10800
2644 3 b112 m111 u11 120 0
2644 3 b112 m111 u11 120 0
2645 4 b111 m112 u111 110 14400
2645 4 b111 m112 u111 110 14400
2646 1 b11 m12 u111 112 7200
2646 1 b11 m12 u111 112 7200
2647
2647
2648 $ hg log -r 'sort(all(), -desc)'
2648 $ hg log -r 'sort(all(), -desc)'
2649 1 b11 m12 u111 112 7200
2649 1 b11 m12 u111 112 7200
2650 4 b111 m112 u111 110 14400
2650 4 b111 m112 u111 110 14400
2651 0 b12 m111 u112 111 10800
2651 0 b12 m111 u112 111 10800
2652 3 b112 m111 u11 120 0
2652 3 b112 m111 u11 120 0
2653 2 b111 m11 u12 111 3600
2653 2 b111 m11 u12 111 3600
2654
2654
2655 $ hg log -r 'sort(all(), user)'
2655 $ hg log -r 'sort(all(), user)'
2656 3 b112 m111 u11 120 0
2656 3 b112 m111 u11 120 0
2657 1 b11 m12 u111 112 7200
2657 1 b11 m12 u111 112 7200
2658 4 b111 m112 u111 110 14400
2658 4 b111 m112 u111 110 14400
2659 0 b12 m111 u112 111 10800
2659 0 b12 m111 u112 111 10800
2660 2 b111 m11 u12 111 3600
2660 2 b111 m11 u12 111 3600
2661
2661
2662 $ hg log -r 'sort(all(), -user)'
2662 $ hg log -r 'sort(all(), -user)'
2663 2 b111 m11 u12 111 3600
2663 2 b111 m11 u12 111 3600
2664 0 b12 m111 u112 111 10800
2664 0 b12 m111 u112 111 10800
2665 1 b11 m12 u111 112 7200
2665 1 b11 m12 u111 112 7200
2666 4 b111 m112 u111 110 14400
2666 4 b111 m112 u111 110 14400
2667 3 b112 m111 u11 120 0
2667 3 b112 m111 u11 120 0
2668
2668
2669 compare dates (tz offset should have no effect):
2669 compare dates (tz offset should have no effect):
2670
2670
2671 $ hg log -r 'sort(all(), date)'
2671 $ hg log -r 'sort(all(), date)'
2672 4 b111 m112 u111 110 14400
2672 4 b111 m112 u111 110 14400
2673 0 b12 m111 u112 111 10800
2673 0 b12 m111 u112 111 10800
2674 2 b111 m11 u12 111 3600
2674 2 b111 m11 u12 111 3600
2675 1 b11 m12 u111 112 7200
2675 1 b11 m12 u111 112 7200
2676 3 b112 m111 u11 120 0
2676 3 b112 m111 u11 120 0
2677
2677
2678 $ hg log -r 'sort(all(), -date)'
2678 $ hg log -r 'sort(all(), -date)'
2679 3 b112 m111 u11 120 0
2679 3 b112 m111 u11 120 0
2680 1 b11 m12 u111 112 7200
2680 1 b11 m12 u111 112 7200
2681 0 b12 m111 u112 111 10800
2681 0 b12 m111 u112 111 10800
2682 2 b111 m11 u12 111 3600
2682 2 b111 m11 u12 111 3600
2683 4 b111 m112 u111 110 14400
2683 4 b111 m112 u111 110 14400
2684
2684
2685 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2685 be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
2686 because '-k' reverses the comparison, not the list itself:
2686 because '-k' reverses the comparison, not the list itself:
2687
2687
2688 $ hg log -r 'sort(0 + 2, date)'
2688 $ hg log -r 'sort(0 + 2, date)'
2689 0 b12 m111 u112 111 10800
2689 0 b12 m111 u112 111 10800
2690 2 b111 m11 u12 111 3600
2690 2 b111 m11 u12 111 3600
2691
2691
2692 $ hg log -r 'sort(0 + 2, -date)'
2692 $ hg log -r 'sort(0 + 2, -date)'
2693 0 b12 m111 u112 111 10800
2693 0 b12 m111 u112 111 10800
2694 2 b111 m11 u12 111 3600
2694 2 b111 m11 u12 111 3600
2695
2695
2696 $ hg log -r 'reverse(sort(0 + 2, date))'
2696 $ hg log -r 'reverse(sort(0 + 2, date))'
2697 2 b111 m11 u12 111 3600
2697 2 b111 m11 u12 111 3600
2698 0 b12 m111 u112 111 10800
2698 0 b12 m111 u112 111 10800
2699
2699
2700 sort by multiple keys:
2700 sort by multiple keys:
2701
2701
2702 $ hg log -r 'sort(all(), "branch -rev")'
2702 $ hg log -r 'sort(all(), "branch -rev")'
2703 1 b11 m12 u111 112 7200
2703 1 b11 m12 u111 112 7200
2704 4 b111 m112 u111 110 14400
2704 4 b111 m112 u111 110 14400
2705 2 b111 m11 u12 111 3600
2705 2 b111 m11 u12 111 3600
2706 3 b112 m111 u11 120 0
2706 3 b112 m111 u11 120 0
2707 0 b12 m111 u112 111 10800
2707 0 b12 m111 u112 111 10800
2708
2708
2709 $ hg log -r 'sort(all(), "-desc -date")'
2709 $ hg log -r 'sort(all(), "-desc -date")'
2710 1 b11 m12 u111 112 7200
2710 1 b11 m12 u111 112 7200
2711 4 b111 m112 u111 110 14400
2711 4 b111 m112 u111 110 14400
2712 3 b112 m111 u11 120 0
2712 3 b112 m111 u11 120 0
2713 0 b12 m111 u112 111 10800
2713 0 b12 m111 u112 111 10800
2714 2 b111 m11 u12 111 3600
2714 2 b111 m11 u12 111 3600
2715
2715
2716 $ hg log -r 'sort(all(), "user -branch date rev")'
2716 $ hg log -r 'sort(all(), "user -branch date rev")'
2717 3 b112 m111 u11 120 0
2717 3 b112 m111 u11 120 0
2718 4 b111 m112 u111 110 14400
2718 4 b111 m112 u111 110 14400
2719 1 b11 m12 u111 112 7200
2719 1 b11 m12 u111 112 7200
2720 0 b12 m111 u112 111 10800
2720 0 b12 m111 u112 111 10800
2721 2 b111 m11 u12 111 3600
2721 2 b111 m11 u12 111 3600
2722
2722
2723 toposort prioritises graph branches
2723 toposort prioritises graph branches
2724
2724
2725 $ hg up 2
2725 $ hg up 2
2726 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2726 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2727 $ touch a
2727 $ touch a
2728 $ hg addremove
2728 $ hg addremove
2729 adding a
2729 adding a
2730 $ hg ci -m 't1' -u 'tu' -d '130 0'
2730 $ hg ci -m 't1' -u 'tu' -d '130 0'
2731 created new head
2731 created new head
2732 $ echo 'a' >> a
2732 $ echo 'a' >> a
2733 $ hg ci -m 't2' -u 'tu' -d '130 0'
2733 $ hg ci -m 't2' -u 'tu' -d '130 0'
2734 $ hg book book1
2734 $ hg book book1
2735 $ hg up 4
2735 $ hg up 4
2736 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2736 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2737 (leaving bookmark book1)
2737 (leaving bookmark book1)
2738 $ touch a
2738 $ touch a
2739 $ hg addremove
2739 $ hg addremove
2740 adding a
2740 adding a
2741 $ hg ci -m 't3' -u 'tu' -d '130 0'
2741 $ hg ci -m 't3' -u 'tu' -d '130 0'
2742
2742
2743 $ hg log -r 'sort(all(), topo)'
2743 $ hg log -r 'sort(all(), topo)'
2744 7 b111 t3 tu 130 0
2744 7 b111 t3 tu 130 0
2745 4 b111 m112 u111 110 14400
2745 4 b111 m112 u111 110 14400
2746 3 b112 m111 u11 120 0
2746 3 b112 m111 u11 120 0
2747 6 b111 t2 tu 130 0
2747 6 b111 t2 tu 130 0
2748 5 b111 t1 tu 130 0
2748 5 b111 t1 tu 130 0
2749 2 b111 m11 u12 111 3600
2749 2 b111 m11 u12 111 3600
2750 1 b11 m12 u111 112 7200
2750 1 b11 m12 u111 112 7200
2751 0 b12 m111 u112 111 10800
2751 0 b12 m111 u112 111 10800
2752
2752
2753 $ hg log -r 'sort(all(), -topo)'
2753 $ hg log -r 'sort(all(), -topo)'
2754 0 b12 m111 u112 111 10800
2754 0 b12 m111 u112 111 10800
2755 1 b11 m12 u111 112 7200
2755 1 b11 m12 u111 112 7200
2756 2 b111 m11 u12 111 3600
2756 2 b111 m11 u12 111 3600
2757 5 b111 t1 tu 130 0
2757 5 b111 t1 tu 130 0
2758 6 b111 t2 tu 130 0
2758 6 b111 t2 tu 130 0
2759 3 b112 m111 u11 120 0
2759 3 b112 m111 u11 120 0
2760 4 b111 m112 u111 110 14400
2760 4 b111 m112 u111 110 14400
2761 7 b111 t3 tu 130 0
2761 7 b111 t3 tu 130 0
2762
2762
2763 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2763 $ hg log -r 'sort(all(), topo, topo.firstbranch=book1)'
2764 6 b111 t2 tu 130 0
2764 6 b111 t2 tu 130 0
2765 5 b111 t1 tu 130 0
2765 5 b111 t1 tu 130 0
2766 7 b111 t3 tu 130 0
2766 7 b111 t3 tu 130 0
2767 4 b111 m112 u111 110 14400
2767 4 b111 m112 u111 110 14400
2768 3 b112 m111 u11 120 0
2768 3 b112 m111 u11 120 0
2769 2 b111 m11 u12 111 3600
2769 2 b111 m11 u12 111 3600
2770 1 b11 m12 u111 112 7200
2770 1 b11 m12 u111 112 7200
2771 0 b12 m111 u112 111 10800
2771 0 b12 m111 u112 111 10800
2772
2772
2773 topographical sorting can't be combined with other sort keys, and you can't
2773 topographical sorting can't be combined with other sort keys, and you can't
2774 use the topo.firstbranch option when topo sort is not active:
2774 use the topo.firstbranch option when topo sort is not active:
2775
2775
2776 $ hg log -r 'sort(all(), "topo user")'
2776 $ hg log -r 'sort(all(), "topo user")'
2777 hg: parse error: topo sort order cannot be combined with other sort keys
2777 hg: parse error: topo sort order cannot be combined with other sort keys
2778 [255]
2778 [255]
2779
2779
2780 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2780 $ hg log -r 'sort(all(), user, topo.firstbranch=book1)'
2781 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2781 hg: parse error: topo.firstbranch can only be used when using the topo sort key
2782 [255]
2782 [255]
2783
2783
2784 topo.firstbranch should accept any kind of expressions:
2784 topo.firstbranch should accept any kind of expressions:
2785
2785
2786 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2786 $ hg log -r 'sort(0, topo, topo.firstbranch=(book1))'
2787 0 b12 m111 u112 111 10800
2787 0 b12 m111 u112 111 10800
2788
2788
2789 $ cd ..
2789 $ cd ..
2790 $ cd repo
2790 $ cd repo
2791
2791
2792 test multiline revset with errors
2792 test multiline revset with errors
2793
2793
2794 $ echo > multiline-revset
2794 $ echo > multiline-revset
2795 $ echo '. +' >> multiline-revset
2795 $ echo '. +' >> multiline-revset
2796 $ echo '.^ +' >> multiline-revset
2796 $ echo '.^ +' >> multiline-revset
2797 $ hg log -r "`cat multiline-revset`"
2797 $ hg log -r "`cat multiline-revset`"
2798 hg: parse error at 9: not a prefix: end
2798 hg: parse error at 9: not a prefix: end
2799 ( . + .^ +
2799 ( . + .^ +
2800 ^ here)
2800 ^ here)
2801 [255]
2801 [255]
2802 $ hg debugrevspec -v 'revset(first(rev(0)))' -p all
2802 $ hg debugrevspec -v 'revset(first(rev(0)))' -p all
2803 * parsed:
2803 * parsed:
2804 (func
2804 (func
2805 (symbol 'revset')
2805 (symbol 'revset')
2806 (func
2806 (func
2807 (symbol 'first')
2807 (symbol 'first')
2808 (func
2808 (func
2809 (symbol 'rev')
2809 (symbol 'rev')
2810 (symbol '0'))))
2810 (symbol '0'))))
2811 * expanded:
2811 * expanded:
2812 (func
2812 (func
2813 (symbol 'revset')
2813 (symbol 'revset')
2814 (func
2814 (func
2815 (symbol 'first')
2815 (symbol 'first')
2816 (func
2816 (func
2817 (symbol 'rev')
2817 (symbol 'rev')
2818 (symbol '0'))))
2818 (symbol '0'))))
2819 * concatenated:
2819 * concatenated:
2820 (func
2820 (func
2821 (symbol 'revset')
2821 (symbol 'revset')
2822 (func
2822 (func
2823 (symbol 'first')
2823 (symbol 'first')
2824 (func
2824 (func
2825 (symbol 'rev')
2825 (symbol 'rev')
2826 (symbol '0'))))
2826 (symbol '0'))))
2827 * analyzed:
2827 * analyzed:
2828 (func
2828 (func
2829 (symbol 'first')
2829 (symbol 'first')
2830 (func
2830 (func
2831 (symbol 'rev')
2831 (symbol 'rev')
2832 (symbol '0')))
2832 (symbol '0')))
2833 * optimized:
2833 * optimized:
2834 (func
2834 (func
2835 (symbol 'first')
2835 (symbol 'first')
2836 (func
2836 (func
2837 (symbol 'rev')
2837 (symbol 'rev')
2838 (symbol '0')))
2838 (symbol '0')))
2839 * set:
2839 * set:
2840 <baseset+ [0]>
2840 <baseset+ [0]>
2841 0
2841 0
General Comments 0
You need to be logged in to leave comments. Login now