##// END OF EJS Templates
debugfileset: backport --show-stage option from debugrevspec...
Yuya Nishihara -
r38837:1d1c1645 default
parent child Browse files
Show More
@@ -1,3224 +1,3248 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 sshpeer,
73 sshpeer,
74 sslutil,
74 sslutil,
75 streamclone,
75 streamclone,
76 templater,
76 templater,
77 treediscovery,
77 treediscovery,
78 upgrade,
78 upgrade,
79 url as urlmod,
79 url as urlmod,
80 util,
80 util,
81 vfs as vfsmod,
81 vfs as vfsmod,
82 wireprotoframing,
82 wireprotoframing,
83 wireprotoserver,
83 wireprotoserver,
84 wireprotov2peer,
84 wireprotov2peer,
85 )
85 )
86 from .utils import (
86 from .utils import (
87 dateutil,
87 dateutil,
88 procutil,
88 procutil,
89 stringutil,
89 stringutil,
90 )
90 )
91
91
92 release = lockmod.release
92 release = lockmod.release
93
93
94 command = registrar.command()
94 command = registrar.command()
95
95
96 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
96 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
97 def debugancestor(ui, repo, *args):
97 def debugancestor(ui, repo, *args):
98 """find the ancestor revision of two revisions in a given index"""
98 """find the ancestor revision of two revisions in a given index"""
99 if len(args) == 3:
99 if len(args) == 3:
100 index, rev1, rev2 = args
100 index, rev1, rev2 = args
101 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
101 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
102 lookup = r.lookup
102 lookup = r.lookup
103 elif len(args) == 2:
103 elif len(args) == 2:
104 if not repo:
104 if not repo:
105 raise error.Abort(_('there is no Mercurial repository here '
105 raise error.Abort(_('there is no Mercurial repository here '
106 '(.hg not found)'))
106 '(.hg not found)'))
107 rev1, rev2 = args
107 rev1, rev2 = args
108 r = repo.changelog
108 r = repo.changelog
109 lookup = repo.lookup
109 lookup = repo.lookup
110 else:
110 else:
111 raise error.Abort(_('either two or three arguments required'))
111 raise error.Abort(_('either two or three arguments required'))
112 a = r.ancestor(lookup(rev1), lookup(rev2))
112 a = r.ancestor(lookup(rev1), lookup(rev2))
113 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
113 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
114
114
115 @command('debugapplystreamclonebundle', [], 'FILE')
115 @command('debugapplystreamclonebundle', [], 'FILE')
116 def debugapplystreamclonebundle(ui, repo, fname):
116 def debugapplystreamclonebundle(ui, repo, fname):
117 """apply a stream clone bundle file"""
117 """apply a stream clone bundle file"""
118 f = hg.openpath(ui, fname)
118 f = hg.openpath(ui, fname)
119 gen = exchange.readbundle(ui, f, fname)
119 gen = exchange.readbundle(ui, f, fname)
120 gen.apply(repo)
120 gen.apply(repo)
121
121
122 @command('debugbuilddag',
122 @command('debugbuilddag',
123 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
123 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
124 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
124 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
125 ('n', 'new-file', None, _('add new file at each rev'))],
125 ('n', 'new-file', None, _('add new file at each rev'))],
126 _('[OPTION]... [TEXT]'))
126 _('[OPTION]... [TEXT]'))
127 def debugbuilddag(ui, repo, text=None,
127 def debugbuilddag(ui, repo, text=None,
128 mergeable_file=False,
128 mergeable_file=False,
129 overwritten_file=False,
129 overwritten_file=False,
130 new_file=False):
130 new_file=False):
131 """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
132
132
133 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
134 command line.
134 command line.
135
135
136 Elements:
136 Elements:
137
137
138 - "+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
139 - "." is a single node based on the current default parent
139 - "." is a single node based on the current default parent
140 - "$" resets the default parent to null (implied at the start);
140 - "$" resets the default parent to null (implied at the start);
141 otherwise the default parent is always the last node created
141 otherwise the default parent is always the last node created
142 - "<p" sets the default parent to the backref p
142 - "<p" sets the default parent to the backref p
143 - "*p" is a fork at parent p, which is a backref
143 - "*p" is a fork at parent p, which is a backref
144 - "*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
145 - "/p2" is a merge of the preceding node and p2
145 - "/p2" is a merge of the preceding node and p2
146 - ":tag" defines a local tag for the preceding node
146 - ":tag" defines a local tag for the preceding node
147 - "@branch" sets the named branch for subsequent nodes
147 - "@branch" sets the named branch for subsequent nodes
148 - "#...\\n" is a comment up to the end of the line
148 - "#...\\n" is a comment up to the end of the line
149
149
150 Whitespace between the above elements is ignored.
150 Whitespace between the above elements is ignored.
151
151
152 A backref is either
152 A backref is either
153
153
154 - 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
155 node, or
155 node, or
156 - 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
157 - empty to denote the default parent.
157 - empty to denote the default parent.
158
158
159 All string valued-elements are either strictly alphanumeric, or must
159 All string valued-elements are either strictly alphanumeric, or must
160 be enclosed in double quotes ("..."), with "\\" as escape character.
160 be enclosed in double quotes ("..."), with "\\" as escape character.
161 """
161 """
162
162
163 if text is None:
163 if text is None:
164 ui.status(_("reading DAG from stdin\n"))
164 ui.status(_("reading DAG from stdin\n"))
165 text = ui.fin.read()
165 text = ui.fin.read()
166
166
167 cl = repo.changelog
167 cl = repo.changelog
168 if len(cl) > 0:
168 if len(cl) > 0:
169 raise error.Abort(_('repository is not empty'))
169 raise error.Abort(_('repository is not empty'))
170
170
171 # determine number of revs in DAG
171 # determine number of revs in DAG
172 total = 0
172 total = 0
173 for type, data in dagparser.parsedag(text):
173 for type, data in dagparser.parsedag(text):
174 if type == 'n':
174 if type == 'n':
175 total += 1
175 total += 1
176
176
177 if mergeable_file:
177 if mergeable_file:
178 linesperrev = 2
178 linesperrev = 2
179 # make a file with k lines per rev
179 # make a file with k lines per rev
180 initialmergedlines = ['%d' % i
180 initialmergedlines = ['%d' % i
181 for i in pycompat.xrange(0, total * linesperrev)]
181 for i in pycompat.xrange(0, total * linesperrev)]
182 initialmergedlines.append("")
182 initialmergedlines.append("")
183
183
184 tags = []
184 tags = []
185 progress = ui.makeprogress(_('building'), unit=_('revisions'),
185 progress = ui.makeprogress(_('building'), unit=_('revisions'),
186 total=total)
186 total=total)
187 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
187 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
188 at = -1
188 at = -1
189 atbranch = 'default'
189 atbranch = 'default'
190 nodeids = []
190 nodeids = []
191 id = 0
191 id = 0
192 progress.update(id)
192 progress.update(id)
193 for type, data in dagparser.parsedag(text):
193 for type, data in dagparser.parsedag(text):
194 if type == 'n':
194 if type == 'n':
195 ui.note(('node %s\n' % pycompat.bytestr(data)))
195 ui.note(('node %s\n' % pycompat.bytestr(data)))
196 id, ps = data
196 id, ps = data
197
197
198 files = []
198 files = []
199 filecontent = {}
199 filecontent = {}
200
200
201 p2 = None
201 p2 = None
202 if mergeable_file:
202 if mergeable_file:
203 fn = "mf"
203 fn = "mf"
204 p1 = repo[ps[0]]
204 p1 = repo[ps[0]]
205 if len(ps) > 1:
205 if len(ps) > 1:
206 p2 = repo[ps[1]]
206 p2 = repo[ps[1]]
207 pa = p1.ancestor(p2)
207 pa = p1.ancestor(p2)
208 base, local, other = [x[fn].data() for x in (pa, p1,
208 base, local, other = [x[fn].data() for x in (pa, p1,
209 p2)]
209 p2)]
210 m3 = simplemerge.Merge3Text(base, local, other)
210 m3 = simplemerge.Merge3Text(base, local, other)
211 ml = [l.strip() for l in m3.merge_lines()]
211 ml = [l.strip() for l in m3.merge_lines()]
212 ml.append("")
212 ml.append("")
213 elif at > 0:
213 elif at > 0:
214 ml = p1[fn].data().split("\n")
214 ml = p1[fn].data().split("\n")
215 else:
215 else:
216 ml = initialmergedlines
216 ml = initialmergedlines
217 ml[id * linesperrev] += " r%i" % id
217 ml[id * linesperrev] += " r%i" % id
218 mergedtext = "\n".join(ml)
218 mergedtext = "\n".join(ml)
219 files.append(fn)
219 files.append(fn)
220 filecontent[fn] = mergedtext
220 filecontent[fn] = mergedtext
221
221
222 if overwritten_file:
222 if overwritten_file:
223 fn = "of"
223 fn = "of"
224 files.append(fn)
224 files.append(fn)
225 filecontent[fn] = "r%i\n" % id
225 filecontent[fn] = "r%i\n" % id
226
226
227 if new_file:
227 if new_file:
228 fn = "nf%i" % id
228 fn = "nf%i" % id
229 files.append(fn)
229 files.append(fn)
230 filecontent[fn] = "r%i\n" % id
230 filecontent[fn] = "r%i\n" % id
231 if len(ps) > 1:
231 if len(ps) > 1:
232 if not p2:
232 if not p2:
233 p2 = repo[ps[1]]
233 p2 = repo[ps[1]]
234 for fn in p2:
234 for fn in p2:
235 if fn.startswith("nf"):
235 if fn.startswith("nf"):
236 files.append(fn)
236 files.append(fn)
237 filecontent[fn] = p2[fn].data()
237 filecontent[fn] = p2[fn].data()
238
238
239 def fctxfn(repo, cx, path):
239 def fctxfn(repo, cx, path):
240 if path in filecontent:
240 if path in filecontent:
241 return context.memfilectx(repo, cx, path,
241 return context.memfilectx(repo, cx, path,
242 filecontent[path])
242 filecontent[path])
243 return None
243 return None
244
244
245 if len(ps) == 0 or ps[0] < 0:
245 if len(ps) == 0 or ps[0] < 0:
246 pars = [None, None]
246 pars = [None, None]
247 elif len(ps) == 1:
247 elif len(ps) == 1:
248 pars = [nodeids[ps[0]], None]
248 pars = [nodeids[ps[0]], None]
249 else:
249 else:
250 pars = [nodeids[p] for p in ps]
250 pars = [nodeids[p] for p in ps]
251 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
251 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
252 date=(id, 0),
252 date=(id, 0),
253 user="debugbuilddag",
253 user="debugbuilddag",
254 extra={'branch': atbranch})
254 extra={'branch': atbranch})
255 nodeid = repo.commitctx(cx)
255 nodeid = repo.commitctx(cx)
256 nodeids.append(nodeid)
256 nodeids.append(nodeid)
257 at = id
257 at = id
258 elif type == 'l':
258 elif type == 'l':
259 id, name = data
259 id, name = data
260 ui.note(('tag %s\n' % name))
260 ui.note(('tag %s\n' % name))
261 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
261 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
262 elif type == 'a':
262 elif type == 'a':
263 ui.note(('branch %s\n' % data))
263 ui.note(('branch %s\n' % data))
264 atbranch = data
264 atbranch = data
265 progress.update(id)
265 progress.update(id)
266
266
267 if tags:
267 if tags:
268 repo.vfs.write("localtags", "".join(tags))
268 repo.vfs.write("localtags", "".join(tags))
269
269
270 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
270 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
271 indent_string = ' ' * indent
271 indent_string = ' ' * indent
272 if all:
272 if all:
273 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
273 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
274 % indent_string)
274 % indent_string)
275
275
276 def showchunks(named):
276 def showchunks(named):
277 ui.write("\n%s%s\n" % (indent_string, named))
277 ui.write("\n%s%s\n" % (indent_string, named))
278 for deltadata in gen.deltaiter():
278 for deltadata in gen.deltaiter():
279 node, p1, p2, cs, deltabase, delta, flags = deltadata
279 node, p1, p2, cs, deltabase, delta, flags = deltadata
280 ui.write("%s%s %s %s %s %s %d\n" %
280 ui.write("%s%s %s %s %s %s %d\n" %
281 (indent_string, hex(node), hex(p1), hex(p2),
281 (indent_string, hex(node), hex(p1), hex(p2),
282 hex(cs), hex(deltabase), len(delta)))
282 hex(cs), hex(deltabase), len(delta)))
283
283
284 chunkdata = gen.changelogheader()
284 chunkdata = gen.changelogheader()
285 showchunks("changelog")
285 showchunks("changelog")
286 chunkdata = gen.manifestheader()
286 chunkdata = gen.manifestheader()
287 showchunks("manifest")
287 showchunks("manifest")
288 for chunkdata in iter(gen.filelogheader, {}):
288 for chunkdata in iter(gen.filelogheader, {}):
289 fname = chunkdata['filename']
289 fname = chunkdata['filename']
290 showchunks(fname)
290 showchunks(fname)
291 else:
291 else:
292 if isinstance(gen, bundle2.unbundle20):
292 if isinstance(gen, bundle2.unbundle20):
293 raise error.Abort(_('use debugbundle2 for this file'))
293 raise error.Abort(_('use debugbundle2 for this file'))
294 chunkdata = gen.changelogheader()
294 chunkdata = gen.changelogheader()
295 for deltadata in gen.deltaiter():
295 for deltadata in gen.deltaiter():
296 node, p1, p2, cs, deltabase, delta, flags = deltadata
296 node, p1, p2, cs, deltabase, delta, flags = deltadata
297 ui.write("%s%s\n" % (indent_string, hex(node)))
297 ui.write("%s%s\n" % (indent_string, hex(node)))
298
298
299 def _debugobsmarkers(ui, part, indent=0, **opts):
299 def _debugobsmarkers(ui, part, indent=0, **opts):
300 """display version and markers contained in 'data'"""
300 """display version and markers contained in 'data'"""
301 opts = pycompat.byteskwargs(opts)
301 opts = pycompat.byteskwargs(opts)
302 data = part.read()
302 data = part.read()
303 indent_string = ' ' * indent
303 indent_string = ' ' * indent
304 try:
304 try:
305 version, markers = obsolete._readmarkers(data)
305 version, markers = obsolete._readmarkers(data)
306 except error.UnknownVersion as exc:
306 except error.UnknownVersion as exc:
307 msg = "%sunsupported version: %s (%d bytes)\n"
307 msg = "%sunsupported version: %s (%d bytes)\n"
308 msg %= indent_string, exc.version, len(data)
308 msg %= indent_string, exc.version, len(data)
309 ui.write(msg)
309 ui.write(msg)
310 else:
310 else:
311 msg = "%sversion: %d (%d bytes)\n"
311 msg = "%sversion: %d (%d bytes)\n"
312 msg %= indent_string, version, len(data)
312 msg %= indent_string, version, len(data)
313 ui.write(msg)
313 ui.write(msg)
314 fm = ui.formatter('debugobsolete', opts)
314 fm = ui.formatter('debugobsolete', opts)
315 for rawmarker in sorted(markers):
315 for rawmarker in sorted(markers):
316 m = obsutil.marker(None, rawmarker)
316 m = obsutil.marker(None, rawmarker)
317 fm.startitem()
317 fm.startitem()
318 fm.plain(indent_string)
318 fm.plain(indent_string)
319 cmdutil.showmarker(fm, m)
319 cmdutil.showmarker(fm, m)
320 fm.end()
320 fm.end()
321
321
322 def _debugphaseheads(ui, data, indent=0):
322 def _debugphaseheads(ui, data, indent=0):
323 """display version and markers contained in 'data'"""
323 """display version and markers contained in 'data'"""
324 indent_string = ' ' * indent
324 indent_string = ' ' * indent
325 headsbyphase = phases.binarydecode(data)
325 headsbyphase = phases.binarydecode(data)
326 for phase in phases.allphases:
326 for phase in phases.allphases:
327 for head in headsbyphase[phase]:
327 for head in headsbyphase[phase]:
328 ui.write(indent_string)
328 ui.write(indent_string)
329 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
329 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
330
330
331 def _quasirepr(thing):
331 def _quasirepr(thing):
332 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
332 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
333 return '{%s}' % (
333 return '{%s}' % (
334 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
334 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
335 return pycompat.bytestr(repr(thing))
335 return pycompat.bytestr(repr(thing))
336
336
337 def _debugbundle2(ui, gen, all=None, **opts):
337 def _debugbundle2(ui, gen, all=None, **opts):
338 """lists the contents of a bundle2"""
338 """lists the contents of a bundle2"""
339 if not isinstance(gen, bundle2.unbundle20):
339 if not isinstance(gen, bundle2.unbundle20):
340 raise error.Abort(_('not a bundle2 file'))
340 raise error.Abort(_('not a bundle2 file'))
341 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
341 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
342 parttypes = opts.get(r'part_type', [])
342 parttypes = opts.get(r'part_type', [])
343 for part in gen.iterparts():
343 for part in gen.iterparts():
344 if parttypes and part.type not in parttypes:
344 if parttypes and part.type not in parttypes:
345 continue
345 continue
346 msg = '%s -- %s (mandatory: %r)\n'
346 msg = '%s -- %s (mandatory: %r)\n'
347 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
347 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
348 if part.type == 'changegroup':
348 if part.type == 'changegroup':
349 version = part.params.get('version', '01')
349 version = part.params.get('version', '01')
350 cg = changegroup.getunbundler(version, part, 'UN')
350 cg = changegroup.getunbundler(version, part, 'UN')
351 if not ui.quiet:
351 if not ui.quiet:
352 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
352 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
353 if part.type == 'obsmarkers':
353 if part.type == 'obsmarkers':
354 if not ui.quiet:
354 if not ui.quiet:
355 _debugobsmarkers(ui, part, indent=4, **opts)
355 _debugobsmarkers(ui, part, indent=4, **opts)
356 if part.type == 'phase-heads':
356 if part.type == 'phase-heads':
357 if not ui.quiet:
357 if not ui.quiet:
358 _debugphaseheads(ui, part, indent=4)
358 _debugphaseheads(ui, part, indent=4)
359
359
360 @command('debugbundle',
360 @command('debugbundle',
361 [('a', 'all', None, _('show all details')),
361 [('a', 'all', None, _('show all details')),
362 ('', 'part-type', [], _('show only the named part type')),
362 ('', 'part-type', [], _('show only the named part type')),
363 ('', 'spec', None, _('print the bundlespec of the bundle'))],
363 ('', 'spec', None, _('print the bundlespec of the bundle'))],
364 _('FILE'),
364 _('FILE'),
365 norepo=True)
365 norepo=True)
366 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
366 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
367 """lists the contents of a bundle"""
367 """lists the contents of a bundle"""
368 with hg.openpath(ui, bundlepath) as f:
368 with hg.openpath(ui, bundlepath) as f:
369 if spec:
369 if spec:
370 spec = exchange.getbundlespec(ui, f)
370 spec = exchange.getbundlespec(ui, f)
371 ui.write('%s\n' % spec)
371 ui.write('%s\n' % spec)
372 return
372 return
373
373
374 gen = exchange.readbundle(ui, f, bundlepath)
374 gen = exchange.readbundle(ui, f, bundlepath)
375 if isinstance(gen, bundle2.unbundle20):
375 if isinstance(gen, bundle2.unbundle20):
376 return _debugbundle2(ui, gen, all=all, **opts)
376 return _debugbundle2(ui, gen, all=all, **opts)
377 _debugchangegroup(ui, gen, all=all, **opts)
377 _debugchangegroup(ui, gen, all=all, **opts)
378
378
379 @command('debugcapabilities',
379 @command('debugcapabilities',
380 [], _('PATH'),
380 [], _('PATH'),
381 norepo=True)
381 norepo=True)
382 def debugcapabilities(ui, path, **opts):
382 def debugcapabilities(ui, path, **opts):
383 """lists the capabilities of a remote peer"""
383 """lists the capabilities of a remote peer"""
384 opts = pycompat.byteskwargs(opts)
384 opts = pycompat.byteskwargs(opts)
385 peer = hg.peer(ui, opts, path)
385 peer = hg.peer(ui, opts, path)
386 caps = peer.capabilities()
386 caps = peer.capabilities()
387 ui.write(('Main capabilities:\n'))
387 ui.write(('Main capabilities:\n'))
388 for c in sorted(caps):
388 for c in sorted(caps):
389 ui.write((' %s\n') % c)
389 ui.write((' %s\n') % c)
390 b2caps = bundle2.bundle2caps(peer)
390 b2caps = bundle2.bundle2caps(peer)
391 if b2caps:
391 if b2caps:
392 ui.write(('Bundle2 capabilities:\n'))
392 ui.write(('Bundle2 capabilities:\n'))
393 for key, values in sorted(b2caps.iteritems()):
393 for key, values in sorted(b2caps.iteritems()):
394 ui.write((' %s\n') % key)
394 ui.write((' %s\n') % key)
395 for v in values:
395 for v in values:
396 ui.write((' %s\n') % v)
396 ui.write((' %s\n') % v)
397
397
398 @command('debugcheckstate', [], '')
398 @command('debugcheckstate', [], '')
399 def debugcheckstate(ui, repo):
399 def debugcheckstate(ui, repo):
400 """validate the correctness of the current dirstate"""
400 """validate the correctness of the current dirstate"""
401 parent1, parent2 = repo.dirstate.parents()
401 parent1, parent2 = repo.dirstate.parents()
402 m1 = repo[parent1].manifest()
402 m1 = repo[parent1].manifest()
403 m2 = repo[parent2].manifest()
403 m2 = repo[parent2].manifest()
404 errors = 0
404 errors = 0
405 for f in repo.dirstate:
405 for f in repo.dirstate:
406 state = repo.dirstate[f]
406 state = repo.dirstate[f]
407 if state in "nr" and f not in m1:
407 if state in "nr" and f not in m1:
408 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
408 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
409 errors += 1
409 errors += 1
410 if state in "a" and f in m1:
410 if state in "a" and f in m1:
411 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
411 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
412 errors += 1
412 errors += 1
413 if state in "m" and f not in m1 and f not in m2:
413 if state in "m" and f not in m1 and f not in m2:
414 ui.warn(_("%s in state %s, but not in either manifest\n") %
414 ui.warn(_("%s in state %s, but not in either manifest\n") %
415 (f, state))
415 (f, state))
416 errors += 1
416 errors += 1
417 for f in m1:
417 for f in m1:
418 state = repo.dirstate[f]
418 state = repo.dirstate[f]
419 if state not in "nrm":
419 if state not in "nrm":
420 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
420 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
421 errors += 1
421 errors += 1
422 if errors:
422 if errors:
423 error = _(".hg/dirstate inconsistent with current parent's manifest")
423 error = _(".hg/dirstate inconsistent with current parent's manifest")
424 raise error.Abort(error)
424 raise error.Abort(error)
425
425
426 @command('debugcolor',
426 @command('debugcolor',
427 [('', 'style', None, _('show all configured styles'))],
427 [('', 'style', None, _('show all configured styles'))],
428 'hg debugcolor')
428 'hg debugcolor')
429 def debugcolor(ui, repo, **opts):
429 def debugcolor(ui, repo, **opts):
430 """show available color, effects or style"""
430 """show available color, effects or style"""
431 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
431 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
432 if opts.get(r'style'):
432 if opts.get(r'style'):
433 return _debugdisplaystyle(ui)
433 return _debugdisplaystyle(ui)
434 else:
434 else:
435 return _debugdisplaycolor(ui)
435 return _debugdisplaycolor(ui)
436
436
437 def _debugdisplaycolor(ui):
437 def _debugdisplaycolor(ui):
438 ui = ui.copy()
438 ui = ui.copy()
439 ui._styles.clear()
439 ui._styles.clear()
440 for effect in color._activeeffects(ui).keys():
440 for effect in color._activeeffects(ui).keys():
441 ui._styles[effect] = effect
441 ui._styles[effect] = effect
442 if ui._terminfoparams:
442 if ui._terminfoparams:
443 for k, v in ui.configitems('color'):
443 for k, v in ui.configitems('color'):
444 if k.startswith('color.'):
444 if k.startswith('color.'):
445 ui._styles[k] = k[6:]
445 ui._styles[k] = k[6:]
446 elif k.startswith('terminfo.'):
446 elif k.startswith('terminfo.'):
447 ui._styles[k] = k[9:]
447 ui._styles[k] = k[9:]
448 ui.write(_('available colors:\n'))
448 ui.write(_('available colors:\n'))
449 # sort label with a '_' after the other to group '_background' entry.
449 # sort label with a '_' after the other to group '_background' entry.
450 items = sorted(ui._styles.items(),
450 items = sorted(ui._styles.items(),
451 key=lambda i: ('_' in i[0], i[0], i[1]))
451 key=lambda i: ('_' in i[0], i[0], i[1]))
452 for colorname, label in items:
452 for colorname, label in items:
453 ui.write(('%s\n') % colorname, label=label)
453 ui.write(('%s\n') % colorname, label=label)
454
454
455 def _debugdisplaystyle(ui):
455 def _debugdisplaystyle(ui):
456 ui.write(_('available style:\n'))
456 ui.write(_('available style:\n'))
457 if not ui._styles:
457 if not ui._styles:
458 return
458 return
459 width = max(len(s) for s in ui._styles)
459 width = max(len(s) for s in ui._styles)
460 for label, effects in sorted(ui._styles.items()):
460 for label, effects in sorted(ui._styles.items()):
461 ui.write('%s' % label, label=label)
461 ui.write('%s' % label, label=label)
462 if effects:
462 if effects:
463 # 50
463 # 50
464 ui.write(': ')
464 ui.write(': ')
465 ui.write(' ' * (max(0, width - len(label))))
465 ui.write(' ' * (max(0, width - len(label))))
466 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
466 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
467 ui.write('\n')
467 ui.write('\n')
468
468
469 @command('debugcreatestreamclonebundle', [], 'FILE')
469 @command('debugcreatestreamclonebundle', [], 'FILE')
470 def debugcreatestreamclonebundle(ui, repo, fname):
470 def debugcreatestreamclonebundle(ui, repo, fname):
471 """create a stream clone bundle file
471 """create a stream clone bundle file
472
472
473 Stream bundles are special bundles that are essentially archives of
473 Stream bundles are special bundles that are essentially archives of
474 revlog files. They are commonly used for cloning very quickly.
474 revlog files. They are commonly used for cloning very quickly.
475 """
475 """
476 # TODO we may want to turn this into an abort when this functionality
476 # TODO we may want to turn this into an abort when this functionality
477 # is moved into `hg bundle`.
477 # is moved into `hg bundle`.
478 if phases.hassecret(repo):
478 if phases.hassecret(repo):
479 ui.warn(_('(warning: stream clone bundle will contain secret '
479 ui.warn(_('(warning: stream clone bundle will contain secret '
480 'revisions)\n'))
480 'revisions)\n'))
481
481
482 requirements, gen = streamclone.generatebundlev1(repo)
482 requirements, gen = streamclone.generatebundlev1(repo)
483 changegroup.writechunks(ui, gen, fname)
483 changegroup.writechunks(ui, gen, fname)
484
484
485 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
485 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
486
486
487 @command('debugdag',
487 @command('debugdag',
488 [('t', 'tags', None, _('use tags as labels')),
488 [('t', 'tags', None, _('use tags as labels')),
489 ('b', 'branches', None, _('annotate with branch names')),
489 ('b', 'branches', None, _('annotate with branch names')),
490 ('', 'dots', None, _('use dots for runs')),
490 ('', 'dots', None, _('use dots for runs')),
491 ('s', 'spaces', None, _('separate elements by spaces'))],
491 ('s', 'spaces', None, _('separate elements by spaces'))],
492 _('[OPTION]... [FILE [REV]...]'),
492 _('[OPTION]... [FILE [REV]...]'),
493 optionalrepo=True)
493 optionalrepo=True)
494 def debugdag(ui, repo, file_=None, *revs, **opts):
494 def debugdag(ui, repo, file_=None, *revs, **opts):
495 """format the changelog or an index DAG as a concise textual description
495 """format the changelog or an index DAG as a concise textual description
496
496
497 If you pass a revlog index, the revlog's DAG is emitted. If you list
497 If you pass a revlog index, the revlog's DAG is emitted. If you list
498 revision numbers, they get labeled in the output as rN.
498 revision numbers, they get labeled in the output as rN.
499
499
500 Otherwise, the changelog DAG of the current repo is emitted.
500 Otherwise, the changelog DAG of the current repo is emitted.
501 """
501 """
502 spaces = opts.get(r'spaces')
502 spaces = opts.get(r'spaces')
503 dots = opts.get(r'dots')
503 dots = opts.get(r'dots')
504 if file_:
504 if file_:
505 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
505 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
506 file_)
506 file_)
507 revs = set((int(r) for r in revs))
507 revs = set((int(r) for r in revs))
508 def events():
508 def events():
509 for r in rlog:
509 for r in rlog:
510 yield 'n', (r, list(p for p in rlog.parentrevs(r)
510 yield 'n', (r, list(p for p in rlog.parentrevs(r)
511 if p != -1))
511 if p != -1))
512 if r in revs:
512 if r in revs:
513 yield 'l', (r, "r%i" % r)
513 yield 'l', (r, "r%i" % r)
514 elif repo:
514 elif repo:
515 cl = repo.changelog
515 cl = repo.changelog
516 tags = opts.get(r'tags')
516 tags = opts.get(r'tags')
517 branches = opts.get(r'branches')
517 branches = opts.get(r'branches')
518 if tags:
518 if tags:
519 labels = {}
519 labels = {}
520 for l, n in repo.tags().items():
520 for l, n in repo.tags().items():
521 labels.setdefault(cl.rev(n), []).append(l)
521 labels.setdefault(cl.rev(n), []).append(l)
522 def events():
522 def events():
523 b = "default"
523 b = "default"
524 for r in cl:
524 for r in cl:
525 if branches:
525 if branches:
526 newb = cl.read(cl.node(r))[5]['branch']
526 newb = cl.read(cl.node(r))[5]['branch']
527 if newb != b:
527 if newb != b:
528 yield 'a', newb
528 yield 'a', newb
529 b = newb
529 b = newb
530 yield 'n', (r, list(p for p in cl.parentrevs(r)
530 yield 'n', (r, list(p for p in cl.parentrevs(r)
531 if p != -1))
531 if p != -1))
532 if tags:
532 if tags:
533 ls = labels.get(r)
533 ls = labels.get(r)
534 if ls:
534 if ls:
535 for l in ls:
535 for l in ls:
536 yield 'l', (r, l)
536 yield 'l', (r, l)
537 else:
537 else:
538 raise error.Abort(_('need repo for changelog dag'))
538 raise error.Abort(_('need repo for changelog dag'))
539
539
540 for line in dagparser.dagtextlines(events(),
540 for line in dagparser.dagtextlines(events(),
541 addspaces=spaces,
541 addspaces=spaces,
542 wraplabels=True,
542 wraplabels=True,
543 wrapannotations=True,
543 wrapannotations=True,
544 wrapnonlinear=dots,
544 wrapnonlinear=dots,
545 usedots=dots,
545 usedots=dots,
546 maxlinewidth=70):
546 maxlinewidth=70):
547 ui.write(line)
547 ui.write(line)
548 ui.write("\n")
548 ui.write("\n")
549
549
550 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
550 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
551 def debugdata(ui, repo, file_, rev=None, **opts):
551 def debugdata(ui, repo, file_, rev=None, **opts):
552 """dump the contents of a data file revision"""
552 """dump the contents of a data file revision"""
553 opts = pycompat.byteskwargs(opts)
553 opts = pycompat.byteskwargs(opts)
554 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
554 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
555 if rev is not None:
555 if rev is not None:
556 raise error.CommandError('debugdata', _('invalid arguments'))
556 raise error.CommandError('debugdata', _('invalid arguments'))
557 file_, rev = None, file_
557 file_, rev = None, file_
558 elif rev is None:
558 elif rev is None:
559 raise error.CommandError('debugdata', _('invalid arguments'))
559 raise error.CommandError('debugdata', _('invalid arguments'))
560 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
560 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
561 try:
561 try:
562 ui.write(r.revision(r.lookup(rev), raw=True))
562 ui.write(r.revision(r.lookup(rev), raw=True))
563 except KeyError:
563 except KeyError:
564 raise error.Abort(_('invalid revision identifier %s') % rev)
564 raise error.Abort(_('invalid revision identifier %s') % rev)
565
565
566 @command('debugdate',
566 @command('debugdate',
567 [('e', 'extended', None, _('try extended date formats'))],
567 [('e', 'extended', None, _('try extended date formats'))],
568 _('[-e] DATE [RANGE]'),
568 _('[-e] DATE [RANGE]'),
569 norepo=True, optionalrepo=True)
569 norepo=True, optionalrepo=True)
570 def debugdate(ui, date, range=None, **opts):
570 def debugdate(ui, date, range=None, **opts):
571 """parse and display a date"""
571 """parse and display a date"""
572 if opts[r"extended"]:
572 if opts[r"extended"]:
573 d = dateutil.parsedate(date, util.extendeddateformats)
573 d = dateutil.parsedate(date, util.extendeddateformats)
574 else:
574 else:
575 d = dateutil.parsedate(date)
575 d = dateutil.parsedate(date)
576 ui.write(("internal: %d %d\n") % d)
576 ui.write(("internal: %d %d\n") % d)
577 ui.write(("standard: %s\n") % dateutil.datestr(d))
577 ui.write(("standard: %s\n") % dateutil.datestr(d))
578 if range:
578 if range:
579 m = dateutil.matchdate(range)
579 m = dateutil.matchdate(range)
580 ui.write(("match: %s\n") % m(d[0]))
580 ui.write(("match: %s\n") % m(d[0]))
581
581
582 @command('debugdeltachain',
582 @command('debugdeltachain',
583 cmdutil.debugrevlogopts + cmdutil.formatteropts,
583 cmdutil.debugrevlogopts + cmdutil.formatteropts,
584 _('-c|-m|FILE'),
584 _('-c|-m|FILE'),
585 optionalrepo=True)
585 optionalrepo=True)
586 def debugdeltachain(ui, repo, file_=None, **opts):
586 def debugdeltachain(ui, repo, file_=None, **opts):
587 """dump information about delta chains in a revlog
587 """dump information about delta chains in a revlog
588
588
589 Output can be templatized. Available template keywords are:
589 Output can be templatized. Available template keywords are:
590
590
591 :``rev``: revision number
591 :``rev``: revision number
592 :``chainid``: delta chain identifier (numbered by unique base)
592 :``chainid``: delta chain identifier (numbered by unique base)
593 :``chainlen``: delta chain length to this revision
593 :``chainlen``: delta chain length to this revision
594 :``prevrev``: previous revision in delta chain
594 :``prevrev``: previous revision in delta chain
595 :``deltatype``: role of delta / how it was computed
595 :``deltatype``: role of delta / how it was computed
596 :``compsize``: compressed size of revision
596 :``compsize``: compressed size of revision
597 :``uncompsize``: uncompressed size of revision
597 :``uncompsize``: uncompressed size of revision
598 :``chainsize``: total size of compressed revisions in chain
598 :``chainsize``: total size of compressed revisions in chain
599 :``chainratio``: total chain size divided by uncompressed revision size
599 :``chainratio``: total chain size divided by uncompressed revision size
600 (new delta chains typically start at ratio 2.00)
600 (new delta chains typically start at ratio 2.00)
601 :``lindist``: linear distance from base revision in delta chain to end
601 :``lindist``: linear distance from base revision in delta chain to end
602 of this revision
602 of this revision
603 :``extradist``: total size of revisions not part of this delta chain from
603 :``extradist``: total size of revisions not part of this delta chain from
604 base of delta chain to end of this revision; a measurement
604 base of delta chain to end of this revision; a measurement
605 of how much extra data we need to read/seek across to read
605 of how much extra data we need to read/seek across to read
606 the delta chain for this revision
606 the delta chain for this revision
607 :``extraratio``: extradist divided by chainsize; another representation of
607 :``extraratio``: extradist divided by chainsize; another representation of
608 how much unrelated data is needed to load this delta chain
608 how much unrelated data is needed to load this delta chain
609
609
610 If the repository is configured to use the sparse read, additional keywords
610 If the repository is configured to use the sparse read, additional keywords
611 are available:
611 are available:
612
612
613 :``readsize``: total size of data read from the disk for a revision
613 :``readsize``: total size of data read from the disk for a revision
614 (sum of the sizes of all the blocks)
614 (sum of the sizes of all the blocks)
615 :``largestblock``: size of the largest block of data read from the disk
615 :``largestblock``: size of the largest block of data read from the disk
616 :``readdensity``: density of useful bytes in the data read from the disk
616 :``readdensity``: density of useful bytes in the data read from the disk
617 :``srchunks``: in how many data hunks the whole revision would be read
617 :``srchunks``: in how many data hunks the whole revision would be read
618
618
619 The sparse read can be enabled with experimental.sparse-read = True
619 The sparse read can be enabled with experimental.sparse-read = True
620 """
620 """
621 opts = pycompat.byteskwargs(opts)
621 opts = pycompat.byteskwargs(opts)
622 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
622 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
623 index = r.index
623 index = r.index
624 start = r.start
624 start = r.start
625 length = r.length
625 length = r.length
626 generaldelta = r.version & revlog.FLAG_GENERALDELTA
626 generaldelta = r.version & revlog.FLAG_GENERALDELTA
627 withsparseread = getattr(r, '_withsparseread', False)
627 withsparseread = getattr(r, '_withsparseread', False)
628
628
629 def revinfo(rev):
629 def revinfo(rev):
630 e = index[rev]
630 e = index[rev]
631 compsize = e[1]
631 compsize = e[1]
632 uncompsize = e[2]
632 uncompsize = e[2]
633 chainsize = 0
633 chainsize = 0
634
634
635 if generaldelta:
635 if generaldelta:
636 if e[3] == e[5]:
636 if e[3] == e[5]:
637 deltatype = 'p1'
637 deltatype = 'p1'
638 elif e[3] == e[6]:
638 elif e[3] == e[6]:
639 deltatype = 'p2'
639 deltatype = 'p2'
640 elif e[3] == rev - 1:
640 elif e[3] == rev - 1:
641 deltatype = 'prev'
641 deltatype = 'prev'
642 elif e[3] == rev:
642 elif e[3] == rev:
643 deltatype = 'base'
643 deltatype = 'base'
644 else:
644 else:
645 deltatype = 'other'
645 deltatype = 'other'
646 else:
646 else:
647 if e[3] == rev:
647 if e[3] == rev:
648 deltatype = 'base'
648 deltatype = 'base'
649 else:
649 else:
650 deltatype = 'prev'
650 deltatype = 'prev'
651
651
652 chain = r._deltachain(rev)[0]
652 chain = r._deltachain(rev)[0]
653 for iterrev in chain:
653 for iterrev in chain:
654 e = index[iterrev]
654 e = index[iterrev]
655 chainsize += e[1]
655 chainsize += e[1]
656
656
657 return compsize, uncompsize, deltatype, chain, chainsize
657 return compsize, uncompsize, deltatype, chain, chainsize
658
658
659 fm = ui.formatter('debugdeltachain', opts)
659 fm = ui.formatter('debugdeltachain', opts)
660
660
661 fm.plain(' rev chain# chainlen prev delta '
661 fm.plain(' rev chain# chainlen prev delta '
662 'size rawsize chainsize ratio lindist extradist '
662 'size rawsize chainsize ratio lindist extradist '
663 'extraratio')
663 'extraratio')
664 if withsparseread:
664 if withsparseread:
665 fm.plain(' readsize largestblk rddensity srchunks')
665 fm.plain(' readsize largestblk rddensity srchunks')
666 fm.plain('\n')
666 fm.plain('\n')
667
667
668 chainbases = {}
668 chainbases = {}
669 for rev in r:
669 for rev in r:
670 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
670 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
671 chainbase = chain[0]
671 chainbase = chain[0]
672 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
672 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
673 basestart = start(chainbase)
673 basestart = start(chainbase)
674 revstart = start(rev)
674 revstart = start(rev)
675 lineardist = revstart + comp - basestart
675 lineardist = revstart + comp - basestart
676 extradist = lineardist - chainsize
676 extradist = lineardist - chainsize
677 try:
677 try:
678 prevrev = chain[-2]
678 prevrev = chain[-2]
679 except IndexError:
679 except IndexError:
680 prevrev = -1
680 prevrev = -1
681
681
682 if uncomp != 0:
682 if uncomp != 0:
683 chainratio = float(chainsize) / float(uncomp)
683 chainratio = float(chainsize) / float(uncomp)
684 else:
684 else:
685 chainratio = chainsize
685 chainratio = chainsize
686
686
687 if chainsize != 0:
687 if chainsize != 0:
688 extraratio = float(extradist) / float(chainsize)
688 extraratio = float(extradist) / float(chainsize)
689 else:
689 else:
690 extraratio = extradist
690 extraratio = extradist
691
691
692 fm.startitem()
692 fm.startitem()
693 fm.write('rev chainid chainlen prevrev deltatype compsize '
693 fm.write('rev chainid chainlen prevrev deltatype compsize '
694 'uncompsize chainsize chainratio lindist extradist '
694 'uncompsize chainsize chainratio lindist extradist '
695 'extraratio',
695 'extraratio',
696 '%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',
697 rev, chainid, len(chain), prevrev, deltatype, comp,
697 rev, chainid, len(chain), prevrev, deltatype, comp,
698 uncomp, chainsize, chainratio, lineardist, extradist,
698 uncomp, chainsize, chainratio, lineardist, extradist,
699 extraratio,
699 extraratio,
700 rev=rev, chainid=chainid, chainlen=len(chain),
700 rev=rev, chainid=chainid, chainlen=len(chain),
701 prevrev=prevrev, deltatype=deltatype, compsize=comp,
701 prevrev=prevrev, deltatype=deltatype, compsize=comp,
702 uncompsize=uncomp, chainsize=chainsize,
702 uncompsize=uncomp, chainsize=chainsize,
703 chainratio=chainratio, lindist=lineardist,
703 chainratio=chainratio, lindist=lineardist,
704 extradist=extradist, extraratio=extraratio)
704 extradist=extradist, extraratio=extraratio)
705 if withsparseread:
705 if withsparseread:
706 readsize = 0
706 readsize = 0
707 largestblock = 0
707 largestblock = 0
708 srchunks = 0
708 srchunks = 0
709
709
710 for revschunk in revlog._slicechunk(r, chain):
710 for revschunk in revlog._slicechunk(r, chain):
711 srchunks += 1
711 srchunks += 1
712 blkend = start(revschunk[-1]) + length(revschunk[-1])
712 blkend = start(revschunk[-1]) + length(revschunk[-1])
713 blksize = blkend - start(revschunk[0])
713 blksize = blkend - start(revschunk[0])
714
714
715 readsize += blksize
715 readsize += blksize
716 if largestblock < blksize:
716 if largestblock < blksize:
717 largestblock = blksize
717 largestblock = blksize
718
718
719 if readsize:
719 if readsize:
720 readdensity = float(chainsize) / float(readsize)
720 readdensity = float(chainsize) / float(readsize)
721 else:
721 else:
722 readdensity = 1
722 readdensity = 1
723
723
724 fm.write('readsize largestblock readdensity srchunks',
724 fm.write('readsize largestblock readdensity srchunks',
725 ' %10d %10d %9.5f %8d',
725 ' %10d %10d %9.5f %8d',
726 readsize, largestblock, readdensity, srchunks,
726 readsize, largestblock, readdensity, srchunks,
727 readsize=readsize, largestblock=largestblock,
727 readsize=readsize, largestblock=largestblock,
728 readdensity=readdensity, srchunks=srchunks)
728 readdensity=readdensity, srchunks=srchunks)
729
729
730 fm.plain('\n')
730 fm.plain('\n')
731
731
732 fm.end()
732 fm.end()
733
733
734 @command('debugdirstate|debugstate',
734 @command('debugdirstate|debugstate',
735 [('', 'nodates', None, _('do not display the saved mtime')),
735 [('', 'nodates', None, _('do not display the saved mtime')),
736 ('', 'datesort', None, _('sort by saved mtime'))],
736 ('', 'datesort', None, _('sort by saved mtime'))],
737 _('[OPTION]...'))
737 _('[OPTION]...'))
738 def debugstate(ui, repo, **opts):
738 def debugstate(ui, repo, **opts):
739 """show the contents of the current dirstate"""
739 """show the contents of the current dirstate"""
740
740
741 nodates = opts.get(r'nodates')
741 nodates = opts.get(r'nodates')
742 datesort = opts.get(r'datesort')
742 datesort = opts.get(r'datesort')
743
743
744 timestr = ""
744 timestr = ""
745 if datesort:
745 if datesort:
746 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
746 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
747 else:
747 else:
748 keyfunc = None # sort by filename
748 keyfunc = None # sort by filename
749 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
749 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
750 if ent[3] == -1:
750 if ent[3] == -1:
751 timestr = 'unset '
751 timestr = 'unset '
752 elif nodates:
752 elif nodates:
753 timestr = 'set '
753 timestr = 'set '
754 else:
754 else:
755 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
755 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
756 time.localtime(ent[3]))
756 time.localtime(ent[3]))
757 timestr = encoding.strtolocal(timestr)
757 timestr = encoding.strtolocal(timestr)
758 if ent[1] & 0o20000:
758 if ent[1] & 0o20000:
759 mode = 'lnk'
759 mode = 'lnk'
760 else:
760 else:
761 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
761 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
762 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
762 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
763 for f in repo.dirstate.copies():
763 for f in repo.dirstate.copies():
764 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
764 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
765
765
766 @command('debugdiscovery',
766 @command('debugdiscovery',
767 [('', 'old', None, _('use old-style discovery')),
767 [('', 'old', None, _('use old-style discovery')),
768 ('', 'nonheads', None,
768 ('', 'nonheads', None,
769 _('use old-style discovery with non-heads included')),
769 _('use old-style discovery with non-heads included')),
770 ('', 'rev', [], 'restrict discovery to this set of revs'),
770 ('', 'rev', [], 'restrict discovery to this set of revs'),
771 ] + cmdutil.remoteopts,
771 ] + cmdutil.remoteopts,
772 _('[--rev REV] [OTHER]'))
772 _('[--rev REV] [OTHER]'))
773 def debugdiscovery(ui, repo, remoteurl="default", **opts):
773 def debugdiscovery(ui, repo, remoteurl="default", **opts):
774 """runs the changeset discovery protocol in isolation"""
774 """runs the changeset discovery protocol in isolation"""
775 opts = pycompat.byteskwargs(opts)
775 opts = pycompat.byteskwargs(opts)
776 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
776 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
777 remote = hg.peer(repo, opts, remoteurl)
777 remote = hg.peer(repo, opts, remoteurl)
778 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
778 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
779
779
780 # make sure tests are repeatable
780 # make sure tests are repeatable
781 random.seed(12323)
781 random.seed(12323)
782
782
783 def doit(pushedrevs, remoteheads, remote=remote):
783 def doit(pushedrevs, remoteheads, remote=remote):
784 if opts.get('old'):
784 if opts.get('old'):
785 if not util.safehasattr(remote, 'branches'):
785 if not util.safehasattr(remote, 'branches'):
786 # enable in-client legacy support
786 # enable in-client legacy support
787 remote = localrepo.locallegacypeer(remote.local())
787 remote = localrepo.locallegacypeer(remote.local())
788 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
788 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
789 force=True)
789 force=True)
790 common = set(common)
790 common = set(common)
791 if not opts.get('nonheads'):
791 if not opts.get('nonheads'):
792 ui.write(("unpruned common: %s\n") %
792 ui.write(("unpruned common: %s\n") %
793 " ".join(sorted(short(n) for n in common)))
793 " ".join(sorted(short(n) for n in common)))
794 dag = dagutil.revlogdag(repo.changelog)
794 dag = dagutil.revlogdag(repo.changelog)
795 all = dag.ancestorset(dag.internalizeall(common))
795 all = dag.ancestorset(dag.internalizeall(common))
796 common = dag.externalizeall(dag.headsetofconnecteds(all))
796 common = dag.externalizeall(dag.headsetofconnecteds(all))
797 else:
797 else:
798 nodes = None
798 nodes = None
799 if pushedrevs:
799 if pushedrevs:
800 revs = scmutil.revrange(repo, pushedrevs)
800 revs = scmutil.revrange(repo, pushedrevs)
801 nodes = [repo[r].node() for r in revs]
801 nodes = [repo[r].node() for r in revs]
802 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
802 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
803 ancestorsof=nodes)
803 ancestorsof=nodes)
804 common = set(common)
804 common = set(common)
805 rheads = set(hds)
805 rheads = set(hds)
806 lheads = set(repo.heads())
806 lheads = set(repo.heads())
807 ui.write(("common heads: %s\n") %
807 ui.write(("common heads: %s\n") %
808 " ".join(sorted(short(n) for n in common)))
808 " ".join(sorted(short(n) for n in common)))
809 if lheads <= common:
809 if lheads <= common:
810 ui.write(("local is subset\n"))
810 ui.write(("local is subset\n"))
811 elif rheads <= common:
811 elif rheads <= common:
812 ui.write(("remote is subset\n"))
812 ui.write(("remote is subset\n"))
813
813
814 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
814 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
815 localrevs = opts['rev']
815 localrevs = opts['rev']
816 doit(localrevs, remoterevs)
816 doit(localrevs, remoterevs)
817
817
818 _chunksize = 4 << 10
818 _chunksize = 4 << 10
819
819
820 @command('debugdownload',
820 @command('debugdownload',
821 [
821 [
822 ('o', 'output', '', _('path')),
822 ('o', 'output', '', _('path')),
823 ],
823 ],
824 optionalrepo=True)
824 optionalrepo=True)
825 def debugdownload(ui, repo, url, output=None, **opts):
825 def debugdownload(ui, repo, url, output=None, **opts):
826 """download a resource using Mercurial logic and config
826 """download a resource using Mercurial logic and config
827 """
827 """
828 fh = urlmod.open(ui, url, output)
828 fh = urlmod.open(ui, url, output)
829
829
830 dest = ui
830 dest = ui
831 if output:
831 if output:
832 dest = open(output, "wb", _chunksize)
832 dest = open(output, "wb", _chunksize)
833 try:
833 try:
834 data = fh.read(_chunksize)
834 data = fh.read(_chunksize)
835 while data:
835 while data:
836 dest.write(data)
836 dest.write(data)
837 data = fh.read(_chunksize)
837 data = fh.read(_chunksize)
838 finally:
838 finally:
839 if output:
839 if output:
840 dest.close()
840 dest.close()
841
841
842 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
842 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
843 def debugextensions(ui, repo, **opts):
843 def debugextensions(ui, repo, **opts):
844 '''show information about active extensions'''
844 '''show information about active extensions'''
845 opts = pycompat.byteskwargs(opts)
845 opts = pycompat.byteskwargs(opts)
846 exts = extensions.extensions(ui)
846 exts = extensions.extensions(ui)
847 hgver = util.version()
847 hgver = util.version()
848 fm = ui.formatter('debugextensions', opts)
848 fm = ui.formatter('debugextensions', opts)
849 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
849 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
850 isinternal = extensions.ismoduleinternal(extmod)
850 isinternal = extensions.ismoduleinternal(extmod)
851 extsource = pycompat.fsencode(extmod.__file__)
851 extsource = pycompat.fsencode(extmod.__file__)
852 if isinternal:
852 if isinternal:
853 exttestedwith = [] # never expose magic string to users
853 exttestedwith = [] # never expose magic string to users
854 else:
854 else:
855 exttestedwith = getattr(extmod, 'testedwith', '').split()
855 exttestedwith = getattr(extmod, 'testedwith', '').split()
856 extbuglink = getattr(extmod, 'buglink', None)
856 extbuglink = getattr(extmod, 'buglink', None)
857
857
858 fm.startitem()
858 fm.startitem()
859
859
860 if ui.quiet or ui.verbose:
860 if ui.quiet or ui.verbose:
861 fm.write('name', '%s\n', extname)
861 fm.write('name', '%s\n', extname)
862 else:
862 else:
863 fm.write('name', '%s', extname)
863 fm.write('name', '%s', extname)
864 if isinternal or hgver in exttestedwith:
864 if isinternal or hgver in exttestedwith:
865 fm.plain('\n')
865 fm.plain('\n')
866 elif not exttestedwith:
866 elif not exttestedwith:
867 fm.plain(_(' (untested!)\n'))
867 fm.plain(_(' (untested!)\n'))
868 else:
868 else:
869 lasttestedversion = exttestedwith[-1]
869 lasttestedversion = exttestedwith[-1]
870 fm.plain(' (%s!)\n' % lasttestedversion)
870 fm.plain(' (%s!)\n' % lasttestedversion)
871
871
872 fm.condwrite(ui.verbose and extsource, 'source',
872 fm.condwrite(ui.verbose and extsource, 'source',
873 _(' location: %s\n'), extsource or "")
873 _(' location: %s\n'), extsource or "")
874
874
875 if ui.verbose:
875 if ui.verbose:
876 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
876 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
877 fm.data(bundled=isinternal)
877 fm.data(bundled=isinternal)
878
878
879 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
879 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
880 _(' tested with: %s\n'),
880 _(' tested with: %s\n'),
881 fm.formatlist(exttestedwith, name='ver'))
881 fm.formatlist(exttestedwith, name='ver'))
882
882
883 fm.condwrite(ui.verbose and extbuglink, 'buglink',
883 fm.condwrite(ui.verbose and extbuglink, 'buglink',
884 _(' bug reporting: %s\n'), extbuglink or "")
884 _(' bug reporting: %s\n'), extbuglink or "")
885
885
886 fm.end()
886 fm.end()
887
887
888 @command('debugfileset',
888 @command('debugfileset',
889 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
889 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
890 ('', 'all-files', False,
890 ('', 'all-files', False,
891 _('test files from all revisions and working directory'))],
891 _('test files from all revisions and working directory')),
892 _('[-r REV] [--all-files] FILESPEC'))
892 ('p', 'show-stage', [],
893 _('print parsed tree at the given stage'), _('NAME'))],
894 _('[-r REV] [--all-files] [OPTION]... FILESPEC'))
893 def debugfileset(ui, repo, expr, **opts):
895 def debugfileset(ui, repo, expr, **opts):
894 '''parse and apply a fileset specification'''
896 '''parse and apply a fileset specification'''
895 opts = pycompat.byteskwargs(opts)
897 opts = pycompat.byteskwargs(opts)
896 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
898 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
897 if ui.verbose:
899
898 tree = fileset.parse(expr)
900 stages = [
899 ui.note(fileset.prettyformat(tree), "\n")
901 ('parsed', pycompat.identity),
902 ]
903 stagenames = set(n for n, f in stages)
904
905 showalways = set()
906 if ui.verbose and not opts['show_stage']:
907 # show parsed tree by --verbose (deprecated)
908 showalways.add('parsed')
909 if opts['show_stage'] == ['all']:
910 showalways.update(stagenames)
911 else:
912 for n in opts['show_stage']:
913 if n not in stagenames:
914 raise error.Abort(_('invalid stage name: %s') % n)
915 showalways.update(opts['show_stage'])
916
917 tree = fileset.parse(expr)
918 for n, f in stages:
919 tree = f(tree)
920 if n in showalways:
921 if opts['show_stage'] or n != 'parsed':
922 ui.write(("* %s:\n") % n)
923 ui.write(fileset.prettyformat(tree), "\n")
900
924
901 files = set()
925 files = set()
902 if opts['all_files']:
926 if opts['all_files']:
903 for r in repo:
927 for r in repo:
904 c = repo[r]
928 c = repo[r]
905 files.update(c.files())
929 files.update(c.files())
906 files.update(c.substate)
930 files.update(c.substate)
907 if opts['all_files'] or ctx.rev() is None:
931 if opts['all_files'] or ctx.rev() is None:
908 wctx = repo[None]
932 wctx = repo[None]
909 files.update(repo.dirstate.walk(scmutil.matchall(repo),
933 files.update(repo.dirstate.walk(scmutil.matchall(repo),
910 subrepos=list(wctx.substate),
934 subrepos=list(wctx.substate),
911 unknown=True, ignored=True))
935 unknown=True, ignored=True))
912 files.update(wctx.substate)
936 files.update(wctx.substate)
913 else:
937 else:
914 files.update(ctx.files())
938 files.update(ctx.files())
915 files.update(ctx.substate)
939 files.update(ctx.substate)
916
940
917 m = ctx.matchfileset(expr)
941 m = ctx.matchfileset(expr)
918 for f in sorted(files):
942 for f in sorted(files):
919 if not m(f):
943 if not m(f):
920 continue
944 continue
921 ui.write("%s\n" % f)
945 ui.write("%s\n" % f)
922
946
923 @command('debugformat',
947 @command('debugformat',
924 [] + cmdutil.formatteropts,
948 [] + cmdutil.formatteropts,
925 _(''))
949 _(''))
926 def debugformat(ui, repo, **opts):
950 def debugformat(ui, repo, **opts):
927 """display format information about the current repository
951 """display format information about the current repository
928
952
929 Use --verbose to get extra information about current config value and
953 Use --verbose to get extra information about current config value and
930 Mercurial default."""
954 Mercurial default."""
931 opts = pycompat.byteskwargs(opts)
955 opts = pycompat.byteskwargs(opts)
932 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
956 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
933 maxvariantlength = max(len('format-variant'), maxvariantlength)
957 maxvariantlength = max(len('format-variant'), maxvariantlength)
934
958
935 def makeformatname(name):
959 def makeformatname(name):
936 return '%s:' + (' ' * (maxvariantlength - len(name)))
960 return '%s:' + (' ' * (maxvariantlength - len(name)))
937
961
938 fm = ui.formatter('debugformat', opts)
962 fm = ui.formatter('debugformat', opts)
939 if fm.isplain():
963 if fm.isplain():
940 def formatvalue(value):
964 def formatvalue(value):
941 if util.safehasattr(value, 'startswith'):
965 if util.safehasattr(value, 'startswith'):
942 return value
966 return value
943 if value:
967 if value:
944 return 'yes'
968 return 'yes'
945 else:
969 else:
946 return 'no'
970 return 'no'
947 else:
971 else:
948 formatvalue = pycompat.identity
972 formatvalue = pycompat.identity
949
973
950 fm.plain('format-variant')
974 fm.plain('format-variant')
951 fm.plain(' ' * (maxvariantlength - len('format-variant')))
975 fm.plain(' ' * (maxvariantlength - len('format-variant')))
952 fm.plain(' repo')
976 fm.plain(' repo')
953 if ui.verbose:
977 if ui.verbose:
954 fm.plain(' config default')
978 fm.plain(' config default')
955 fm.plain('\n')
979 fm.plain('\n')
956 for fv in upgrade.allformatvariant:
980 for fv in upgrade.allformatvariant:
957 fm.startitem()
981 fm.startitem()
958 repovalue = fv.fromrepo(repo)
982 repovalue = fv.fromrepo(repo)
959 configvalue = fv.fromconfig(repo)
983 configvalue = fv.fromconfig(repo)
960
984
961 if repovalue != configvalue:
985 if repovalue != configvalue:
962 namelabel = 'formatvariant.name.mismatchconfig'
986 namelabel = 'formatvariant.name.mismatchconfig'
963 repolabel = 'formatvariant.repo.mismatchconfig'
987 repolabel = 'formatvariant.repo.mismatchconfig'
964 elif repovalue != fv.default:
988 elif repovalue != fv.default:
965 namelabel = 'formatvariant.name.mismatchdefault'
989 namelabel = 'formatvariant.name.mismatchdefault'
966 repolabel = 'formatvariant.repo.mismatchdefault'
990 repolabel = 'formatvariant.repo.mismatchdefault'
967 else:
991 else:
968 namelabel = 'formatvariant.name.uptodate'
992 namelabel = 'formatvariant.name.uptodate'
969 repolabel = 'formatvariant.repo.uptodate'
993 repolabel = 'formatvariant.repo.uptodate'
970
994
971 fm.write('name', makeformatname(fv.name), fv.name,
995 fm.write('name', makeformatname(fv.name), fv.name,
972 label=namelabel)
996 label=namelabel)
973 fm.write('repo', ' %3s', formatvalue(repovalue),
997 fm.write('repo', ' %3s', formatvalue(repovalue),
974 label=repolabel)
998 label=repolabel)
975 if fv.default != configvalue:
999 if fv.default != configvalue:
976 configlabel = 'formatvariant.config.special'
1000 configlabel = 'formatvariant.config.special'
977 else:
1001 else:
978 configlabel = 'formatvariant.config.default'
1002 configlabel = 'formatvariant.config.default'
979 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
1003 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
980 label=configlabel)
1004 label=configlabel)
981 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
1005 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
982 label='formatvariant.default')
1006 label='formatvariant.default')
983 fm.plain('\n')
1007 fm.plain('\n')
984 fm.end()
1008 fm.end()
985
1009
986 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1010 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
987 def debugfsinfo(ui, path="."):
1011 def debugfsinfo(ui, path="."):
988 """show information detected about current filesystem"""
1012 """show information detected about current filesystem"""
989 ui.write(('path: %s\n') % path)
1013 ui.write(('path: %s\n') % path)
990 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
1014 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
991 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1015 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
992 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
1016 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
993 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1017 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
994 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1018 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
995 casesensitive = '(unknown)'
1019 casesensitive = '(unknown)'
996 try:
1020 try:
997 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
1021 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
998 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
1022 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
999 except OSError:
1023 except OSError:
1000 pass
1024 pass
1001 ui.write(('case-sensitive: %s\n') % casesensitive)
1025 ui.write(('case-sensitive: %s\n') % casesensitive)
1002
1026
1003 @command('debuggetbundle',
1027 @command('debuggetbundle',
1004 [('H', 'head', [], _('id of head node'), _('ID')),
1028 [('H', 'head', [], _('id of head node'), _('ID')),
1005 ('C', 'common', [], _('id of common node'), _('ID')),
1029 ('C', 'common', [], _('id of common node'), _('ID')),
1006 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1030 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1007 _('REPO FILE [-H|-C ID]...'),
1031 _('REPO FILE [-H|-C ID]...'),
1008 norepo=True)
1032 norepo=True)
1009 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1033 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1010 """retrieves a bundle from a repo
1034 """retrieves a bundle from a repo
1011
1035
1012 Every ID must be a full-length hex node id string. Saves the bundle to the
1036 Every ID must be a full-length hex node id string. Saves the bundle to the
1013 given file.
1037 given file.
1014 """
1038 """
1015 opts = pycompat.byteskwargs(opts)
1039 opts = pycompat.byteskwargs(opts)
1016 repo = hg.peer(ui, opts, repopath)
1040 repo = hg.peer(ui, opts, repopath)
1017 if not repo.capable('getbundle'):
1041 if not repo.capable('getbundle'):
1018 raise error.Abort("getbundle() not supported by target repository")
1042 raise error.Abort("getbundle() not supported by target repository")
1019 args = {}
1043 args = {}
1020 if common:
1044 if common:
1021 args[r'common'] = [bin(s) for s in common]
1045 args[r'common'] = [bin(s) for s in common]
1022 if head:
1046 if head:
1023 args[r'heads'] = [bin(s) for s in head]
1047 args[r'heads'] = [bin(s) for s in head]
1024 # TODO: get desired bundlecaps from command line.
1048 # TODO: get desired bundlecaps from command line.
1025 args[r'bundlecaps'] = None
1049 args[r'bundlecaps'] = None
1026 bundle = repo.getbundle('debug', **args)
1050 bundle = repo.getbundle('debug', **args)
1027
1051
1028 bundletype = opts.get('type', 'bzip2').lower()
1052 bundletype = opts.get('type', 'bzip2').lower()
1029 btypes = {'none': 'HG10UN',
1053 btypes = {'none': 'HG10UN',
1030 'bzip2': 'HG10BZ',
1054 'bzip2': 'HG10BZ',
1031 'gzip': 'HG10GZ',
1055 'gzip': 'HG10GZ',
1032 'bundle2': 'HG20'}
1056 'bundle2': 'HG20'}
1033 bundletype = btypes.get(bundletype)
1057 bundletype = btypes.get(bundletype)
1034 if bundletype not in bundle2.bundletypes:
1058 if bundletype not in bundle2.bundletypes:
1035 raise error.Abort(_('unknown bundle type specified with --type'))
1059 raise error.Abort(_('unknown bundle type specified with --type'))
1036 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1060 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1037
1061
1038 @command('debugignore', [], '[FILE]')
1062 @command('debugignore', [], '[FILE]')
1039 def debugignore(ui, repo, *files, **opts):
1063 def debugignore(ui, repo, *files, **opts):
1040 """display the combined ignore pattern and information about ignored files
1064 """display the combined ignore pattern and information about ignored files
1041
1065
1042 With no argument display the combined ignore pattern.
1066 With no argument display the combined ignore pattern.
1043
1067
1044 Given space separated file names, shows if the given file is ignored and
1068 Given space separated file names, shows if the given file is ignored and
1045 if so, show the ignore rule (file and line number) that matched it.
1069 if so, show the ignore rule (file and line number) that matched it.
1046 """
1070 """
1047 ignore = repo.dirstate._ignore
1071 ignore = repo.dirstate._ignore
1048 if not files:
1072 if not files:
1049 # Show all the patterns
1073 # Show all the patterns
1050 ui.write("%s\n" % pycompat.byterepr(ignore))
1074 ui.write("%s\n" % pycompat.byterepr(ignore))
1051 else:
1075 else:
1052 m = scmutil.match(repo[None], pats=files)
1076 m = scmutil.match(repo[None], pats=files)
1053 for f in m.files():
1077 for f in m.files():
1054 nf = util.normpath(f)
1078 nf = util.normpath(f)
1055 ignored = None
1079 ignored = None
1056 ignoredata = None
1080 ignoredata = None
1057 if nf != '.':
1081 if nf != '.':
1058 if ignore(nf):
1082 if ignore(nf):
1059 ignored = nf
1083 ignored = nf
1060 ignoredata = repo.dirstate._ignorefileandline(nf)
1084 ignoredata = repo.dirstate._ignorefileandline(nf)
1061 else:
1085 else:
1062 for p in util.finddirs(nf):
1086 for p in util.finddirs(nf):
1063 if ignore(p):
1087 if ignore(p):
1064 ignored = p
1088 ignored = p
1065 ignoredata = repo.dirstate._ignorefileandline(p)
1089 ignoredata = repo.dirstate._ignorefileandline(p)
1066 break
1090 break
1067 if ignored:
1091 if ignored:
1068 if ignored == nf:
1092 if ignored == nf:
1069 ui.write(_("%s is ignored\n") % m.uipath(f))
1093 ui.write(_("%s is ignored\n") % m.uipath(f))
1070 else:
1094 else:
1071 ui.write(_("%s is ignored because of "
1095 ui.write(_("%s is ignored because of "
1072 "containing folder %s\n")
1096 "containing folder %s\n")
1073 % (m.uipath(f), ignored))
1097 % (m.uipath(f), ignored))
1074 ignorefile, lineno, line = ignoredata
1098 ignorefile, lineno, line = ignoredata
1075 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1099 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1076 % (ignorefile, lineno, line))
1100 % (ignorefile, lineno, line))
1077 else:
1101 else:
1078 ui.write(_("%s is not ignored\n") % m.uipath(f))
1102 ui.write(_("%s is not ignored\n") % m.uipath(f))
1079
1103
1080 @command('debugindex', cmdutil.debugrevlogopts +
1104 @command('debugindex', cmdutil.debugrevlogopts +
1081 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1105 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1082 _('[-f FORMAT] -c|-m|FILE'),
1106 _('[-f FORMAT] -c|-m|FILE'),
1083 optionalrepo=True)
1107 optionalrepo=True)
1084 def debugindex(ui, repo, file_=None, **opts):
1108 def debugindex(ui, repo, file_=None, **opts):
1085 """dump the contents of an index file"""
1109 """dump the contents of an index file"""
1086 opts = pycompat.byteskwargs(opts)
1110 opts = pycompat.byteskwargs(opts)
1087 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1111 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1088 format = opts.get('format', 0)
1112 format = opts.get('format', 0)
1089 if format not in (0, 1):
1113 if format not in (0, 1):
1090 raise error.Abort(_("unknown format %d") % format)
1114 raise error.Abort(_("unknown format %d") % format)
1091
1115
1092 if ui.debugflag:
1116 if ui.debugflag:
1093 shortfn = hex
1117 shortfn = hex
1094 else:
1118 else:
1095 shortfn = short
1119 shortfn = short
1096
1120
1097 # There might not be anything in r, so have a sane default
1121 # There might not be anything in r, so have a sane default
1098 idlen = 12
1122 idlen = 12
1099 for i in r:
1123 for i in r:
1100 idlen = len(shortfn(r.node(i)))
1124 idlen = len(shortfn(r.node(i)))
1101 break
1125 break
1102
1126
1103 if format == 0:
1127 if format == 0:
1104 if ui.verbose:
1128 if ui.verbose:
1105 ui.write((" rev offset length linkrev"
1129 ui.write((" rev offset length linkrev"
1106 " %s %s p2\n") % ("nodeid".ljust(idlen),
1130 " %s %s p2\n") % ("nodeid".ljust(idlen),
1107 "p1".ljust(idlen)))
1131 "p1".ljust(idlen)))
1108 else:
1132 else:
1109 ui.write((" rev linkrev %s %s p2\n") % (
1133 ui.write((" rev linkrev %s %s p2\n") % (
1110 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1134 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1111 elif format == 1:
1135 elif format == 1:
1112 if ui.verbose:
1136 if ui.verbose:
1113 ui.write((" rev flag offset length size link p1"
1137 ui.write((" rev flag offset length size link p1"
1114 " p2 %s\n") % "nodeid".rjust(idlen))
1138 " p2 %s\n") % "nodeid".rjust(idlen))
1115 else:
1139 else:
1116 ui.write((" rev flag size link p1 p2 %s\n") %
1140 ui.write((" rev flag size link p1 p2 %s\n") %
1117 "nodeid".rjust(idlen))
1141 "nodeid".rjust(idlen))
1118
1142
1119 for i in r:
1143 for i in r:
1120 node = r.node(i)
1144 node = r.node(i)
1121 if format == 0:
1145 if format == 0:
1122 try:
1146 try:
1123 pp = r.parents(node)
1147 pp = r.parents(node)
1124 except Exception:
1148 except Exception:
1125 pp = [nullid, nullid]
1149 pp = [nullid, nullid]
1126 if ui.verbose:
1150 if ui.verbose:
1127 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1151 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1128 i, r.start(i), r.length(i), r.linkrev(i),
1152 i, r.start(i), r.length(i), r.linkrev(i),
1129 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1153 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1130 else:
1154 else:
1131 ui.write("% 6d % 7d %s %s %s\n" % (
1155 ui.write("% 6d % 7d %s %s %s\n" % (
1132 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1156 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1133 shortfn(pp[1])))
1157 shortfn(pp[1])))
1134 elif format == 1:
1158 elif format == 1:
1135 pr = r.parentrevs(i)
1159 pr = r.parentrevs(i)
1136 if ui.verbose:
1160 if ui.verbose:
1137 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1161 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1138 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1162 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1139 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1163 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1140 else:
1164 else:
1141 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1165 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1142 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1166 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1143 shortfn(node)))
1167 shortfn(node)))
1144
1168
1145 @command('debugindexdot', cmdutil.debugrevlogopts,
1169 @command('debugindexdot', cmdutil.debugrevlogopts,
1146 _('-c|-m|FILE'), optionalrepo=True)
1170 _('-c|-m|FILE'), optionalrepo=True)
1147 def debugindexdot(ui, repo, file_=None, **opts):
1171 def debugindexdot(ui, repo, file_=None, **opts):
1148 """dump an index DAG as a graphviz dot file"""
1172 """dump an index DAG as a graphviz dot file"""
1149 opts = pycompat.byteskwargs(opts)
1173 opts = pycompat.byteskwargs(opts)
1150 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1174 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1151 ui.write(("digraph G {\n"))
1175 ui.write(("digraph G {\n"))
1152 for i in r:
1176 for i in r:
1153 node = r.node(i)
1177 node = r.node(i)
1154 pp = r.parents(node)
1178 pp = r.parents(node)
1155 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1179 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1156 if pp[1] != nullid:
1180 if pp[1] != nullid:
1157 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1181 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1158 ui.write("}\n")
1182 ui.write("}\n")
1159
1183
1160 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1184 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1161 def debuginstall(ui, **opts):
1185 def debuginstall(ui, **opts):
1162 '''test Mercurial installation
1186 '''test Mercurial installation
1163
1187
1164 Returns 0 on success.
1188 Returns 0 on success.
1165 '''
1189 '''
1166 opts = pycompat.byteskwargs(opts)
1190 opts = pycompat.byteskwargs(opts)
1167
1191
1168 def writetemp(contents):
1192 def writetemp(contents):
1169 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
1193 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
1170 f = os.fdopen(fd, r"wb")
1194 f = os.fdopen(fd, r"wb")
1171 f.write(contents)
1195 f.write(contents)
1172 f.close()
1196 f.close()
1173 return name
1197 return name
1174
1198
1175 problems = 0
1199 problems = 0
1176
1200
1177 fm = ui.formatter('debuginstall', opts)
1201 fm = ui.formatter('debuginstall', opts)
1178 fm.startitem()
1202 fm.startitem()
1179
1203
1180 # encoding
1204 # encoding
1181 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1205 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1182 err = None
1206 err = None
1183 try:
1207 try:
1184 codecs.lookup(pycompat.sysstr(encoding.encoding))
1208 codecs.lookup(pycompat.sysstr(encoding.encoding))
1185 except LookupError as inst:
1209 except LookupError as inst:
1186 err = stringutil.forcebytestr(inst)
1210 err = stringutil.forcebytestr(inst)
1187 problems += 1
1211 problems += 1
1188 fm.condwrite(err, 'encodingerror', _(" %s\n"
1212 fm.condwrite(err, 'encodingerror', _(" %s\n"
1189 " (check that your locale is properly set)\n"), err)
1213 " (check that your locale is properly set)\n"), err)
1190
1214
1191 # Python
1215 # Python
1192 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1216 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1193 pycompat.sysexecutable)
1217 pycompat.sysexecutable)
1194 fm.write('pythonver', _("checking Python version (%s)\n"),
1218 fm.write('pythonver', _("checking Python version (%s)\n"),
1195 ("%d.%d.%d" % sys.version_info[:3]))
1219 ("%d.%d.%d" % sys.version_info[:3]))
1196 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1220 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1197 os.path.dirname(pycompat.fsencode(os.__file__)))
1221 os.path.dirname(pycompat.fsencode(os.__file__)))
1198
1222
1199 security = set(sslutil.supportedprotocols)
1223 security = set(sslutil.supportedprotocols)
1200 if sslutil.hassni:
1224 if sslutil.hassni:
1201 security.add('sni')
1225 security.add('sni')
1202
1226
1203 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1227 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1204 fm.formatlist(sorted(security), name='protocol',
1228 fm.formatlist(sorted(security), name='protocol',
1205 fmt='%s', sep=','))
1229 fmt='%s', sep=','))
1206
1230
1207 # These are warnings, not errors. So don't increment problem count. This
1231 # These are warnings, not errors. So don't increment problem count. This
1208 # may change in the future.
1232 # may change in the future.
1209 if 'tls1.2' not in security:
1233 if 'tls1.2' not in security:
1210 fm.plain(_(' TLS 1.2 not supported by Python install; '
1234 fm.plain(_(' TLS 1.2 not supported by Python install; '
1211 'network connections lack modern security\n'))
1235 'network connections lack modern security\n'))
1212 if 'sni' not in security:
1236 if 'sni' not in security:
1213 fm.plain(_(' SNI not supported by Python install; may have '
1237 fm.plain(_(' SNI not supported by Python install; may have '
1214 'connectivity issues with some servers\n'))
1238 'connectivity issues with some servers\n'))
1215
1239
1216 # TODO print CA cert info
1240 # TODO print CA cert info
1217
1241
1218 # hg version
1242 # hg version
1219 hgver = util.version()
1243 hgver = util.version()
1220 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1244 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1221 hgver.split('+')[0])
1245 hgver.split('+')[0])
1222 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1246 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1223 '+'.join(hgver.split('+')[1:]))
1247 '+'.join(hgver.split('+')[1:]))
1224
1248
1225 # compiled modules
1249 # compiled modules
1226 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1250 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1227 policy.policy)
1251 policy.policy)
1228 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1252 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1229 os.path.dirname(pycompat.fsencode(__file__)))
1253 os.path.dirname(pycompat.fsencode(__file__)))
1230
1254
1231 if policy.policy in ('c', 'allow'):
1255 if policy.policy in ('c', 'allow'):
1232 err = None
1256 err = None
1233 try:
1257 try:
1234 from .cext import (
1258 from .cext import (
1235 base85,
1259 base85,
1236 bdiff,
1260 bdiff,
1237 mpatch,
1261 mpatch,
1238 osutil,
1262 osutil,
1239 )
1263 )
1240 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1264 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1241 except Exception as inst:
1265 except Exception as inst:
1242 err = stringutil.forcebytestr(inst)
1266 err = stringutil.forcebytestr(inst)
1243 problems += 1
1267 problems += 1
1244 fm.condwrite(err, 'extensionserror', " %s\n", err)
1268 fm.condwrite(err, 'extensionserror', " %s\n", err)
1245
1269
1246 compengines = util.compengines._engines.values()
1270 compengines = util.compengines._engines.values()
1247 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1271 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1248 fm.formatlist(sorted(e.name() for e in compengines),
1272 fm.formatlist(sorted(e.name() for e in compengines),
1249 name='compengine', fmt='%s', sep=', '))
1273 name='compengine', fmt='%s', sep=', '))
1250 fm.write('compenginesavail', _('checking available compression engines '
1274 fm.write('compenginesavail', _('checking available compression engines '
1251 '(%s)\n'),
1275 '(%s)\n'),
1252 fm.formatlist(sorted(e.name() for e in compengines
1276 fm.formatlist(sorted(e.name() for e in compengines
1253 if e.available()),
1277 if e.available()),
1254 name='compengine', fmt='%s', sep=', '))
1278 name='compengine', fmt='%s', sep=', '))
1255 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1279 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1256 fm.write('compenginesserver', _('checking available compression engines '
1280 fm.write('compenginesserver', _('checking available compression engines '
1257 'for wire protocol (%s)\n'),
1281 'for wire protocol (%s)\n'),
1258 fm.formatlist([e.name() for e in wirecompengines
1282 fm.formatlist([e.name() for e in wirecompengines
1259 if e.wireprotosupport()],
1283 if e.wireprotosupport()],
1260 name='compengine', fmt='%s', sep=', '))
1284 name='compengine', fmt='%s', sep=', '))
1261 re2 = 'missing'
1285 re2 = 'missing'
1262 if util._re2:
1286 if util._re2:
1263 re2 = 'available'
1287 re2 = 'available'
1264 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1288 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1265 fm.data(re2=bool(util._re2))
1289 fm.data(re2=bool(util._re2))
1266
1290
1267 # templates
1291 # templates
1268 p = templater.templatepaths()
1292 p = templater.templatepaths()
1269 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1293 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1270 fm.condwrite(not p, '', _(" no template directories found\n"))
1294 fm.condwrite(not p, '', _(" no template directories found\n"))
1271 if p:
1295 if p:
1272 m = templater.templatepath("map-cmdline.default")
1296 m = templater.templatepath("map-cmdline.default")
1273 if m:
1297 if m:
1274 # template found, check if it is working
1298 # template found, check if it is working
1275 err = None
1299 err = None
1276 try:
1300 try:
1277 templater.templater.frommapfile(m)
1301 templater.templater.frommapfile(m)
1278 except Exception as inst:
1302 except Exception as inst:
1279 err = stringutil.forcebytestr(inst)
1303 err = stringutil.forcebytestr(inst)
1280 p = None
1304 p = None
1281 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1305 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1282 else:
1306 else:
1283 p = None
1307 p = None
1284 fm.condwrite(p, 'defaulttemplate',
1308 fm.condwrite(p, 'defaulttemplate',
1285 _("checking default template (%s)\n"), m)
1309 _("checking default template (%s)\n"), m)
1286 fm.condwrite(not m, 'defaulttemplatenotfound',
1310 fm.condwrite(not m, 'defaulttemplatenotfound',
1287 _(" template '%s' not found\n"), "default")
1311 _(" template '%s' not found\n"), "default")
1288 if not p:
1312 if not p:
1289 problems += 1
1313 problems += 1
1290 fm.condwrite(not p, '',
1314 fm.condwrite(not p, '',
1291 _(" (templates seem to have been installed incorrectly)\n"))
1315 _(" (templates seem to have been installed incorrectly)\n"))
1292
1316
1293 # editor
1317 # editor
1294 editor = ui.geteditor()
1318 editor = ui.geteditor()
1295 editor = util.expandpath(editor)
1319 editor = util.expandpath(editor)
1296 editorbin = procutil.shellsplit(editor)[0]
1320 editorbin = procutil.shellsplit(editor)[0]
1297 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1321 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1298 cmdpath = procutil.findexe(editorbin)
1322 cmdpath = procutil.findexe(editorbin)
1299 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1323 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1300 _(" No commit editor set and can't find %s in PATH\n"
1324 _(" No commit editor set and can't find %s in PATH\n"
1301 " (specify a commit editor in your configuration"
1325 " (specify a commit editor in your configuration"
1302 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1326 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1303 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1327 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1304 _(" Can't find editor '%s' in PATH\n"
1328 _(" Can't find editor '%s' in PATH\n"
1305 " (specify a commit editor in your configuration"
1329 " (specify a commit editor in your configuration"
1306 " file)\n"), not cmdpath and editorbin)
1330 " file)\n"), not cmdpath and editorbin)
1307 if not cmdpath and editor != 'vi':
1331 if not cmdpath and editor != 'vi':
1308 problems += 1
1332 problems += 1
1309
1333
1310 # check username
1334 # check username
1311 username = None
1335 username = None
1312 err = None
1336 err = None
1313 try:
1337 try:
1314 username = ui.username()
1338 username = ui.username()
1315 except error.Abort as e:
1339 except error.Abort as e:
1316 err = stringutil.forcebytestr(e)
1340 err = stringutil.forcebytestr(e)
1317 problems += 1
1341 problems += 1
1318
1342
1319 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1343 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1320 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1344 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1321 " (specify a username in your configuration file)\n"), err)
1345 " (specify a username in your configuration file)\n"), err)
1322
1346
1323 fm.condwrite(not problems, '',
1347 fm.condwrite(not problems, '',
1324 _("no problems detected\n"))
1348 _("no problems detected\n"))
1325 if not problems:
1349 if not problems:
1326 fm.data(problems=problems)
1350 fm.data(problems=problems)
1327 fm.condwrite(problems, 'problems',
1351 fm.condwrite(problems, 'problems',
1328 _("%d problems detected,"
1352 _("%d problems detected,"
1329 " please check your install!\n"), problems)
1353 " please check your install!\n"), problems)
1330 fm.end()
1354 fm.end()
1331
1355
1332 return problems
1356 return problems
1333
1357
1334 @command('debugknown', [], _('REPO ID...'), norepo=True)
1358 @command('debugknown', [], _('REPO ID...'), norepo=True)
1335 def debugknown(ui, repopath, *ids, **opts):
1359 def debugknown(ui, repopath, *ids, **opts):
1336 """test whether node ids are known to a repo
1360 """test whether node ids are known to a repo
1337
1361
1338 Every ID must be a full-length hex node id string. Returns a list of 0s
1362 Every ID must be a full-length hex node id string. Returns a list of 0s
1339 and 1s indicating unknown/known.
1363 and 1s indicating unknown/known.
1340 """
1364 """
1341 opts = pycompat.byteskwargs(opts)
1365 opts = pycompat.byteskwargs(opts)
1342 repo = hg.peer(ui, opts, repopath)
1366 repo = hg.peer(ui, opts, repopath)
1343 if not repo.capable('known'):
1367 if not repo.capable('known'):
1344 raise error.Abort("known() not supported by target repository")
1368 raise error.Abort("known() not supported by target repository")
1345 flags = repo.known([bin(s) for s in ids])
1369 flags = repo.known([bin(s) for s in ids])
1346 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1370 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1347
1371
1348 @command('debuglabelcomplete', [], _('LABEL...'))
1372 @command('debuglabelcomplete', [], _('LABEL...'))
1349 def debuglabelcomplete(ui, repo, *args):
1373 def debuglabelcomplete(ui, repo, *args):
1350 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1374 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1351 debugnamecomplete(ui, repo, *args)
1375 debugnamecomplete(ui, repo, *args)
1352
1376
1353 @command('debuglocks',
1377 @command('debuglocks',
1354 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1378 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1355 ('W', 'force-wlock', None,
1379 ('W', 'force-wlock', None,
1356 _('free the working state lock (DANGEROUS)')),
1380 _('free the working state lock (DANGEROUS)')),
1357 ('s', 'set-lock', None, _('set the store lock until stopped')),
1381 ('s', 'set-lock', None, _('set the store lock until stopped')),
1358 ('S', 'set-wlock', None,
1382 ('S', 'set-wlock', None,
1359 _('set the working state lock until stopped'))],
1383 _('set the working state lock until stopped'))],
1360 _('[OPTION]...'))
1384 _('[OPTION]...'))
1361 def debuglocks(ui, repo, **opts):
1385 def debuglocks(ui, repo, **opts):
1362 """show or modify state of locks
1386 """show or modify state of locks
1363
1387
1364 By default, this command will show which locks are held. This
1388 By default, this command will show which locks are held. This
1365 includes the user and process holding the lock, the amount of time
1389 includes the user and process holding the lock, the amount of time
1366 the lock has been held, and the machine name where the process is
1390 the lock has been held, and the machine name where the process is
1367 running if it's not local.
1391 running if it's not local.
1368
1392
1369 Locks protect the integrity of Mercurial's data, so should be
1393 Locks protect the integrity of Mercurial's data, so should be
1370 treated with care. System crashes or other interruptions may cause
1394 treated with care. System crashes or other interruptions may cause
1371 locks to not be properly released, though Mercurial will usually
1395 locks to not be properly released, though Mercurial will usually
1372 detect and remove such stale locks automatically.
1396 detect and remove such stale locks automatically.
1373
1397
1374 However, detecting stale locks may not always be possible (for
1398 However, detecting stale locks may not always be possible (for
1375 instance, on a shared filesystem). Removing locks may also be
1399 instance, on a shared filesystem). Removing locks may also be
1376 blocked by filesystem permissions.
1400 blocked by filesystem permissions.
1377
1401
1378 Setting a lock will prevent other commands from changing the data.
1402 Setting a lock will prevent other commands from changing the data.
1379 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1403 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1380 The set locks are removed when the command exits.
1404 The set locks are removed when the command exits.
1381
1405
1382 Returns 0 if no locks are held.
1406 Returns 0 if no locks are held.
1383
1407
1384 """
1408 """
1385
1409
1386 if opts.get(r'force_lock'):
1410 if opts.get(r'force_lock'):
1387 repo.svfs.unlink('lock')
1411 repo.svfs.unlink('lock')
1388 if opts.get(r'force_wlock'):
1412 if opts.get(r'force_wlock'):
1389 repo.vfs.unlink('wlock')
1413 repo.vfs.unlink('wlock')
1390 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1414 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1391 return 0
1415 return 0
1392
1416
1393 locks = []
1417 locks = []
1394 try:
1418 try:
1395 if opts.get(r'set_wlock'):
1419 if opts.get(r'set_wlock'):
1396 try:
1420 try:
1397 locks.append(repo.wlock(False))
1421 locks.append(repo.wlock(False))
1398 except error.LockHeld:
1422 except error.LockHeld:
1399 raise error.Abort(_('wlock is already held'))
1423 raise error.Abort(_('wlock is already held'))
1400 if opts.get(r'set_lock'):
1424 if opts.get(r'set_lock'):
1401 try:
1425 try:
1402 locks.append(repo.lock(False))
1426 locks.append(repo.lock(False))
1403 except error.LockHeld:
1427 except error.LockHeld:
1404 raise error.Abort(_('lock is already held'))
1428 raise error.Abort(_('lock is already held'))
1405 if len(locks):
1429 if len(locks):
1406 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1430 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1407 return 0
1431 return 0
1408 finally:
1432 finally:
1409 release(*locks)
1433 release(*locks)
1410
1434
1411 now = time.time()
1435 now = time.time()
1412 held = 0
1436 held = 0
1413
1437
1414 def report(vfs, name, method):
1438 def report(vfs, name, method):
1415 # this causes stale locks to get reaped for more accurate reporting
1439 # this causes stale locks to get reaped for more accurate reporting
1416 try:
1440 try:
1417 l = method(False)
1441 l = method(False)
1418 except error.LockHeld:
1442 except error.LockHeld:
1419 l = None
1443 l = None
1420
1444
1421 if l:
1445 if l:
1422 l.release()
1446 l.release()
1423 else:
1447 else:
1424 try:
1448 try:
1425 st = vfs.lstat(name)
1449 st = vfs.lstat(name)
1426 age = now - st[stat.ST_MTIME]
1450 age = now - st[stat.ST_MTIME]
1427 user = util.username(st.st_uid)
1451 user = util.username(st.st_uid)
1428 locker = vfs.readlock(name)
1452 locker = vfs.readlock(name)
1429 if ":" in locker:
1453 if ":" in locker:
1430 host, pid = locker.split(':')
1454 host, pid = locker.split(':')
1431 if host == socket.gethostname():
1455 if host == socket.gethostname():
1432 locker = 'user %s, process %s' % (user, pid)
1456 locker = 'user %s, process %s' % (user, pid)
1433 else:
1457 else:
1434 locker = 'user %s, process %s, host %s' \
1458 locker = 'user %s, process %s, host %s' \
1435 % (user, pid, host)
1459 % (user, pid, host)
1436 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1460 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1437 return 1
1461 return 1
1438 except OSError as e:
1462 except OSError as e:
1439 if e.errno != errno.ENOENT:
1463 if e.errno != errno.ENOENT:
1440 raise
1464 raise
1441
1465
1442 ui.write(("%-6s free\n") % (name + ":"))
1466 ui.write(("%-6s free\n") % (name + ":"))
1443 return 0
1467 return 0
1444
1468
1445 held += report(repo.svfs, "lock", repo.lock)
1469 held += report(repo.svfs, "lock", repo.lock)
1446 held += report(repo.vfs, "wlock", repo.wlock)
1470 held += report(repo.vfs, "wlock", repo.wlock)
1447
1471
1448 return held
1472 return held
1449
1473
1450 @command('debugmanifestfulltextcache', [
1474 @command('debugmanifestfulltextcache', [
1451 ('', 'clear', False, _('clear the cache')),
1475 ('', 'clear', False, _('clear the cache')),
1452 ('a', 'add', '', _('add the given manifest node to the cache'),
1476 ('a', 'add', '', _('add the given manifest node to the cache'),
1453 _('NODE'))
1477 _('NODE'))
1454 ], '')
1478 ], '')
1455 def debugmanifestfulltextcache(ui, repo, add=None, **opts):
1479 def debugmanifestfulltextcache(ui, repo, add=None, **opts):
1456 """show, clear or amend the contents of the manifest fulltext cache"""
1480 """show, clear or amend the contents of the manifest fulltext cache"""
1457 with repo.lock():
1481 with repo.lock():
1458 r = repo.manifestlog._revlog
1482 r = repo.manifestlog._revlog
1459 try:
1483 try:
1460 cache = r._fulltextcache
1484 cache = r._fulltextcache
1461 except AttributeError:
1485 except AttributeError:
1462 ui.warn(_(
1486 ui.warn(_(
1463 "Current revlog implementation doesn't appear to have a "
1487 "Current revlog implementation doesn't appear to have a "
1464 'manifest fulltext cache\n'))
1488 'manifest fulltext cache\n'))
1465 return
1489 return
1466
1490
1467 if opts.get(r'clear'):
1491 if opts.get(r'clear'):
1468 cache.clear()
1492 cache.clear()
1469
1493
1470 if add:
1494 if add:
1471 try:
1495 try:
1472 manifest = repo.manifestlog[r.lookup(add)]
1496 manifest = repo.manifestlog[r.lookup(add)]
1473 except error.LookupError as e:
1497 except error.LookupError as e:
1474 raise error.Abort(e, hint="Check your manifest node id")
1498 raise error.Abort(e, hint="Check your manifest node id")
1475 manifest.read() # stores revisision in cache too
1499 manifest.read() # stores revisision in cache too
1476
1500
1477 if not len(cache):
1501 if not len(cache):
1478 ui.write(_('Cache empty'))
1502 ui.write(_('Cache empty'))
1479 else:
1503 else:
1480 ui.write(
1504 ui.write(
1481 _('Cache contains %d manifest entries, in order of most to '
1505 _('Cache contains %d manifest entries, in order of most to '
1482 'least recent:\n') % (len(cache),))
1506 'least recent:\n') % (len(cache),))
1483 totalsize = 0
1507 totalsize = 0
1484 for nodeid in cache:
1508 for nodeid in cache:
1485 # Use cache.get to not update the LRU order
1509 # Use cache.get to not update the LRU order
1486 data = cache.get(nodeid)
1510 data = cache.get(nodeid)
1487 size = len(data)
1511 size = len(data)
1488 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1512 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1489 ui.write(_('id: %s, size %s\n') % (
1513 ui.write(_('id: %s, size %s\n') % (
1490 hex(nodeid), util.bytecount(size)))
1514 hex(nodeid), util.bytecount(size)))
1491 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1515 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1492 ui.write(
1516 ui.write(
1493 _('Total cache data size %s, on-disk %s\n') % (
1517 _('Total cache data size %s, on-disk %s\n') % (
1494 util.bytecount(totalsize), util.bytecount(ondisk))
1518 util.bytecount(totalsize), util.bytecount(ondisk))
1495 )
1519 )
1496
1520
1497 @command('debugmergestate', [], '')
1521 @command('debugmergestate', [], '')
1498 def debugmergestate(ui, repo, *args):
1522 def debugmergestate(ui, repo, *args):
1499 """print merge state
1523 """print merge state
1500
1524
1501 Use --verbose to print out information about whether v1 or v2 merge state
1525 Use --verbose to print out information about whether v1 or v2 merge state
1502 was chosen."""
1526 was chosen."""
1503 def _hashornull(h):
1527 def _hashornull(h):
1504 if h == nullhex:
1528 if h == nullhex:
1505 return 'null'
1529 return 'null'
1506 else:
1530 else:
1507 return h
1531 return h
1508
1532
1509 def printrecords(version):
1533 def printrecords(version):
1510 ui.write(('* version %d records\n') % version)
1534 ui.write(('* version %d records\n') % version)
1511 if version == 1:
1535 if version == 1:
1512 records = v1records
1536 records = v1records
1513 else:
1537 else:
1514 records = v2records
1538 records = v2records
1515
1539
1516 for rtype, record in records:
1540 for rtype, record in records:
1517 # pretty print some record types
1541 # pretty print some record types
1518 if rtype == 'L':
1542 if rtype == 'L':
1519 ui.write(('local: %s\n') % record)
1543 ui.write(('local: %s\n') % record)
1520 elif rtype == 'O':
1544 elif rtype == 'O':
1521 ui.write(('other: %s\n') % record)
1545 ui.write(('other: %s\n') % record)
1522 elif rtype == 'm':
1546 elif rtype == 'm':
1523 driver, mdstate = record.split('\0', 1)
1547 driver, mdstate = record.split('\0', 1)
1524 ui.write(('merge driver: %s (state "%s")\n')
1548 ui.write(('merge driver: %s (state "%s")\n')
1525 % (driver, mdstate))
1549 % (driver, mdstate))
1526 elif rtype in 'FDC':
1550 elif rtype in 'FDC':
1527 r = record.split('\0')
1551 r = record.split('\0')
1528 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1552 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1529 if version == 1:
1553 if version == 1:
1530 onode = 'not stored in v1 format'
1554 onode = 'not stored in v1 format'
1531 flags = r[7]
1555 flags = r[7]
1532 else:
1556 else:
1533 onode, flags = r[7:9]
1557 onode, flags = r[7:9]
1534 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1558 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1535 % (f, rtype, state, _hashornull(hash)))
1559 % (f, rtype, state, _hashornull(hash)))
1536 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1560 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1537 ui.write((' ancestor path: %s (node %s)\n')
1561 ui.write((' ancestor path: %s (node %s)\n')
1538 % (afile, _hashornull(anode)))
1562 % (afile, _hashornull(anode)))
1539 ui.write((' other path: %s (node %s)\n')
1563 ui.write((' other path: %s (node %s)\n')
1540 % (ofile, _hashornull(onode)))
1564 % (ofile, _hashornull(onode)))
1541 elif rtype == 'f':
1565 elif rtype == 'f':
1542 filename, rawextras = record.split('\0', 1)
1566 filename, rawextras = record.split('\0', 1)
1543 extras = rawextras.split('\0')
1567 extras = rawextras.split('\0')
1544 i = 0
1568 i = 0
1545 extrastrings = []
1569 extrastrings = []
1546 while i < len(extras):
1570 while i < len(extras):
1547 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1571 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1548 i += 2
1572 i += 2
1549
1573
1550 ui.write(('file extras: %s (%s)\n')
1574 ui.write(('file extras: %s (%s)\n')
1551 % (filename, ', '.join(extrastrings)))
1575 % (filename, ', '.join(extrastrings)))
1552 elif rtype == 'l':
1576 elif rtype == 'l':
1553 labels = record.split('\0', 2)
1577 labels = record.split('\0', 2)
1554 labels = [l for l in labels if len(l) > 0]
1578 labels = [l for l in labels if len(l) > 0]
1555 ui.write(('labels:\n'))
1579 ui.write(('labels:\n'))
1556 ui.write((' local: %s\n' % labels[0]))
1580 ui.write((' local: %s\n' % labels[0]))
1557 ui.write((' other: %s\n' % labels[1]))
1581 ui.write((' other: %s\n' % labels[1]))
1558 if len(labels) > 2:
1582 if len(labels) > 2:
1559 ui.write((' base: %s\n' % labels[2]))
1583 ui.write((' base: %s\n' % labels[2]))
1560 else:
1584 else:
1561 ui.write(('unrecognized entry: %s\t%s\n')
1585 ui.write(('unrecognized entry: %s\t%s\n')
1562 % (rtype, record.replace('\0', '\t')))
1586 % (rtype, record.replace('\0', '\t')))
1563
1587
1564 # Avoid mergestate.read() since it may raise an exception for unsupported
1588 # Avoid mergestate.read() since it may raise an exception for unsupported
1565 # merge state records. We shouldn't be doing this, but this is OK since this
1589 # merge state records. We shouldn't be doing this, but this is OK since this
1566 # command is pretty low-level.
1590 # command is pretty low-level.
1567 ms = mergemod.mergestate(repo)
1591 ms = mergemod.mergestate(repo)
1568
1592
1569 # sort so that reasonable information is on top
1593 # sort so that reasonable information is on top
1570 v1records = ms._readrecordsv1()
1594 v1records = ms._readrecordsv1()
1571 v2records = ms._readrecordsv2()
1595 v2records = ms._readrecordsv2()
1572 order = 'LOml'
1596 order = 'LOml'
1573 def key(r):
1597 def key(r):
1574 idx = order.find(r[0])
1598 idx = order.find(r[0])
1575 if idx == -1:
1599 if idx == -1:
1576 return (1, r[1])
1600 return (1, r[1])
1577 else:
1601 else:
1578 return (0, idx)
1602 return (0, idx)
1579 v1records.sort(key=key)
1603 v1records.sort(key=key)
1580 v2records.sort(key=key)
1604 v2records.sort(key=key)
1581
1605
1582 if not v1records and not v2records:
1606 if not v1records and not v2records:
1583 ui.write(('no merge state found\n'))
1607 ui.write(('no merge state found\n'))
1584 elif not v2records:
1608 elif not v2records:
1585 ui.note(('no version 2 merge state\n'))
1609 ui.note(('no version 2 merge state\n'))
1586 printrecords(1)
1610 printrecords(1)
1587 elif ms._v1v2match(v1records, v2records):
1611 elif ms._v1v2match(v1records, v2records):
1588 ui.note(('v1 and v2 states match: using v2\n'))
1612 ui.note(('v1 and v2 states match: using v2\n'))
1589 printrecords(2)
1613 printrecords(2)
1590 else:
1614 else:
1591 ui.note(('v1 and v2 states mismatch: using v1\n'))
1615 ui.note(('v1 and v2 states mismatch: using v1\n'))
1592 printrecords(1)
1616 printrecords(1)
1593 if ui.verbose:
1617 if ui.verbose:
1594 printrecords(2)
1618 printrecords(2)
1595
1619
1596 @command('debugnamecomplete', [], _('NAME...'))
1620 @command('debugnamecomplete', [], _('NAME...'))
1597 def debugnamecomplete(ui, repo, *args):
1621 def debugnamecomplete(ui, repo, *args):
1598 '''complete "names" - tags, open branch names, bookmark names'''
1622 '''complete "names" - tags, open branch names, bookmark names'''
1599
1623
1600 names = set()
1624 names = set()
1601 # since we previously only listed open branches, we will handle that
1625 # since we previously only listed open branches, we will handle that
1602 # specially (after this for loop)
1626 # specially (after this for loop)
1603 for name, ns in repo.names.iteritems():
1627 for name, ns in repo.names.iteritems():
1604 if name != 'branches':
1628 if name != 'branches':
1605 names.update(ns.listnames(repo))
1629 names.update(ns.listnames(repo))
1606 names.update(tag for (tag, heads, tip, closed)
1630 names.update(tag for (tag, heads, tip, closed)
1607 in repo.branchmap().iterbranches() if not closed)
1631 in repo.branchmap().iterbranches() if not closed)
1608 completions = set()
1632 completions = set()
1609 if not args:
1633 if not args:
1610 args = ['']
1634 args = ['']
1611 for a in args:
1635 for a in args:
1612 completions.update(n for n in names if n.startswith(a))
1636 completions.update(n for n in names if n.startswith(a))
1613 ui.write('\n'.join(sorted(completions)))
1637 ui.write('\n'.join(sorted(completions)))
1614 ui.write('\n')
1638 ui.write('\n')
1615
1639
1616 @command('debugobsolete',
1640 @command('debugobsolete',
1617 [('', 'flags', 0, _('markers flag')),
1641 [('', 'flags', 0, _('markers flag')),
1618 ('', 'record-parents', False,
1642 ('', 'record-parents', False,
1619 _('record parent information for the precursor')),
1643 _('record parent information for the precursor')),
1620 ('r', 'rev', [], _('display markers relevant to REV')),
1644 ('r', 'rev', [], _('display markers relevant to REV')),
1621 ('', 'exclusive', False, _('restrict display to markers only '
1645 ('', 'exclusive', False, _('restrict display to markers only '
1622 'relevant to REV')),
1646 'relevant to REV')),
1623 ('', 'index', False, _('display index of the marker')),
1647 ('', 'index', False, _('display index of the marker')),
1624 ('', 'delete', [], _('delete markers specified by indices')),
1648 ('', 'delete', [], _('delete markers specified by indices')),
1625 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1649 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1626 _('[OBSOLETED [REPLACEMENT ...]]'))
1650 _('[OBSOLETED [REPLACEMENT ...]]'))
1627 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1651 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1628 """create arbitrary obsolete marker
1652 """create arbitrary obsolete marker
1629
1653
1630 With no arguments, displays the list of obsolescence markers."""
1654 With no arguments, displays the list of obsolescence markers."""
1631
1655
1632 opts = pycompat.byteskwargs(opts)
1656 opts = pycompat.byteskwargs(opts)
1633
1657
1634 def parsenodeid(s):
1658 def parsenodeid(s):
1635 try:
1659 try:
1636 # We do not use revsingle/revrange functions here to accept
1660 # We do not use revsingle/revrange functions here to accept
1637 # arbitrary node identifiers, possibly not present in the
1661 # arbitrary node identifiers, possibly not present in the
1638 # local repository.
1662 # local repository.
1639 n = bin(s)
1663 n = bin(s)
1640 if len(n) != len(nullid):
1664 if len(n) != len(nullid):
1641 raise TypeError()
1665 raise TypeError()
1642 return n
1666 return n
1643 except TypeError:
1667 except TypeError:
1644 raise error.Abort('changeset references must be full hexadecimal '
1668 raise error.Abort('changeset references must be full hexadecimal '
1645 'node identifiers')
1669 'node identifiers')
1646
1670
1647 if opts.get('delete'):
1671 if opts.get('delete'):
1648 indices = []
1672 indices = []
1649 for v in opts.get('delete'):
1673 for v in opts.get('delete'):
1650 try:
1674 try:
1651 indices.append(int(v))
1675 indices.append(int(v))
1652 except ValueError:
1676 except ValueError:
1653 raise error.Abort(_('invalid index value: %r') % v,
1677 raise error.Abort(_('invalid index value: %r') % v,
1654 hint=_('use integers for indices'))
1678 hint=_('use integers for indices'))
1655
1679
1656 if repo.currenttransaction():
1680 if repo.currenttransaction():
1657 raise error.Abort(_('cannot delete obsmarkers in the middle '
1681 raise error.Abort(_('cannot delete obsmarkers in the middle '
1658 'of transaction.'))
1682 'of transaction.'))
1659
1683
1660 with repo.lock():
1684 with repo.lock():
1661 n = repair.deleteobsmarkers(repo.obsstore, indices)
1685 n = repair.deleteobsmarkers(repo.obsstore, indices)
1662 ui.write(_('deleted %i obsolescence markers\n') % n)
1686 ui.write(_('deleted %i obsolescence markers\n') % n)
1663
1687
1664 return
1688 return
1665
1689
1666 if precursor is not None:
1690 if precursor is not None:
1667 if opts['rev']:
1691 if opts['rev']:
1668 raise error.Abort('cannot select revision when creating marker')
1692 raise error.Abort('cannot select revision when creating marker')
1669 metadata = {}
1693 metadata = {}
1670 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
1694 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
1671 succs = tuple(parsenodeid(succ) for succ in successors)
1695 succs = tuple(parsenodeid(succ) for succ in successors)
1672 l = repo.lock()
1696 l = repo.lock()
1673 try:
1697 try:
1674 tr = repo.transaction('debugobsolete')
1698 tr = repo.transaction('debugobsolete')
1675 try:
1699 try:
1676 date = opts.get('date')
1700 date = opts.get('date')
1677 if date:
1701 if date:
1678 date = dateutil.parsedate(date)
1702 date = dateutil.parsedate(date)
1679 else:
1703 else:
1680 date = None
1704 date = None
1681 prec = parsenodeid(precursor)
1705 prec = parsenodeid(precursor)
1682 parents = None
1706 parents = None
1683 if opts['record_parents']:
1707 if opts['record_parents']:
1684 if prec not in repo.unfiltered():
1708 if prec not in repo.unfiltered():
1685 raise error.Abort('cannot used --record-parents on '
1709 raise error.Abort('cannot used --record-parents on '
1686 'unknown changesets')
1710 'unknown changesets')
1687 parents = repo.unfiltered()[prec].parents()
1711 parents = repo.unfiltered()[prec].parents()
1688 parents = tuple(p.node() for p in parents)
1712 parents = tuple(p.node() for p in parents)
1689 repo.obsstore.create(tr, prec, succs, opts['flags'],
1713 repo.obsstore.create(tr, prec, succs, opts['flags'],
1690 parents=parents, date=date,
1714 parents=parents, date=date,
1691 metadata=metadata, ui=ui)
1715 metadata=metadata, ui=ui)
1692 tr.close()
1716 tr.close()
1693 except ValueError as exc:
1717 except ValueError as exc:
1694 raise error.Abort(_('bad obsmarker input: %s') %
1718 raise error.Abort(_('bad obsmarker input: %s') %
1695 pycompat.bytestr(exc))
1719 pycompat.bytestr(exc))
1696 finally:
1720 finally:
1697 tr.release()
1721 tr.release()
1698 finally:
1722 finally:
1699 l.release()
1723 l.release()
1700 else:
1724 else:
1701 if opts['rev']:
1725 if opts['rev']:
1702 revs = scmutil.revrange(repo, opts['rev'])
1726 revs = scmutil.revrange(repo, opts['rev'])
1703 nodes = [repo[r].node() for r in revs]
1727 nodes = [repo[r].node() for r in revs]
1704 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1728 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1705 exclusive=opts['exclusive']))
1729 exclusive=opts['exclusive']))
1706 markers.sort(key=lambda x: x._data)
1730 markers.sort(key=lambda x: x._data)
1707 else:
1731 else:
1708 markers = obsutil.getmarkers(repo)
1732 markers = obsutil.getmarkers(repo)
1709
1733
1710 markerstoiter = markers
1734 markerstoiter = markers
1711 isrelevant = lambda m: True
1735 isrelevant = lambda m: True
1712 if opts.get('rev') and opts.get('index'):
1736 if opts.get('rev') and opts.get('index'):
1713 markerstoiter = obsutil.getmarkers(repo)
1737 markerstoiter = obsutil.getmarkers(repo)
1714 markerset = set(markers)
1738 markerset = set(markers)
1715 isrelevant = lambda m: m in markerset
1739 isrelevant = lambda m: m in markerset
1716
1740
1717 fm = ui.formatter('debugobsolete', opts)
1741 fm = ui.formatter('debugobsolete', opts)
1718 for i, m in enumerate(markerstoiter):
1742 for i, m in enumerate(markerstoiter):
1719 if not isrelevant(m):
1743 if not isrelevant(m):
1720 # marker can be irrelevant when we're iterating over a set
1744 # marker can be irrelevant when we're iterating over a set
1721 # of markers (markerstoiter) which is bigger than the set
1745 # of markers (markerstoiter) which is bigger than the set
1722 # of markers we want to display (markers)
1746 # of markers we want to display (markers)
1723 # this can happen if both --index and --rev options are
1747 # this can happen if both --index and --rev options are
1724 # provided and thus we need to iterate over all of the markers
1748 # provided and thus we need to iterate over all of the markers
1725 # to get the correct indices, but only display the ones that
1749 # to get the correct indices, but only display the ones that
1726 # are relevant to --rev value
1750 # are relevant to --rev value
1727 continue
1751 continue
1728 fm.startitem()
1752 fm.startitem()
1729 ind = i if opts.get('index') else None
1753 ind = i if opts.get('index') else None
1730 cmdutil.showmarker(fm, m, index=ind)
1754 cmdutil.showmarker(fm, m, index=ind)
1731 fm.end()
1755 fm.end()
1732
1756
1733 @command('debugpathcomplete',
1757 @command('debugpathcomplete',
1734 [('f', 'full', None, _('complete an entire path')),
1758 [('f', 'full', None, _('complete an entire path')),
1735 ('n', 'normal', None, _('show only normal files')),
1759 ('n', 'normal', None, _('show only normal files')),
1736 ('a', 'added', None, _('show only added files')),
1760 ('a', 'added', None, _('show only added files')),
1737 ('r', 'removed', None, _('show only removed files'))],
1761 ('r', 'removed', None, _('show only removed files'))],
1738 _('FILESPEC...'))
1762 _('FILESPEC...'))
1739 def debugpathcomplete(ui, repo, *specs, **opts):
1763 def debugpathcomplete(ui, repo, *specs, **opts):
1740 '''complete part or all of a tracked path
1764 '''complete part or all of a tracked path
1741
1765
1742 This command supports shells that offer path name completion. It
1766 This command supports shells that offer path name completion. It
1743 currently completes only files already known to the dirstate.
1767 currently completes only files already known to the dirstate.
1744
1768
1745 Completion extends only to the next path segment unless
1769 Completion extends only to the next path segment unless
1746 --full is specified, in which case entire paths are used.'''
1770 --full is specified, in which case entire paths are used.'''
1747
1771
1748 def complete(path, acceptable):
1772 def complete(path, acceptable):
1749 dirstate = repo.dirstate
1773 dirstate = repo.dirstate
1750 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1774 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1751 rootdir = repo.root + pycompat.ossep
1775 rootdir = repo.root + pycompat.ossep
1752 if spec != repo.root and not spec.startswith(rootdir):
1776 if spec != repo.root and not spec.startswith(rootdir):
1753 return [], []
1777 return [], []
1754 if os.path.isdir(spec):
1778 if os.path.isdir(spec):
1755 spec += '/'
1779 spec += '/'
1756 spec = spec[len(rootdir):]
1780 spec = spec[len(rootdir):]
1757 fixpaths = pycompat.ossep != '/'
1781 fixpaths = pycompat.ossep != '/'
1758 if fixpaths:
1782 if fixpaths:
1759 spec = spec.replace(pycompat.ossep, '/')
1783 spec = spec.replace(pycompat.ossep, '/')
1760 speclen = len(spec)
1784 speclen = len(spec)
1761 fullpaths = opts[r'full']
1785 fullpaths = opts[r'full']
1762 files, dirs = set(), set()
1786 files, dirs = set(), set()
1763 adddir, addfile = dirs.add, files.add
1787 adddir, addfile = dirs.add, files.add
1764 for f, st in dirstate.iteritems():
1788 for f, st in dirstate.iteritems():
1765 if f.startswith(spec) and st[0] in acceptable:
1789 if f.startswith(spec) and st[0] in acceptable:
1766 if fixpaths:
1790 if fixpaths:
1767 f = f.replace('/', pycompat.ossep)
1791 f = f.replace('/', pycompat.ossep)
1768 if fullpaths:
1792 if fullpaths:
1769 addfile(f)
1793 addfile(f)
1770 continue
1794 continue
1771 s = f.find(pycompat.ossep, speclen)
1795 s = f.find(pycompat.ossep, speclen)
1772 if s >= 0:
1796 if s >= 0:
1773 adddir(f[:s])
1797 adddir(f[:s])
1774 else:
1798 else:
1775 addfile(f)
1799 addfile(f)
1776 return files, dirs
1800 return files, dirs
1777
1801
1778 acceptable = ''
1802 acceptable = ''
1779 if opts[r'normal']:
1803 if opts[r'normal']:
1780 acceptable += 'nm'
1804 acceptable += 'nm'
1781 if opts[r'added']:
1805 if opts[r'added']:
1782 acceptable += 'a'
1806 acceptable += 'a'
1783 if opts[r'removed']:
1807 if opts[r'removed']:
1784 acceptable += 'r'
1808 acceptable += 'r'
1785 cwd = repo.getcwd()
1809 cwd = repo.getcwd()
1786 if not specs:
1810 if not specs:
1787 specs = ['.']
1811 specs = ['.']
1788
1812
1789 files, dirs = set(), set()
1813 files, dirs = set(), set()
1790 for spec in specs:
1814 for spec in specs:
1791 f, d = complete(spec, acceptable or 'nmar')
1815 f, d = complete(spec, acceptable or 'nmar')
1792 files.update(f)
1816 files.update(f)
1793 dirs.update(d)
1817 dirs.update(d)
1794 files.update(dirs)
1818 files.update(dirs)
1795 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1819 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1796 ui.write('\n')
1820 ui.write('\n')
1797
1821
1798 @command('debugpeer', [], _('PATH'), norepo=True)
1822 @command('debugpeer', [], _('PATH'), norepo=True)
1799 def debugpeer(ui, path):
1823 def debugpeer(ui, path):
1800 """establish a connection to a peer repository"""
1824 """establish a connection to a peer repository"""
1801 # Always enable peer request logging. Requires --debug to display
1825 # Always enable peer request logging. Requires --debug to display
1802 # though.
1826 # though.
1803 overrides = {
1827 overrides = {
1804 ('devel', 'debug.peer-request'): True,
1828 ('devel', 'debug.peer-request'): True,
1805 }
1829 }
1806
1830
1807 with ui.configoverride(overrides):
1831 with ui.configoverride(overrides):
1808 peer = hg.peer(ui, {}, path)
1832 peer = hg.peer(ui, {}, path)
1809
1833
1810 local = peer.local() is not None
1834 local = peer.local() is not None
1811 canpush = peer.canpush()
1835 canpush = peer.canpush()
1812
1836
1813 ui.write(_('url: %s\n') % peer.url())
1837 ui.write(_('url: %s\n') % peer.url())
1814 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1838 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1815 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1839 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1816
1840
1817 @command('debugpickmergetool',
1841 @command('debugpickmergetool',
1818 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1842 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1819 ('', 'changedelete', None, _('emulate merging change and delete')),
1843 ('', 'changedelete', None, _('emulate merging change and delete')),
1820 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1844 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1821 _('[PATTERN]...'),
1845 _('[PATTERN]...'),
1822 inferrepo=True)
1846 inferrepo=True)
1823 def debugpickmergetool(ui, repo, *pats, **opts):
1847 def debugpickmergetool(ui, repo, *pats, **opts):
1824 """examine which merge tool is chosen for specified file
1848 """examine which merge tool is chosen for specified file
1825
1849
1826 As described in :hg:`help merge-tools`, Mercurial examines
1850 As described in :hg:`help merge-tools`, Mercurial examines
1827 configurations below in this order to decide which merge tool is
1851 configurations below in this order to decide which merge tool is
1828 chosen for specified file.
1852 chosen for specified file.
1829
1853
1830 1. ``--tool`` option
1854 1. ``--tool`` option
1831 2. ``HGMERGE`` environment variable
1855 2. ``HGMERGE`` environment variable
1832 3. configurations in ``merge-patterns`` section
1856 3. configurations in ``merge-patterns`` section
1833 4. configuration of ``ui.merge``
1857 4. configuration of ``ui.merge``
1834 5. configurations in ``merge-tools`` section
1858 5. configurations in ``merge-tools`` section
1835 6. ``hgmerge`` tool (for historical reason only)
1859 6. ``hgmerge`` tool (for historical reason only)
1836 7. default tool for fallback (``:merge`` or ``:prompt``)
1860 7. default tool for fallback (``:merge`` or ``:prompt``)
1837
1861
1838 This command writes out examination result in the style below::
1862 This command writes out examination result in the style below::
1839
1863
1840 FILE = MERGETOOL
1864 FILE = MERGETOOL
1841
1865
1842 By default, all files known in the first parent context of the
1866 By default, all files known in the first parent context of the
1843 working directory are examined. Use file patterns and/or -I/-X
1867 working directory are examined. Use file patterns and/or -I/-X
1844 options to limit target files. -r/--rev is also useful to examine
1868 options to limit target files. -r/--rev is also useful to examine
1845 files in another context without actual updating to it.
1869 files in another context without actual updating to it.
1846
1870
1847 With --debug, this command shows warning messages while matching
1871 With --debug, this command shows warning messages while matching
1848 against ``merge-patterns`` and so on, too. It is recommended to
1872 against ``merge-patterns`` and so on, too. It is recommended to
1849 use this option with explicit file patterns and/or -I/-X options,
1873 use this option with explicit file patterns and/or -I/-X options,
1850 because this option increases amount of output per file according
1874 because this option increases amount of output per file according
1851 to configurations in hgrc.
1875 to configurations in hgrc.
1852
1876
1853 With -v/--verbose, this command shows configurations below at
1877 With -v/--verbose, this command shows configurations below at
1854 first (only if specified).
1878 first (only if specified).
1855
1879
1856 - ``--tool`` option
1880 - ``--tool`` option
1857 - ``HGMERGE`` environment variable
1881 - ``HGMERGE`` environment variable
1858 - configuration of ``ui.merge``
1882 - configuration of ``ui.merge``
1859
1883
1860 If merge tool is chosen before matching against
1884 If merge tool is chosen before matching against
1861 ``merge-patterns``, this command can't show any helpful
1885 ``merge-patterns``, this command can't show any helpful
1862 information, even with --debug. In such case, information above is
1886 information, even with --debug. In such case, information above is
1863 useful to know why a merge tool is chosen.
1887 useful to know why a merge tool is chosen.
1864 """
1888 """
1865 opts = pycompat.byteskwargs(opts)
1889 opts = pycompat.byteskwargs(opts)
1866 overrides = {}
1890 overrides = {}
1867 if opts['tool']:
1891 if opts['tool']:
1868 overrides[('ui', 'forcemerge')] = opts['tool']
1892 overrides[('ui', 'forcemerge')] = opts['tool']
1869 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1893 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1870
1894
1871 with ui.configoverride(overrides, 'debugmergepatterns'):
1895 with ui.configoverride(overrides, 'debugmergepatterns'):
1872 hgmerge = encoding.environ.get("HGMERGE")
1896 hgmerge = encoding.environ.get("HGMERGE")
1873 if hgmerge is not None:
1897 if hgmerge is not None:
1874 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1898 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1875 uimerge = ui.config("ui", "merge")
1899 uimerge = ui.config("ui", "merge")
1876 if uimerge:
1900 if uimerge:
1877 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1901 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1878
1902
1879 ctx = scmutil.revsingle(repo, opts.get('rev'))
1903 ctx = scmutil.revsingle(repo, opts.get('rev'))
1880 m = scmutil.match(ctx, pats, opts)
1904 m = scmutil.match(ctx, pats, opts)
1881 changedelete = opts['changedelete']
1905 changedelete = opts['changedelete']
1882 for path in ctx.walk(m):
1906 for path in ctx.walk(m):
1883 fctx = ctx[path]
1907 fctx = ctx[path]
1884 try:
1908 try:
1885 if not ui.debugflag:
1909 if not ui.debugflag:
1886 ui.pushbuffer(error=True)
1910 ui.pushbuffer(error=True)
1887 tool, toolpath = filemerge._picktool(repo, ui, path,
1911 tool, toolpath = filemerge._picktool(repo, ui, path,
1888 fctx.isbinary(),
1912 fctx.isbinary(),
1889 'l' in fctx.flags(),
1913 'l' in fctx.flags(),
1890 changedelete)
1914 changedelete)
1891 finally:
1915 finally:
1892 if not ui.debugflag:
1916 if not ui.debugflag:
1893 ui.popbuffer()
1917 ui.popbuffer()
1894 ui.write(('%s = %s\n') % (path, tool))
1918 ui.write(('%s = %s\n') % (path, tool))
1895
1919
1896 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1920 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1897 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1921 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1898 '''access the pushkey key/value protocol
1922 '''access the pushkey key/value protocol
1899
1923
1900 With two args, list the keys in the given namespace.
1924 With two args, list the keys in the given namespace.
1901
1925
1902 With five args, set a key to new if it currently is set to old.
1926 With five args, set a key to new if it currently is set to old.
1903 Reports success or failure.
1927 Reports success or failure.
1904 '''
1928 '''
1905
1929
1906 target = hg.peer(ui, {}, repopath)
1930 target = hg.peer(ui, {}, repopath)
1907 if keyinfo:
1931 if keyinfo:
1908 key, old, new = keyinfo
1932 key, old, new = keyinfo
1909 with target.commandexecutor() as e:
1933 with target.commandexecutor() as e:
1910 r = e.callcommand('pushkey', {
1934 r = e.callcommand('pushkey', {
1911 'namespace': namespace,
1935 'namespace': namespace,
1912 'key': key,
1936 'key': key,
1913 'old': old,
1937 'old': old,
1914 'new': new,
1938 'new': new,
1915 }).result()
1939 }).result()
1916
1940
1917 ui.status(pycompat.bytestr(r) + '\n')
1941 ui.status(pycompat.bytestr(r) + '\n')
1918 return not r
1942 return not r
1919 else:
1943 else:
1920 for k, v in sorted(target.listkeys(namespace).iteritems()):
1944 for k, v in sorted(target.listkeys(namespace).iteritems()):
1921 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1945 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1922 stringutil.escapestr(v)))
1946 stringutil.escapestr(v)))
1923
1947
1924 @command('debugpvec', [], _('A B'))
1948 @command('debugpvec', [], _('A B'))
1925 def debugpvec(ui, repo, a, b=None):
1949 def debugpvec(ui, repo, a, b=None):
1926 ca = scmutil.revsingle(repo, a)
1950 ca = scmutil.revsingle(repo, a)
1927 cb = scmutil.revsingle(repo, b)
1951 cb = scmutil.revsingle(repo, b)
1928 pa = pvec.ctxpvec(ca)
1952 pa = pvec.ctxpvec(ca)
1929 pb = pvec.ctxpvec(cb)
1953 pb = pvec.ctxpvec(cb)
1930 if pa == pb:
1954 if pa == pb:
1931 rel = "="
1955 rel = "="
1932 elif pa > pb:
1956 elif pa > pb:
1933 rel = ">"
1957 rel = ">"
1934 elif pa < pb:
1958 elif pa < pb:
1935 rel = "<"
1959 rel = "<"
1936 elif pa | pb:
1960 elif pa | pb:
1937 rel = "|"
1961 rel = "|"
1938 ui.write(_("a: %s\n") % pa)
1962 ui.write(_("a: %s\n") % pa)
1939 ui.write(_("b: %s\n") % pb)
1963 ui.write(_("b: %s\n") % pb)
1940 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1964 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1941 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1965 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1942 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1966 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1943 pa.distance(pb), rel))
1967 pa.distance(pb), rel))
1944
1968
1945 @command('debugrebuilddirstate|debugrebuildstate',
1969 @command('debugrebuilddirstate|debugrebuildstate',
1946 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1970 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1947 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1971 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1948 'the working copy parent')),
1972 'the working copy parent')),
1949 ],
1973 ],
1950 _('[-r REV]'))
1974 _('[-r REV]'))
1951 def debugrebuilddirstate(ui, repo, rev, **opts):
1975 def debugrebuilddirstate(ui, repo, rev, **opts):
1952 """rebuild the dirstate as it would look like for the given revision
1976 """rebuild the dirstate as it would look like for the given revision
1953
1977
1954 If no revision is specified the first current parent will be used.
1978 If no revision is specified the first current parent will be used.
1955
1979
1956 The dirstate will be set to the files of the given revision.
1980 The dirstate will be set to the files of the given revision.
1957 The actual working directory content or existing dirstate
1981 The actual working directory content or existing dirstate
1958 information such as adds or removes is not considered.
1982 information such as adds or removes is not considered.
1959
1983
1960 ``minimal`` will only rebuild the dirstate status for files that claim to be
1984 ``minimal`` will only rebuild the dirstate status for files that claim to be
1961 tracked but are not in the parent manifest, or that exist in the parent
1985 tracked but are not in the parent manifest, or that exist in the parent
1962 manifest but are not in the dirstate. It will not change adds, removes, or
1986 manifest but are not in the dirstate. It will not change adds, removes, or
1963 modified files that are in the working copy parent.
1987 modified files that are in the working copy parent.
1964
1988
1965 One use of this command is to make the next :hg:`status` invocation
1989 One use of this command is to make the next :hg:`status` invocation
1966 check the actual file content.
1990 check the actual file content.
1967 """
1991 """
1968 ctx = scmutil.revsingle(repo, rev)
1992 ctx = scmutil.revsingle(repo, rev)
1969 with repo.wlock():
1993 with repo.wlock():
1970 dirstate = repo.dirstate
1994 dirstate = repo.dirstate
1971 changedfiles = None
1995 changedfiles = None
1972 # See command doc for what minimal does.
1996 # See command doc for what minimal does.
1973 if opts.get(r'minimal'):
1997 if opts.get(r'minimal'):
1974 manifestfiles = set(ctx.manifest().keys())
1998 manifestfiles = set(ctx.manifest().keys())
1975 dirstatefiles = set(dirstate)
1999 dirstatefiles = set(dirstate)
1976 manifestonly = manifestfiles - dirstatefiles
2000 manifestonly = manifestfiles - dirstatefiles
1977 dsonly = dirstatefiles - manifestfiles
2001 dsonly = dirstatefiles - manifestfiles
1978 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2002 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1979 changedfiles = manifestonly | dsnotadded
2003 changedfiles = manifestonly | dsnotadded
1980
2004
1981 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2005 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1982
2006
1983 @command('debugrebuildfncache', [], '')
2007 @command('debugrebuildfncache', [], '')
1984 def debugrebuildfncache(ui, repo):
2008 def debugrebuildfncache(ui, repo):
1985 """rebuild the fncache file"""
2009 """rebuild the fncache file"""
1986 repair.rebuildfncache(ui, repo)
2010 repair.rebuildfncache(ui, repo)
1987
2011
1988 @command('debugrename',
2012 @command('debugrename',
1989 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2013 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1990 _('[-r REV] FILE'))
2014 _('[-r REV] FILE'))
1991 def debugrename(ui, repo, file1, *pats, **opts):
2015 def debugrename(ui, repo, file1, *pats, **opts):
1992 """dump rename information"""
2016 """dump rename information"""
1993
2017
1994 opts = pycompat.byteskwargs(opts)
2018 opts = pycompat.byteskwargs(opts)
1995 ctx = scmutil.revsingle(repo, opts.get('rev'))
2019 ctx = scmutil.revsingle(repo, opts.get('rev'))
1996 m = scmutil.match(ctx, (file1,) + pats, opts)
2020 m = scmutil.match(ctx, (file1,) + pats, opts)
1997 for abs in ctx.walk(m):
2021 for abs in ctx.walk(m):
1998 fctx = ctx[abs]
2022 fctx = ctx[abs]
1999 o = fctx.filelog().renamed(fctx.filenode())
2023 o = fctx.filelog().renamed(fctx.filenode())
2000 rel = m.rel(abs)
2024 rel = m.rel(abs)
2001 if o:
2025 if o:
2002 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2026 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2003 else:
2027 else:
2004 ui.write(_("%s not renamed\n") % rel)
2028 ui.write(_("%s not renamed\n") % rel)
2005
2029
2006 @command('debugrevlog', cmdutil.debugrevlogopts +
2030 @command('debugrevlog', cmdutil.debugrevlogopts +
2007 [('d', 'dump', False, _('dump index data'))],
2031 [('d', 'dump', False, _('dump index data'))],
2008 _('-c|-m|FILE'),
2032 _('-c|-m|FILE'),
2009 optionalrepo=True)
2033 optionalrepo=True)
2010 def debugrevlog(ui, repo, file_=None, **opts):
2034 def debugrevlog(ui, repo, file_=None, **opts):
2011 """show data and statistics about a revlog"""
2035 """show data and statistics about a revlog"""
2012 opts = pycompat.byteskwargs(opts)
2036 opts = pycompat.byteskwargs(opts)
2013 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2037 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2014
2038
2015 if opts.get("dump"):
2039 if opts.get("dump"):
2016 numrevs = len(r)
2040 numrevs = len(r)
2017 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2041 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2018 " rawsize totalsize compression heads chainlen\n"))
2042 " rawsize totalsize compression heads chainlen\n"))
2019 ts = 0
2043 ts = 0
2020 heads = set()
2044 heads = set()
2021
2045
2022 for rev in pycompat.xrange(numrevs):
2046 for rev in pycompat.xrange(numrevs):
2023 dbase = r.deltaparent(rev)
2047 dbase = r.deltaparent(rev)
2024 if dbase == -1:
2048 if dbase == -1:
2025 dbase = rev
2049 dbase = rev
2026 cbase = r.chainbase(rev)
2050 cbase = r.chainbase(rev)
2027 clen = r.chainlen(rev)
2051 clen = r.chainlen(rev)
2028 p1, p2 = r.parentrevs(rev)
2052 p1, p2 = r.parentrevs(rev)
2029 rs = r.rawsize(rev)
2053 rs = r.rawsize(rev)
2030 ts = ts + rs
2054 ts = ts + rs
2031 heads -= set(r.parentrevs(rev))
2055 heads -= set(r.parentrevs(rev))
2032 heads.add(rev)
2056 heads.add(rev)
2033 try:
2057 try:
2034 compression = ts / r.end(rev)
2058 compression = ts / r.end(rev)
2035 except ZeroDivisionError:
2059 except ZeroDivisionError:
2036 compression = 0
2060 compression = 0
2037 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2061 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2038 "%11d %5d %8d\n" %
2062 "%11d %5d %8d\n" %
2039 (rev, p1, p2, r.start(rev), r.end(rev),
2063 (rev, p1, p2, r.start(rev), r.end(rev),
2040 r.start(dbase), r.start(cbase),
2064 r.start(dbase), r.start(cbase),
2041 r.start(p1), r.start(p2),
2065 r.start(p1), r.start(p2),
2042 rs, ts, compression, len(heads), clen))
2066 rs, ts, compression, len(heads), clen))
2043 return 0
2067 return 0
2044
2068
2045 v = r.version
2069 v = r.version
2046 format = v & 0xFFFF
2070 format = v & 0xFFFF
2047 flags = []
2071 flags = []
2048 gdelta = False
2072 gdelta = False
2049 if v & revlog.FLAG_INLINE_DATA:
2073 if v & revlog.FLAG_INLINE_DATA:
2050 flags.append('inline')
2074 flags.append('inline')
2051 if v & revlog.FLAG_GENERALDELTA:
2075 if v & revlog.FLAG_GENERALDELTA:
2052 gdelta = True
2076 gdelta = True
2053 flags.append('generaldelta')
2077 flags.append('generaldelta')
2054 if not flags:
2078 if not flags:
2055 flags = ['(none)']
2079 flags = ['(none)']
2056
2080
2057 nummerges = 0
2081 nummerges = 0
2058 numfull = 0
2082 numfull = 0
2059 numprev = 0
2083 numprev = 0
2060 nump1 = 0
2084 nump1 = 0
2061 nump2 = 0
2085 nump2 = 0
2062 numother = 0
2086 numother = 0
2063 nump1prev = 0
2087 nump1prev = 0
2064 nump2prev = 0
2088 nump2prev = 0
2065 chainlengths = []
2089 chainlengths = []
2066 chainbases = []
2090 chainbases = []
2067 chainspans = []
2091 chainspans = []
2068
2092
2069 datasize = [None, 0, 0]
2093 datasize = [None, 0, 0]
2070 fullsize = [None, 0, 0]
2094 fullsize = [None, 0, 0]
2071 deltasize = [None, 0, 0]
2095 deltasize = [None, 0, 0]
2072 chunktypecounts = {}
2096 chunktypecounts = {}
2073 chunktypesizes = {}
2097 chunktypesizes = {}
2074
2098
2075 def addsize(size, l):
2099 def addsize(size, l):
2076 if l[0] is None or size < l[0]:
2100 if l[0] is None or size < l[0]:
2077 l[0] = size
2101 l[0] = size
2078 if size > l[1]:
2102 if size > l[1]:
2079 l[1] = size
2103 l[1] = size
2080 l[2] += size
2104 l[2] += size
2081
2105
2082 numrevs = len(r)
2106 numrevs = len(r)
2083 for rev in pycompat.xrange(numrevs):
2107 for rev in pycompat.xrange(numrevs):
2084 p1, p2 = r.parentrevs(rev)
2108 p1, p2 = r.parentrevs(rev)
2085 delta = r.deltaparent(rev)
2109 delta = r.deltaparent(rev)
2086 if format > 0:
2110 if format > 0:
2087 addsize(r.rawsize(rev), datasize)
2111 addsize(r.rawsize(rev), datasize)
2088 if p2 != nullrev:
2112 if p2 != nullrev:
2089 nummerges += 1
2113 nummerges += 1
2090 size = r.length(rev)
2114 size = r.length(rev)
2091 if delta == nullrev:
2115 if delta == nullrev:
2092 chainlengths.append(0)
2116 chainlengths.append(0)
2093 chainbases.append(r.start(rev))
2117 chainbases.append(r.start(rev))
2094 chainspans.append(size)
2118 chainspans.append(size)
2095 numfull += 1
2119 numfull += 1
2096 addsize(size, fullsize)
2120 addsize(size, fullsize)
2097 else:
2121 else:
2098 chainlengths.append(chainlengths[delta] + 1)
2122 chainlengths.append(chainlengths[delta] + 1)
2099 baseaddr = chainbases[delta]
2123 baseaddr = chainbases[delta]
2100 revaddr = r.start(rev)
2124 revaddr = r.start(rev)
2101 chainbases.append(baseaddr)
2125 chainbases.append(baseaddr)
2102 chainspans.append((revaddr - baseaddr) + size)
2126 chainspans.append((revaddr - baseaddr) + size)
2103 addsize(size, deltasize)
2127 addsize(size, deltasize)
2104 if delta == rev - 1:
2128 if delta == rev - 1:
2105 numprev += 1
2129 numprev += 1
2106 if delta == p1:
2130 if delta == p1:
2107 nump1prev += 1
2131 nump1prev += 1
2108 elif delta == p2:
2132 elif delta == p2:
2109 nump2prev += 1
2133 nump2prev += 1
2110 elif delta == p1:
2134 elif delta == p1:
2111 nump1 += 1
2135 nump1 += 1
2112 elif delta == p2:
2136 elif delta == p2:
2113 nump2 += 1
2137 nump2 += 1
2114 elif delta != nullrev:
2138 elif delta != nullrev:
2115 numother += 1
2139 numother += 1
2116
2140
2117 # Obtain data on the raw chunks in the revlog.
2141 # Obtain data on the raw chunks in the revlog.
2118 segment = r._getsegmentforrevs(rev, rev)[1]
2142 segment = r._getsegmentforrevs(rev, rev)[1]
2119 if segment:
2143 if segment:
2120 chunktype = bytes(segment[0:1])
2144 chunktype = bytes(segment[0:1])
2121 else:
2145 else:
2122 chunktype = 'empty'
2146 chunktype = 'empty'
2123
2147
2124 if chunktype not in chunktypecounts:
2148 if chunktype not in chunktypecounts:
2125 chunktypecounts[chunktype] = 0
2149 chunktypecounts[chunktype] = 0
2126 chunktypesizes[chunktype] = 0
2150 chunktypesizes[chunktype] = 0
2127
2151
2128 chunktypecounts[chunktype] += 1
2152 chunktypecounts[chunktype] += 1
2129 chunktypesizes[chunktype] += size
2153 chunktypesizes[chunktype] += size
2130
2154
2131 # Adjust size min value for empty cases
2155 # Adjust size min value for empty cases
2132 for size in (datasize, fullsize, deltasize):
2156 for size in (datasize, fullsize, deltasize):
2133 if size[0] is None:
2157 if size[0] is None:
2134 size[0] = 0
2158 size[0] = 0
2135
2159
2136 numdeltas = numrevs - numfull
2160 numdeltas = numrevs - numfull
2137 numoprev = numprev - nump1prev - nump2prev
2161 numoprev = numprev - nump1prev - nump2prev
2138 totalrawsize = datasize[2]
2162 totalrawsize = datasize[2]
2139 datasize[2] /= numrevs
2163 datasize[2] /= numrevs
2140 fulltotal = fullsize[2]
2164 fulltotal = fullsize[2]
2141 fullsize[2] /= numfull
2165 fullsize[2] /= numfull
2142 deltatotal = deltasize[2]
2166 deltatotal = deltasize[2]
2143 if numrevs - numfull > 0:
2167 if numrevs - numfull > 0:
2144 deltasize[2] /= numrevs - numfull
2168 deltasize[2] /= numrevs - numfull
2145 totalsize = fulltotal + deltatotal
2169 totalsize = fulltotal + deltatotal
2146 avgchainlen = sum(chainlengths) / numrevs
2170 avgchainlen = sum(chainlengths) / numrevs
2147 maxchainlen = max(chainlengths)
2171 maxchainlen = max(chainlengths)
2148 maxchainspan = max(chainspans)
2172 maxchainspan = max(chainspans)
2149 compratio = 1
2173 compratio = 1
2150 if totalsize:
2174 if totalsize:
2151 compratio = totalrawsize / totalsize
2175 compratio = totalrawsize / totalsize
2152
2176
2153 basedfmtstr = '%%%dd\n'
2177 basedfmtstr = '%%%dd\n'
2154 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2178 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2155
2179
2156 def dfmtstr(max):
2180 def dfmtstr(max):
2157 return basedfmtstr % len(str(max))
2181 return basedfmtstr % len(str(max))
2158 def pcfmtstr(max, padding=0):
2182 def pcfmtstr(max, padding=0):
2159 return basepcfmtstr % (len(str(max)), ' ' * padding)
2183 return basepcfmtstr % (len(str(max)), ' ' * padding)
2160
2184
2161 def pcfmt(value, total):
2185 def pcfmt(value, total):
2162 if total:
2186 if total:
2163 return (value, 100 * float(value) / total)
2187 return (value, 100 * float(value) / total)
2164 else:
2188 else:
2165 return value, 100.0
2189 return value, 100.0
2166
2190
2167 ui.write(('format : %d\n') % format)
2191 ui.write(('format : %d\n') % format)
2168 ui.write(('flags : %s\n') % ', '.join(flags))
2192 ui.write(('flags : %s\n') % ', '.join(flags))
2169
2193
2170 ui.write('\n')
2194 ui.write('\n')
2171 fmt = pcfmtstr(totalsize)
2195 fmt = pcfmtstr(totalsize)
2172 fmt2 = dfmtstr(totalsize)
2196 fmt2 = dfmtstr(totalsize)
2173 ui.write(('revisions : ') + fmt2 % numrevs)
2197 ui.write(('revisions : ') + fmt2 % numrevs)
2174 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2198 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2175 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2199 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2176 ui.write(('revisions : ') + fmt2 % numrevs)
2200 ui.write(('revisions : ') + fmt2 % numrevs)
2177 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2201 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2178 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2202 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2179 ui.write(('revision size : ') + fmt2 % totalsize)
2203 ui.write(('revision size : ') + fmt2 % totalsize)
2180 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2204 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2181 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2205 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2182
2206
2183 def fmtchunktype(chunktype):
2207 def fmtchunktype(chunktype):
2184 if chunktype == 'empty':
2208 if chunktype == 'empty':
2185 return ' %s : ' % chunktype
2209 return ' %s : ' % chunktype
2186 elif chunktype in pycompat.bytestr(string.ascii_letters):
2210 elif chunktype in pycompat.bytestr(string.ascii_letters):
2187 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2211 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2188 else:
2212 else:
2189 return ' 0x%s : ' % hex(chunktype)
2213 return ' 0x%s : ' % hex(chunktype)
2190
2214
2191 ui.write('\n')
2215 ui.write('\n')
2192 ui.write(('chunks : ') + fmt2 % numrevs)
2216 ui.write(('chunks : ') + fmt2 % numrevs)
2193 for chunktype in sorted(chunktypecounts):
2217 for chunktype in sorted(chunktypecounts):
2194 ui.write(fmtchunktype(chunktype))
2218 ui.write(fmtchunktype(chunktype))
2195 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2219 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2196 ui.write(('chunks size : ') + fmt2 % totalsize)
2220 ui.write(('chunks size : ') + fmt2 % totalsize)
2197 for chunktype in sorted(chunktypecounts):
2221 for chunktype in sorted(chunktypecounts):
2198 ui.write(fmtchunktype(chunktype))
2222 ui.write(fmtchunktype(chunktype))
2199 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2223 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2200
2224
2201 ui.write('\n')
2225 ui.write('\n')
2202 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2226 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2203 ui.write(('avg chain length : ') + fmt % avgchainlen)
2227 ui.write(('avg chain length : ') + fmt % avgchainlen)
2204 ui.write(('max chain length : ') + fmt % maxchainlen)
2228 ui.write(('max chain length : ') + fmt % maxchainlen)
2205 ui.write(('max chain reach : ') + fmt % maxchainspan)
2229 ui.write(('max chain reach : ') + fmt % maxchainspan)
2206 ui.write(('compression ratio : ') + fmt % compratio)
2230 ui.write(('compression ratio : ') + fmt % compratio)
2207
2231
2208 if format > 0:
2232 if format > 0:
2209 ui.write('\n')
2233 ui.write('\n')
2210 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2234 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2211 % tuple(datasize))
2235 % tuple(datasize))
2212 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2236 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2213 % tuple(fullsize))
2237 % tuple(fullsize))
2214 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2238 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2215 % tuple(deltasize))
2239 % tuple(deltasize))
2216
2240
2217 if numdeltas > 0:
2241 if numdeltas > 0:
2218 ui.write('\n')
2242 ui.write('\n')
2219 fmt = pcfmtstr(numdeltas)
2243 fmt = pcfmtstr(numdeltas)
2220 fmt2 = pcfmtstr(numdeltas, 4)
2244 fmt2 = pcfmtstr(numdeltas, 4)
2221 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2245 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2222 if numprev > 0:
2246 if numprev > 0:
2223 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2247 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2224 numprev))
2248 numprev))
2225 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2249 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2226 numprev))
2250 numprev))
2227 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2251 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2228 numprev))
2252 numprev))
2229 if gdelta:
2253 if gdelta:
2230 ui.write(('deltas against p1 : ')
2254 ui.write(('deltas against p1 : ')
2231 + fmt % pcfmt(nump1, numdeltas))
2255 + fmt % pcfmt(nump1, numdeltas))
2232 ui.write(('deltas against p2 : ')
2256 ui.write(('deltas against p2 : ')
2233 + fmt % pcfmt(nump2, numdeltas))
2257 + fmt % pcfmt(nump2, numdeltas))
2234 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2258 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2235 numdeltas))
2259 numdeltas))
2236
2260
2237 @command('debugrevspec',
2261 @command('debugrevspec',
2238 [('', 'optimize', None,
2262 [('', 'optimize', None,
2239 _('print parsed tree after optimizing (DEPRECATED)')),
2263 _('print parsed tree after optimizing (DEPRECATED)')),
2240 ('', 'show-revs', True, _('print list of result revisions (default)')),
2264 ('', 'show-revs', True, _('print list of result revisions (default)')),
2241 ('s', 'show-set', None, _('print internal representation of result set')),
2265 ('s', 'show-set', None, _('print internal representation of result set')),
2242 ('p', 'show-stage', [],
2266 ('p', 'show-stage', [],
2243 _('print parsed tree at the given stage'), _('NAME')),
2267 _('print parsed tree at the given stage'), _('NAME')),
2244 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2268 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2245 ('', 'verify-optimized', False, _('verify optimized result')),
2269 ('', 'verify-optimized', False, _('verify optimized result')),
2246 ],
2270 ],
2247 ('REVSPEC'))
2271 ('REVSPEC'))
2248 def debugrevspec(ui, repo, expr, **opts):
2272 def debugrevspec(ui, repo, expr, **opts):
2249 """parse and apply a revision specification
2273 """parse and apply a revision specification
2250
2274
2251 Use -p/--show-stage option to print the parsed tree at the given stages.
2275 Use -p/--show-stage option to print the parsed tree at the given stages.
2252 Use -p all to print tree at every stage.
2276 Use -p all to print tree at every stage.
2253
2277
2254 Use --no-show-revs option with -s or -p to print only the set
2278 Use --no-show-revs option with -s or -p to print only the set
2255 representation or the parsed tree respectively.
2279 representation or the parsed tree respectively.
2256
2280
2257 Use --verify-optimized to compare the optimized result with the unoptimized
2281 Use --verify-optimized to compare the optimized result with the unoptimized
2258 one. Returns 1 if the optimized result differs.
2282 one. Returns 1 if the optimized result differs.
2259 """
2283 """
2260 opts = pycompat.byteskwargs(opts)
2284 opts = pycompat.byteskwargs(opts)
2261 aliases = ui.configitems('revsetalias')
2285 aliases = ui.configitems('revsetalias')
2262 stages = [
2286 stages = [
2263 ('parsed', lambda tree: tree),
2287 ('parsed', lambda tree: tree),
2264 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2288 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2265 ui.warn)),
2289 ui.warn)),
2266 ('concatenated', revsetlang.foldconcat),
2290 ('concatenated', revsetlang.foldconcat),
2267 ('analyzed', revsetlang.analyze),
2291 ('analyzed', revsetlang.analyze),
2268 ('optimized', revsetlang.optimize),
2292 ('optimized', revsetlang.optimize),
2269 ]
2293 ]
2270 if opts['no_optimized']:
2294 if opts['no_optimized']:
2271 stages = stages[:-1]
2295 stages = stages[:-1]
2272 if opts['verify_optimized'] and opts['no_optimized']:
2296 if opts['verify_optimized'] and opts['no_optimized']:
2273 raise error.Abort(_('cannot use --verify-optimized with '
2297 raise error.Abort(_('cannot use --verify-optimized with '
2274 '--no-optimized'))
2298 '--no-optimized'))
2275 stagenames = set(n for n, f in stages)
2299 stagenames = set(n for n, f in stages)
2276
2300
2277 showalways = set()
2301 showalways = set()
2278 showchanged = set()
2302 showchanged = set()
2279 if ui.verbose and not opts['show_stage']:
2303 if ui.verbose and not opts['show_stage']:
2280 # show parsed tree by --verbose (deprecated)
2304 # show parsed tree by --verbose (deprecated)
2281 showalways.add('parsed')
2305 showalways.add('parsed')
2282 showchanged.update(['expanded', 'concatenated'])
2306 showchanged.update(['expanded', 'concatenated'])
2283 if opts['optimize']:
2307 if opts['optimize']:
2284 showalways.add('optimized')
2308 showalways.add('optimized')
2285 if opts['show_stage'] and opts['optimize']:
2309 if opts['show_stage'] and opts['optimize']:
2286 raise error.Abort(_('cannot use --optimize with --show-stage'))
2310 raise error.Abort(_('cannot use --optimize with --show-stage'))
2287 if opts['show_stage'] == ['all']:
2311 if opts['show_stage'] == ['all']:
2288 showalways.update(stagenames)
2312 showalways.update(stagenames)
2289 else:
2313 else:
2290 for n in opts['show_stage']:
2314 for n in opts['show_stage']:
2291 if n not in stagenames:
2315 if n not in stagenames:
2292 raise error.Abort(_('invalid stage name: %s') % n)
2316 raise error.Abort(_('invalid stage name: %s') % n)
2293 showalways.update(opts['show_stage'])
2317 showalways.update(opts['show_stage'])
2294
2318
2295 treebystage = {}
2319 treebystage = {}
2296 printedtree = None
2320 printedtree = None
2297 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2321 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2298 for n, f in stages:
2322 for n, f in stages:
2299 treebystage[n] = tree = f(tree)
2323 treebystage[n] = tree = f(tree)
2300 if n in showalways or (n in showchanged and tree != printedtree):
2324 if n in showalways or (n in showchanged and tree != printedtree):
2301 if opts['show_stage'] or n != 'parsed':
2325 if opts['show_stage'] or n != 'parsed':
2302 ui.write(("* %s:\n") % n)
2326 ui.write(("* %s:\n") % n)
2303 ui.write(revsetlang.prettyformat(tree), "\n")
2327 ui.write(revsetlang.prettyformat(tree), "\n")
2304 printedtree = tree
2328 printedtree = tree
2305
2329
2306 if opts['verify_optimized']:
2330 if opts['verify_optimized']:
2307 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2331 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2308 brevs = revset.makematcher(treebystage['optimized'])(repo)
2332 brevs = revset.makematcher(treebystage['optimized'])(repo)
2309 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2333 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2310 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2334 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2311 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2335 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2312 arevs = list(arevs)
2336 arevs = list(arevs)
2313 brevs = list(brevs)
2337 brevs = list(brevs)
2314 if arevs == brevs:
2338 if arevs == brevs:
2315 return 0
2339 return 0
2316 ui.write(('--- analyzed\n'), label='diff.file_a')
2340 ui.write(('--- analyzed\n'), label='diff.file_a')
2317 ui.write(('+++ optimized\n'), label='diff.file_b')
2341 ui.write(('+++ optimized\n'), label='diff.file_b')
2318 sm = difflib.SequenceMatcher(None, arevs, brevs)
2342 sm = difflib.SequenceMatcher(None, arevs, brevs)
2319 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2343 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2320 if tag in ('delete', 'replace'):
2344 if tag in ('delete', 'replace'):
2321 for c in arevs[alo:ahi]:
2345 for c in arevs[alo:ahi]:
2322 ui.write('-%s\n' % c, label='diff.deleted')
2346 ui.write('-%s\n' % c, label='diff.deleted')
2323 if tag in ('insert', 'replace'):
2347 if tag in ('insert', 'replace'):
2324 for c in brevs[blo:bhi]:
2348 for c in brevs[blo:bhi]:
2325 ui.write('+%s\n' % c, label='diff.inserted')
2349 ui.write('+%s\n' % c, label='diff.inserted')
2326 if tag == 'equal':
2350 if tag == 'equal':
2327 for c in arevs[alo:ahi]:
2351 for c in arevs[alo:ahi]:
2328 ui.write(' %s\n' % c)
2352 ui.write(' %s\n' % c)
2329 return 1
2353 return 1
2330
2354
2331 func = revset.makematcher(tree)
2355 func = revset.makematcher(tree)
2332 revs = func(repo)
2356 revs = func(repo)
2333 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2357 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2334 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2358 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2335 if not opts['show_revs']:
2359 if not opts['show_revs']:
2336 return
2360 return
2337 for c in revs:
2361 for c in revs:
2338 ui.write("%d\n" % c)
2362 ui.write("%d\n" % c)
2339
2363
2340 @command('debugserve', [
2364 @command('debugserve', [
2341 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2365 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2342 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2366 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2343 ('', 'logiofile', '', _('file to log server I/O to')),
2367 ('', 'logiofile', '', _('file to log server I/O to')),
2344 ], '')
2368 ], '')
2345 def debugserve(ui, repo, **opts):
2369 def debugserve(ui, repo, **opts):
2346 """run a server with advanced settings
2370 """run a server with advanced settings
2347
2371
2348 This command is similar to :hg:`serve`. It exists partially as a
2372 This command is similar to :hg:`serve`. It exists partially as a
2349 workaround to the fact that ``hg serve --stdio`` must have specific
2373 workaround to the fact that ``hg serve --stdio`` must have specific
2350 arguments for security reasons.
2374 arguments for security reasons.
2351 """
2375 """
2352 opts = pycompat.byteskwargs(opts)
2376 opts = pycompat.byteskwargs(opts)
2353
2377
2354 if not opts['sshstdio']:
2378 if not opts['sshstdio']:
2355 raise error.Abort(_('only --sshstdio is currently supported'))
2379 raise error.Abort(_('only --sshstdio is currently supported'))
2356
2380
2357 logfh = None
2381 logfh = None
2358
2382
2359 if opts['logiofd'] and opts['logiofile']:
2383 if opts['logiofd'] and opts['logiofile']:
2360 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2384 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2361
2385
2362 if opts['logiofd']:
2386 if opts['logiofd']:
2363 # Line buffered because output is line based.
2387 # Line buffered because output is line based.
2364 try:
2388 try:
2365 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2389 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2366 except OSError as e:
2390 except OSError as e:
2367 if e.errno != errno.ESPIPE:
2391 if e.errno != errno.ESPIPE:
2368 raise
2392 raise
2369 # can't seek a pipe, so `ab` mode fails on py3
2393 # can't seek a pipe, so `ab` mode fails on py3
2370 logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
2394 logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
2371 elif opts['logiofile']:
2395 elif opts['logiofile']:
2372 logfh = open(opts['logiofile'], 'ab', 1)
2396 logfh = open(opts['logiofile'], 'ab', 1)
2373
2397
2374 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2398 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2375 s.serve_forever()
2399 s.serve_forever()
2376
2400
2377 @command('debugsetparents', [], _('REV1 [REV2]'))
2401 @command('debugsetparents', [], _('REV1 [REV2]'))
2378 def debugsetparents(ui, repo, rev1, rev2=None):
2402 def debugsetparents(ui, repo, rev1, rev2=None):
2379 """manually set the parents of the current working directory
2403 """manually set the parents of the current working directory
2380
2404
2381 This is useful for writing repository conversion tools, but should
2405 This is useful for writing repository conversion tools, but should
2382 be used with care. For example, neither the working directory nor the
2406 be used with care. For example, neither the working directory nor the
2383 dirstate is updated, so file status may be incorrect after running this
2407 dirstate is updated, so file status may be incorrect after running this
2384 command.
2408 command.
2385
2409
2386 Returns 0 on success.
2410 Returns 0 on success.
2387 """
2411 """
2388
2412
2389 node1 = scmutil.revsingle(repo, rev1).node()
2413 node1 = scmutil.revsingle(repo, rev1).node()
2390 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2414 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2391
2415
2392 with repo.wlock():
2416 with repo.wlock():
2393 repo.setparents(node1, node2)
2417 repo.setparents(node1, node2)
2394
2418
2395 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2419 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2396 def debugssl(ui, repo, source=None, **opts):
2420 def debugssl(ui, repo, source=None, **opts):
2397 '''test a secure connection to a server
2421 '''test a secure connection to a server
2398
2422
2399 This builds the certificate chain for the server on Windows, installing the
2423 This builds the certificate chain for the server on Windows, installing the
2400 missing intermediates and trusted root via Windows Update if necessary. It
2424 missing intermediates and trusted root via Windows Update if necessary. It
2401 does nothing on other platforms.
2425 does nothing on other platforms.
2402
2426
2403 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2427 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2404 that server is used. See :hg:`help urls` for more information.
2428 that server is used. See :hg:`help urls` for more information.
2405
2429
2406 If the update succeeds, retry the original operation. Otherwise, the cause
2430 If the update succeeds, retry the original operation. Otherwise, the cause
2407 of the SSL error is likely another issue.
2431 of the SSL error is likely another issue.
2408 '''
2432 '''
2409 if not pycompat.iswindows:
2433 if not pycompat.iswindows:
2410 raise error.Abort(_('certificate chain building is only possible on '
2434 raise error.Abort(_('certificate chain building is only possible on '
2411 'Windows'))
2435 'Windows'))
2412
2436
2413 if not source:
2437 if not source:
2414 if not repo:
2438 if not repo:
2415 raise error.Abort(_("there is no Mercurial repository here, and no "
2439 raise error.Abort(_("there is no Mercurial repository here, and no "
2416 "server specified"))
2440 "server specified"))
2417 source = "default"
2441 source = "default"
2418
2442
2419 source, branches = hg.parseurl(ui.expandpath(source))
2443 source, branches = hg.parseurl(ui.expandpath(source))
2420 url = util.url(source)
2444 url = util.url(source)
2421 addr = None
2445 addr = None
2422
2446
2423 defaultport = {'https': 443, 'ssh': 22}
2447 defaultport = {'https': 443, 'ssh': 22}
2424 if url.scheme in defaultport:
2448 if url.scheme in defaultport:
2425 try:
2449 try:
2426 addr = (url.host, int(url.port or defaultport[url.scheme]))
2450 addr = (url.host, int(url.port or defaultport[url.scheme]))
2427 except ValueError:
2451 except ValueError:
2428 raise error.Abort(_("malformed port number in URL"))
2452 raise error.Abort(_("malformed port number in URL"))
2429 else:
2453 else:
2430 raise error.Abort(_("only https and ssh connections are supported"))
2454 raise error.Abort(_("only https and ssh connections are supported"))
2431
2455
2432 from . import win32
2456 from . import win32
2433
2457
2434 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2458 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2435 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2459 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2436
2460
2437 try:
2461 try:
2438 s.connect(addr)
2462 s.connect(addr)
2439 cert = s.getpeercert(True)
2463 cert = s.getpeercert(True)
2440
2464
2441 ui.status(_('checking the certificate chain for %s\n') % url.host)
2465 ui.status(_('checking the certificate chain for %s\n') % url.host)
2442
2466
2443 complete = win32.checkcertificatechain(cert, build=False)
2467 complete = win32.checkcertificatechain(cert, build=False)
2444
2468
2445 if not complete:
2469 if not complete:
2446 ui.status(_('certificate chain is incomplete, updating... '))
2470 ui.status(_('certificate chain is incomplete, updating... '))
2447
2471
2448 if not win32.checkcertificatechain(cert):
2472 if not win32.checkcertificatechain(cert):
2449 ui.status(_('failed.\n'))
2473 ui.status(_('failed.\n'))
2450 else:
2474 else:
2451 ui.status(_('done.\n'))
2475 ui.status(_('done.\n'))
2452 else:
2476 else:
2453 ui.status(_('full certificate chain is available\n'))
2477 ui.status(_('full certificate chain is available\n'))
2454 finally:
2478 finally:
2455 s.close()
2479 s.close()
2456
2480
2457 @command('debugsub',
2481 @command('debugsub',
2458 [('r', 'rev', '',
2482 [('r', 'rev', '',
2459 _('revision to check'), _('REV'))],
2483 _('revision to check'), _('REV'))],
2460 _('[-r REV] [REV]'))
2484 _('[-r REV] [REV]'))
2461 def debugsub(ui, repo, rev=None):
2485 def debugsub(ui, repo, rev=None):
2462 ctx = scmutil.revsingle(repo, rev, None)
2486 ctx = scmutil.revsingle(repo, rev, None)
2463 for k, v in sorted(ctx.substate.items()):
2487 for k, v in sorted(ctx.substate.items()):
2464 ui.write(('path %s\n') % k)
2488 ui.write(('path %s\n') % k)
2465 ui.write((' source %s\n') % v[0])
2489 ui.write((' source %s\n') % v[0])
2466 ui.write((' revision %s\n') % v[1])
2490 ui.write((' revision %s\n') % v[1])
2467
2491
2468 @command('debugsuccessorssets',
2492 @command('debugsuccessorssets',
2469 [('', 'closest', False, _('return closest successors sets only'))],
2493 [('', 'closest', False, _('return closest successors sets only'))],
2470 _('[REV]'))
2494 _('[REV]'))
2471 def debugsuccessorssets(ui, repo, *revs, **opts):
2495 def debugsuccessorssets(ui, repo, *revs, **opts):
2472 """show set of successors for revision
2496 """show set of successors for revision
2473
2497
2474 A successors set of changeset A is a consistent group of revisions that
2498 A successors set of changeset A is a consistent group of revisions that
2475 succeed A. It contains non-obsolete changesets only unless closests
2499 succeed A. It contains non-obsolete changesets only unless closests
2476 successors set is set.
2500 successors set is set.
2477
2501
2478 In most cases a changeset A has a single successors set containing a single
2502 In most cases a changeset A has a single successors set containing a single
2479 successor (changeset A replaced by A').
2503 successor (changeset A replaced by A').
2480
2504
2481 A changeset that is made obsolete with no successors are called "pruned".
2505 A changeset that is made obsolete with no successors are called "pruned".
2482 Such changesets have no successors sets at all.
2506 Such changesets have no successors sets at all.
2483
2507
2484 A changeset that has been "split" will have a successors set containing
2508 A changeset that has been "split" will have a successors set containing
2485 more than one successor.
2509 more than one successor.
2486
2510
2487 A changeset that has been rewritten in multiple different ways is called
2511 A changeset that has been rewritten in multiple different ways is called
2488 "divergent". Such changesets have multiple successor sets (each of which
2512 "divergent". Such changesets have multiple successor sets (each of which
2489 may also be split, i.e. have multiple successors).
2513 may also be split, i.e. have multiple successors).
2490
2514
2491 Results are displayed as follows::
2515 Results are displayed as follows::
2492
2516
2493 <rev1>
2517 <rev1>
2494 <successors-1A>
2518 <successors-1A>
2495 <rev2>
2519 <rev2>
2496 <successors-2A>
2520 <successors-2A>
2497 <successors-2B1> <successors-2B2> <successors-2B3>
2521 <successors-2B1> <successors-2B2> <successors-2B3>
2498
2522
2499 Here rev2 has two possible (i.e. divergent) successors sets. The first
2523 Here rev2 has two possible (i.e. divergent) successors sets. The first
2500 holds one element, whereas the second holds three (i.e. the changeset has
2524 holds one element, whereas the second holds three (i.e. the changeset has
2501 been split).
2525 been split).
2502 """
2526 """
2503 # passed to successorssets caching computation from one call to another
2527 # passed to successorssets caching computation from one call to another
2504 cache = {}
2528 cache = {}
2505 ctx2str = bytes
2529 ctx2str = bytes
2506 node2str = short
2530 node2str = short
2507 for rev in scmutil.revrange(repo, revs):
2531 for rev in scmutil.revrange(repo, revs):
2508 ctx = repo[rev]
2532 ctx = repo[rev]
2509 ui.write('%s\n'% ctx2str(ctx))
2533 ui.write('%s\n'% ctx2str(ctx))
2510 for succsset in obsutil.successorssets(repo, ctx.node(),
2534 for succsset in obsutil.successorssets(repo, ctx.node(),
2511 closest=opts[r'closest'],
2535 closest=opts[r'closest'],
2512 cache=cache):
2536 cache=cache):
2513 if succsset:
2537 if succsset:
2514 ui.write(' ')
2538 ui.write(' ')
2515 ui.write(node2str(succsset[0]))
2539 ui.write(node2str(succsset[0]))
2516 for node in succsset[1:]:
2540 for node in succsset[1:]:
2517 ui.write(' ')
2541 ui.write(' ')
2518 ui.write(node2str(node))
2542 ui.write(node2str(node))
2519 ui.write('\n')
2543 ui.write('\n')
2520
2544
2521 @command('debugtemplate',
2545 @command('debugtemplate',
2522 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2546 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2523 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2547 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2524 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2548 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2525 optionalrepo=True)
2549 optionalrepo=True)
2526 def debugtemplate(ui, repo, tmpl, **opts):
2550 def debugtemplate(ui, repo, tmpl, **opts):
2527 """parse and apply a template
2551 """parse and apply a template
2528
2552
2529 If -r/--rev is given, the template is processed as a log template and
2553 If -r/--rev is given, the template is processed as a log template and
2530 applied to the given changesets. Otherwise, it is processed as a generic
2554 applied to the given changesets. Otherwise, it is processed as a generic
2531 template.
2555 template.
2532
2556
2533 Use --verbose to print the parsed tree.
2557 Use --verbose to print the parsed tree.
2534 """
2558 """
2535 revs = None
2559 revs = None
2536 if opts[r'rev']:
2560 if opts[r'rev']:
2537 if repo is None:
2561 if repo is None:
2538 raise error.RepoError(_('there is no Mercurial repository here '
2562 raise error.RepoError(_('there is no Mercurial repository here '
2539 '(.hg not found)'))
2563 '(.hg not found)'))
2540 revs = scmutil.revrange(repo, opts[r'rev'])
2564 revs = scmutil.revrange(repo, opts[r'rev'])
2541
2565
2542 props = {}
2566 props = {}
2543 for d in opts[r'define']:
2567 for d in opts[r'define']:
2544 try:
2568 try:
2545 k, v = (e.strip() for e in d.split('=', 1))
2569 k, v = (e.strip() for e in d.split('=', 1))
2546 if not k or k == 'ui':
2570 if not k or k == 'ui':
2547 raise ValueError
2571 raise ValueError
2548 props[k] = v
2572 props[k] = v
2549 except ValueError:
2573 except ValueError:
2550 raise error.Abort(_('malformed keyword definition: %s') % d)
2574 raise error.Abort(_('malformed keyword definition: %s') % d)
2551
2575
2552 if ui.verbose:
2576 if ui.verbose:
2553 aliases = ui.configitems('templatealias')
2577 aliases = ui.configitems('templatealias')
2554 tree = templater.parse(tmpl)
2578 tree = templater.parse(tmpl)
2555 ui.note(templater.prettyformat(tree), '\n')
2579 ui.note(templater.prettyformat(tree), '\n')
2556 newtree = templater.expandaliases(tree, aliases)
2580 newtree = templater.expandaliases(tree, aliases)
2557 if newtree != tree:
2581 if newtree != tree:
2558 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2582 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2559
2583
2560 if revs is None:
2584 if revs is None:
2561 tres = formatter.templateresources(ui, repo)
2585 tres = formatter.templateresources(ui, repo)
2562 t = formatter.maketemplater(ui, tmpl, resources=tres)
2586 t = formatter.maketemplater(ui, tmpl, resources=tres)
2563 if ui.verbose:
2587 if ui.verbose:
2564 kwds, funcs = t.symbolsuseddefault()
2588 kwds, funcs = t.symbolsuseddefault()
2565 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2589 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2566 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2590 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2567 ui.write(t.renderdefault(props))
2591 ui.write(t.renderdefault(props))
2568 else:
2592 else:
2569 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2593 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2570 if ui.verbose:
2594 if ui.verbose:
2571 kwds, funcs = displayer.t.symbolsuseddefault()
2595 kwds, funcs = displayer.t.symbolsuseddefault()
2572 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2596 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2573 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2597 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2574 for r in revs:
2598 for r in revs:
2575 displayer.show(repo[r], **pycompat.strkwargs(props))
2599 displayer.show(repo[r], **pycompat.strkwargs(props))
2576 displayer.close()
2600 displayer.close()
2577
2601
2578 @command('debuguigetpass', [
2602 @command('debuguigetpass', [
2579 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2603 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2580 ], _('[-p TEXT]'), norepo=True)
2604 ], _('[-p TEXT]'), norepo=True)
2581 def debuguigetpass(ui, prompt=''):
2605 def debuguigetpass(ui, prompt=''):
2582 """show prompt to type password"""
2606 """show prompt to type password"""
2583 r = ui.getpass(prompt)
2607 r = ui.getpass(prompt)
2584 ui.write(('respose: %s\n') % r)
2608 ui.write(('respose: %s\n') % r)
2585
2609
2586 @command('debuguiprompt', [
2610 @command('debuguiprompt', [
2587 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2611 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2588 ], _('[-p TEXT]'), norepo=True)
2612 ], _('[-p TEXT]'), norepo=True)
2589 def debuguiprompt(ui, prompt=''):
2613 def debuguiprompt(ui, prompt=''):
2590 """show plain prompt"""
2614 """show plain prompt"""
2591 r = ui.prompt(prompt)
2615 r = ui.prompt(prompt)
2592 ui.write(('response: %s\n') % r)
2616 ui.write(('response: %s\n') % r)
2593
2617
2594 @command('debugupdatecaches', [])
2618 @command('debugupdatecaches', [])
2595 def debugupdatecaches(ui, repo, *pats, **opts):
2619 def debugupdatecaches(ui, repo, *pats, **opts):
2596 """warm all known caches in the repository"""
2620 """warm all known caches in the repository"""
2597 with repo.wlock(), repo.lock():
2621 with repo.wlock(), repo.lock():
2598 repo.updatecaches(full=True)
2622 repo.updatecaches(full=True)
2599
2623
2600 @command('debugupgraderepo', [
2624 @command('debugupgraderepo', [
2601 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2625 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2602 ('', 'run', False, _('performs an upgrade')),
2626 ('', 'run', False, _('performs an upgrade')),
2603 ])
2627 ])
2604 def debugupgraderepo(ui, repo, run=False, optimize=None):
2628 def debugupgraderepo(ui, repo, run=False, optimize=None):
2605 """upgrade a repository to use different features
2629 """upgrade a repository to use different features
2606
2630
2607 If no arguments are specified, the repository is evaluated for upgrade
2631 If no arguments are specified, the repository is evaluated for upgrade
2608 and a list of problems and potential optimizations is printed.
2632 and a list of problems and potential optimizations is printed.
2609
2633
2610 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2634 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2611 can be influenced via additional arguments. More details will be provided
2635 can be influenced via additional arguments. More details will be provided
2612 by the command output when run without ``--run``.
2636 by the command output when run without ``--run``.
2613
2637
2614 During the upgrade, the repository will be locked and no writes will be
2638 During the upgrade, the repository will be locked and no writes will be
2615 allowed.
2639 allowed.
2616
2640
2617 At the end of the upgrade, the repository may not be readable while new
2641 At the end of the upgrade, the repository may not be readable while new
2618 repository data is swapped in. This window will be as long as it takes to
2642 repository data is swapped in. This window will be as long as it takes to
2619 rename some directories inside the ``.hg`` directory. On most machines, this
2643 rename some directories inside the ``.hg`` directory. On most machines, this
2620 should complete almost instantaneously and the chances of a consumer being
2644 should complete almost instantaneously and the chances of a consumer being
2621 unable to access the repository should be low.
2645 unable to access the repository should be low.
2622 """
2646 """
2623 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2647 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2624
2648
2625 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2649 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2626 inferrepo=True)
2650 inferrepo=True)
2627 def debugwalk(ui, repo, *pats, **opts):
2651 def debugwalk(ui, repo, *pats, **opts):
2628 """show how files match on given patterns"""
2652 """show how files match on given patterns"""
2629 opts = pycompat.byteskwargs(opts)
2653 opts = pycompat.byteskwargs(opts)
2630 m = scmutil.match(repo[None], pats, opts)
2654 m = scmutil.match(repo[None], pats, opts)
2631 if ui.verbose:
2655 if ui.verbose:
2632 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
2656 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
2633 items = list(repo[None].walk(m))
2657 items = list(repo[None].walk(m))
2634 if not items:
2658 if not items:
2635 return
2659 return
2636 f = lambda fn: fn
2660 f = lambda fn: fn
2637 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2661 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2638 f = lambda fn: util.normpath(fn)
2662 f = lambda fn: util.normpath(fn)
2639 fmt = 'f %%-%ds %%-%ds %%s' % (
2663 fmt = 'f %%-%ds %%-%ds %%s' % (
2640 max([len(abs) for abs in items]),
2664 max([len(abs) for abs in items]),
2641 max([len(m.rel(abs)) for abs in items]))
2665 max([len(m.rel(abs)) for abs in items]))
2642 for abs in items:
2666 for abs in items:
2643 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2667 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2644 ui.write("%s\n" % line.rstrip())
2668 ui.write("%s\n" % line.rstrip())
2645
2669
2646 @command('debugwhyunstable', [], _('REV'))
2670 @command('debugwhyunstable', [], _('REV'))
2647 def debugwhyunstable(ui, repo, rev):
2671 def debugwhyunstable(ui, repo, rev):
2648 """explain instabilities of a changeset"""
2672 """explain instabilities of a changeset"""
2649 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2673 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2650 dnodes = ''
2674 dnodes = ''
2651 if entry.get('divergentnodes'):
2675 if entry.get('divergentnodes'):
2652 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2676 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2653 for ctx in entry['divergentnodes']) + ' '
2677 for ctx in entry['divergentnodes']) + ' '
2654 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2678 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2655 entry['reason'], entry['node']))
2679 entry['reason'], entry['node']))
2656
2680
2657 @command('debugwireargs',
2681 @command('debugwireargs',
2658 [('', 'three', '', 'three'),
2682 [('', 'three', '', 'three'),
2659 ('', 'four', '', 'four'),
2683 ('', 'four', '', 'four'),
2660 ('', 'five', '', 'five'),
2684 ('', 'five', '', 'five'),
2661 ] + cmdutil.remoteopts,
2685 ] + cmdutil.remoteopts,
2662 _('REPO [OPTIONS]... [ONE [TWO]]'),
2686 _('REPO [OPTIONS]... [ONE [TWO]]'),
2663 norepo=True)
2687 norepo=True)
2664 def debugwireargs(ui, repopath, *vals, **opts):
2688 def debugwireargs(ui, repopath, *vals, **opts):
2665 opts = pycompat.byteskwargs(opts)
2689 opts = pycompat.byteskwargs(opts)
2666 repo = hg.peer(ui, opts, repopath)
2690 repo = hg.peer(ui, opts, repopath)
2667 for opt in cmdutil.remoteopts:
2691 for opt in cmdutil.remoteopts:
2668 del opts[opt[1]]
2692 del opts[opt[1]]
2669 args = {}
2693 args = {}
2670 for k, v in opts.iteritems():
2694 for k, v in opts.iteritems():
2671 if v:
2695 if v:
2672 args[k] = v
2696 args[k] = v
2673 args = pycompat.strkwargs(args)
2697 args = pycompat.strkwargs(args)
2674 # run twice to check that we don't mess up the stream for the next command
2698 # run twice to check that we don't mess up the stream for the next command
2675 res1 = repo.debugwireargs(*vals, **args)
2699 res1 = repo.debugwireargs(*vals, **args)
2676 res2 = repo.debugwireargs(*vals, **args)
2700 res2 = repo.debugwireargs(*vals, **args)
2677 ui.write("%s\n" % res1)
2701 ui.write("%s\n" % res1)
2678 if res1 != res2:
2702 if res1 != res2:
2679 ui.warn("%s\n" % res2)
2703 ui.warn("%s\n" % res2)
2680
2704
2681 def _parsewirelangblocks(fh):
2705 def _parsewirelangblocks(fh):
2682 activeaction = None
2706 activeaction = None
2683 blocklines = []
2707 blocklines = []
2684
2708
2685 for line in fh:
2709 for line in fh:
2686 line = line.rstrip()
2710 line = line.rstrip()
2687 if not line:
2711 if not line:
2688 continue
2712 continue
2689
2713
2690 if line.startswith(b'#'):
2714 if line.startswith(b'#'):
2691 continue
2715 continue
2692
2716
2693 if not line.startswith(' '):
2717 if not line.startswith(' '):
2694 # New block. Flush previous one.
2718 # New block. Flush previous one.
2695 if activeaction:
2719 if activeaction:
2696 yield activeaction, blocklines
2720 yield activeaction, blocklines
2697
2721
2698 activeaction = line
2722 activeaction = line
2699 blocklines = []
2723 blocklines = []
2700 continue
2724 continue
2701
2725
2702 # Else we start with an indent.
2726 # Else we start with an indent.
2703
2727
2704 if not activeaction:
2728 if not activeaction:
2705 raise error.Abort(_('indented line outside of block'))
2729 raise error.Abort(_('indented line outside of block'))
2706
2730
2707 blocklines.append(line)
2731 blocklines.append(line)
2708
2732
2709 # Flush last block.
2733 # Flush last block.
2710 if activeaction:
2734 if activeaction:
2711 yield activeaction, blocklines
2735 yield activeaction, blocklines
2712
2736
2713 @command('debugwireproto',
2737 @command('debugwireproto',
2714 [
2738 [
2715 ('', 'localssh', False, _('start an SSH server for this repo')),
2739 ('', 'localssh', False, _('start an SSH server for this repo')),
2716 ('', 'peer', '', _('construct a specific version of the peer')),
2740 ('', 'peer', '', _('construct a specific version of the peer')),
2717 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2741 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2718 ('', 'nologhandshake', False,
2742 ('', 'nologhandshake', False,
2719 _('do not log I/O related to the peer handshake')),
2743 _('do not log I/O related to the peer handshake')),
2720 ] + cmdutil.remoteopts,
2744 ] + cmdutil.remoteopts,
2721 _('[PATH]'),
2745 _('[PATH]'),
2722 optionalrepo=True)
2746 optionalrepo=True)
2723 def debugwireproto(ui, repo, path=None, **opts):
2747 def debugwireproto(ui, repo, path=None, **opts):
2724 """send wire protocol commands to a server
2748 """send wire protocol commands to a server
2725
2749
2726 This command can be used to issue wire protocol commands to remote
2750 This command can be used to issue wire protocol commands to remote
2727 peers and to debug the raw data being exchanged.
2751 peers and to debug the raw data being exchanged.
2728
2752
2729 ``--localssh`` will start an SSH server against the current repository
2753 ``--localssh`` will start an SSH server against the current repository
2730 and connect to that. By default, the connection will perform a handshake
2754 and connect to that. By default, the connection will perform a handshake
2731 and establish an appropriate peer instance.
2755 and establish an appropriate peer instance.
2732
2756
2733 ``--peer`` can be used to bypass the handshake protocol and construct a
2757 ``--peer`` can be used to bypass the handshake protocol and construct a
2734 peer instance using the specified class type. Valid values are ``raw``,
2758 peer instance using the specified class type. Valid values are ``raw``,
2735 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2759 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2736 raw data payloads and don't support higher-level command actions.
2760 raw data payloads and don't support higher-level command actions.
2737
2761
2738 ``--noreadstderr`` can be used to disable automatic reading from stderr
2762 ``--noreadstderr`` can be used to disable automatic reading from stderr
2739 of the peer (for SSH connections only). Disabling automatic reading of
2763 of the peer (for SSH connections only). Disabling automatic reading of
2740 stderr is useful for making output more deterministic.
2764 stderr is useful for making output more deterministic.
2741
2765
2742 Commands are issued via a mini language which is specified via stdin.
2766 Commands are issued via a mini language which is specified via stdin.
2743 The language consists of individual actions to perform. An action is
2767 The language consists of individual actions to perform. An action is
2744 defined by a block. A block is defined as a line with no leading
2768 defined by a block. A block is defined as a line with no leading
2745 space followed by 0 or more lines with leading space. Blocks are
2769 space followed by 0 or more lines with leading space. Blocks are
2746 effectively a high-level command with additional metadata.
2770 effectively a high-level command with additional metadata.
2747
2771
2748 Lines beginning with ``#`` are ignored.
2772 Lines beginning with ``#`` are ignored.
2749
2773
2750 The following sections denote available actions.
2774 The following sections denote available actions.
2751
2775
2752 raw
2776 raw
2753 ---
2777 ---
2754
2778
2755 Send raw data to the server.
2779 Send raw data to the server.
2756
2780
2757 The block payload contains the raw data to send as one atomic send
2781 The block payload contains the raw data to send as one atomic send
2758 operation. The data may not actually be delivered in a single system
2782 operation. The data may not actually be delivered in a single system
2759 call: it depends on the abilities of the transport being used.
2783 call: it depends on the abilities of the transport being used.
2760
2784
2761 Each line in the block is de-indented and concatenated. Then, that
2785 Each line in the block is de-indented and concatenated. Then, that
2762 value is evaluated as a Python b'' literal. This allows the use of
2786 value is evaluated as a Python b'' literal. This allows the use of
2763 backslash escaping, etc.
2787 backslash escaping, etc.
2764
2788
2765 raw+
2789 raw+
2766 ----
2790 ----
2767
2791
2768 Behaves like ``raw`` except flushes output afterwards.
2792 Behaves like ``raw`` except flushes output afterwards.
2769
2793
2770 command <X>
2794 command <X>
2771 -----------
2795 -----------
2772
2796
2773 Send a request to run a named command, whose name follows the ``command``
2797 Send a request to run a named command, whose name follows the ``command``
2774 string.
2798 string.
2775
2799
2776 Arguments to the command are defined as lines in this block. The format of
2800 Arguments to the command are defined as lines in this block. The format of
2777 each line is ``<key> <value>``. e.g.::
2801 each line is ``<key> <value>``. e.g.::
2778
2802
2779 command listkeys
2803 command listkeys
2780 namespace bookmarks
2804 namespace bookmarks
2781
2805
2782 If the value begins with ``eval:``, it will be interpreted as a Python
2806 If the value begins with ``eval:``, it will be interpreted as a Python
2783 literal expression. Otherwise values are interpreted as Python b'' literals.
2807 literal expression. Otherwise values are interpreted as Python b'' literals.
2784 This allows sending complex types and encoding special byte sequences via
2808 This allows sending complex types and encoding special byte sequences via
2785 backslash escaping.
2809 backslash escaping.
2786
2810
2787 The following arguments have special meaning:
2811 The following arguments have special meaning:
2788
2812
2789 ``PUSHFILE``
2813 ``PUSHFILE``
2790 When defined, the *push* mechanism of the peer will be used instead
2814 When defined, the *push* mechanism of the peer will be used instead
2791 of the static request-response mechanism and the content of the
2815 of the static request-response mechanism and the content of the
2792 file specified in the value of this argument will be sent as the
2816 file specified in the value of this argument will be sent as the
2793 command payload.
2817 command payload.
2794
2818
2795 This can be used to submit a local bundle file to the remote.
2819 This can be used to submit a local bundle file to the remote.
2796
2820
2797 batchbegin
2821 batchbegin
2798 ----------
2822 ----------
2799
2823
2800 Instruct the peer to begin a batched send.
2824 Instruct the peer to begin a batched send.
2801
2825
2802 All ``command`` blocks are queued for execution until the next
2826 All ``command`` blocks are queued for execution until the next
2803 ``batchsubmit`` block.
2827 ``batchsubmit`` block.
2804
2828
2805 batchsubmit
2829 batchsubmit
2806 -----------
2830 -----------
2807
2831
2808 Submit previously queued ``command`` blocks as a batch request.
2832 Submit previously queued ``command`` blocks as a batch request.
2809
2833
2810 This action MUST be paired with a ``batchbegin`` action.
2834 This action MUST be paired with a ``batchbegin`` action.
2811
2835
2812 httprequest <method> <path>
2836 httprequest <method> <path>
2813 ---------------------------
2837 ---------------------------
2814
2838
2815 (HTTP peer only)
2839 (HTTP peer only)
2816
2840
2817 Send an HTTP request to the peer.
2841 Send an HTTP request to the peer.
2818
2842
2819 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2843 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2820
2844
2821 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2845 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2822 headers to add to the request. e.g. ``Accept: foo``.
2846 headers to add to the request. e.g. ``Accept: foo``.
2823
2847
2824 The following arguments are special:
2848 The following arguments are special:
2825
2849
2826 ``BODYFILE``
2850 ``BODYFILE``
2827 The content of the file defined as the value to this argument will be
2851 The content of the file defined as the value to this argument will be
2828 transferred verbatim as the HTTP request body.
2852 transferred verbatim as the HTTP request body.
2829
2853
2830 ``frame <type> <flags> <payload>``
2854 ``frame <type> <flags> <payload>``
2831 Send a unified protocol frame as part of the request body.
2855 Send a unified protocol frame as part of the request body.
2832
2856
2833 All frames will be collected and sent as the body to the HTTP
2857 All frames will be collected and sent as the body to the HTTP
2834 request.
2858 request.
2835
2859
2836 close
2860 close
2837 -----
2861 -----
2838
2862
2839 Close the connection to the server.
2863 Close the connection to the server.
2840
2864
2841 flush
2865 flush
2842 -----
2866 -----
2843
2867
2844 Flush data written to the server.
2868 Flush data written to the server.
2845
2869
2846 readavailable
2870 readavailable
2847 -------------
2871 -------------
2848
2872
2849 Close the write end of the connection and read all available data from
2873 Close the write end of the connection and read all available data from
2850 the server.
2874 the server.
2851
2875
2852 If the connection to the server encompasses multiple pipes, we poll both
2876 If the connection to the server encompasses multiple pipes, we poll both
2853 pipes and read available data.
2877 pipes and read available data.
2854
2878
2855 readline
2879 readline
2856 --------
2880 --------
2857
2881
2858 Read a line of output from the server. If there are multiple output
2882 Read a line of output from the server. If there are multiple output
2859 pipes, reads only the main pipe.
2883 pipes, reads only the main pipe.
2860
2884
2861 ereadline
2885 ereadline
2862 ---------
2886 ---------
2863
2887
2864 Like ``readline``, but read from the stderr pipe, if available.
2888 Like ``readline``, but read from the stderr pipe, if available.
2865
2889
2866 read <X>
2890 read <X>
2867 --------
2891 --------
2868
2892
2869 ``read()`` N bytes from the server's main output pipe.
2893 ``read()`` N bytes from the server's main output pipe.
2870
2894
2871 eread <X>
2895 eread <X>
2872 ---------
2896 ---------
2873
2897
2874 ``read()`` N bytes from the server's stderr pipe, if available.
2898 ``read()`` N bytes from the server's stderr pipe, if available.
2875
2899
2876 Specifying Unified Frame-Based Protocol Frames
2900 Specifying Unified Frame-Based Protocol Frames
2877 ----------------------------------------------
2901 ----------------------------------------------
2878
2902
2879 It is possible to emit a *Unified Frame-Based Protocol* by using special
2903 It is possible to emit a *Unified Frame-Based Protocol* by using special
2880 syntax.
2904 syntax.
2881
2905
2882 A frame is composed as a type, flags, and payload. These can be parsed
2906 A frame is composed as a type, flags, and payload. These can be parsed
2883 from a string of the form:
2907 from a string of the form:
2884
2908
2885 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2909 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2886
2910
2887 ``request-id`` and ``stream-id`` are integers defining the request and
2911 ``request-id`` and ``stream-id`` are integers defining the request and
2888 stream identifiers.
2912 stream identifiers.
2889
2913
2890 ``type`` can be an integer value for the frame type or the string name
2914 ``type`` can be an integer value for the frame type or the string name
2891 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2915 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2892 ``command-name``.
2916 ``command-name``.
2893
2917
2894 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2918 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2895 components. Each component (and there can be just one) can be an integer
2919 components. Each component (and there can be just one) can be an integer
2896 or a flag name for stream flags or frame flags, respectively. Values are
2920 or a flag name for stream flags or frame flags, respectively. Values are
2897 resolved to integers and then bitwise OR'd together.
2921 resolved to integers and then bitwise OR'd together.
2898
2922
2899 ``payload`` represents the raw frame payload. If it begins with
2923 ``payload`` represents the raw frame payload. If it begins with
2900 ``cbor:``, the following string is evaluated as Python code and the
2924 ``cbor:``, the following string is evaluated as Python code and the
2901 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2925 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2902 as a Python byte string literal.
2926 as a Python byte string literal.
2903 """
2927 """
2904 opts = pycompat.byteskwargs(opts)
2928 opts = pycompat.byteskwargs(opts)
2905
2929
2906 if opts['localssh'] and not repo:
2930 if opts['localssh'] and not repo:
2907 raise error.Abort(_('--localssh requires a repository'))
2931 raise error.Abort(_('--localssh requires a repository'))
2908
2932
2909 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2933 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2910 raise error.Abort(_('invalid value for --peer'),
2934 raise error.Abort(_('invalid value for --peer'),
2911 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2935 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2912
2936
2913 if path and opts['localssh']:
2937 if path and opts['localssh']:
2914 raise error.Abort(_('cannot specify --localssh with an explicit '
2938 raise error.Abort(_('cannot specify --localssh with an explicit '
2915 'path'))
2939 'path'))
2916
2940
2917 if ui.interactive():
2941 if ui.interactive():
2918 ui.write(_('(waiting for commands on stdin)\n'))
2942 ui.write(_('(waiting for commands on stdin)\n'))
2919
2943
2920 blocks = list(_parsewirelangblocks(ui.fin))
2944 blocks = list(_parsewirelangblocks(ui.fin))
2921
2945
2922 proc = None
2946 proc = None
2923 stdin = None
2947 stdin = None
2924 stdout = None
2948 stdout = None
2925 stderr = None
2949 stderr = None
2926 opener = None
2950 opener = None
2927
2951
2928 if opts['localssh']:
2952 if opts['localssh']:
2929 # We start the SSH server in its own process so there is process
2953 # We start the SSH server in its own process so there is process
2930 # separation. This prevents a whole class of potential bugs around
2954 # separation. This prevents a whole class of potential bugs around
2931 # shared state from interfering with server operation.
2955 # shared state from interfering with server operation.
2932 args = procutil.hgcmd() + [
2956 args = procutil.hgcmd() + [
2933 '-R', repo.root,
2957 '-R', repo.root,
2934 'debugserve', '--sshstdio',
2958 'debugserve', '--sshstdio',
2935 ]
2959 ]
2936 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2960 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2937 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2961 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2938 bufsize=0)
2962 bufsize=0)
2939
2963
2940 stdin = proc.stdin
2964 stdin = proc.stdin
2941 stdout = proc.stdout
2965 stdout = proc.stdout
2942 stderr = proc.stderr
2966 stderr = proc.stderr
2943
2967
2944 # We turn the pipes into observers so we can log I/O.
2968 # We turn the pipes into observers so we can log I/O.
2945 if ui.verbose or opts['peer'] == 'raw':
2969 if ui.verbose or opts['peer'] == 'raw':
2946 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2970 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2947 logdata=True)
2971 logdata=True)
2948 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2972 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2949 logdata=True)
2973 logdata=True)
2950 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2974 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2951 logdata=True)
2975 logdata=True)
2952
2976
2953 # --localssh also implies the peer connection settings.
2977 # --localssh also implies the peer connection settings.
2954
2978
2955 url = 'ssh://localserver'
2979 url = 'ssh://localserver'
2956 autoreadstderr = not opts['noreadstderr']
2980 autoreadstderr = not opts['noreadstderr']
2957
2981
2958 if opts['peer'] == 'ssh1':
2982 if opts['peer'] == 'ssh1':
2959 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2983 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2960 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2984 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2961 None, autoreadstderr=autoreadstderr)
2985 None, autoreadstderr=autoreadstderr)
2962 elif opts['peer'] == 'ssh2':
2986 elif opts['peer'] == 'ssh2':
2963 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2987 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2964 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2988 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2965 None, autoreadstderr=autoreadstderr)
2989 None, autoreadstderr=autoreadstderr)
2966 elif opts['peer'] == 'raw':
2990 elif opts['peer'] == 'raw':
2967 ui.write(_('using raw connection to peer\n'))
2991 ui.write(_('using raw connection to peer\n'))
2968 peer = None
2992 peer = None
2969 else:
2993 else:
2970 ui.write(_('creating ssh peer from handshake results\n'))
2994 ui.write(_('creating ssh peer from handshake results\n'))
2971 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2995 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2972 autoreadstderr=autoreadstderr)
2996 autoreadstderr=autoreadstderr)
2973
2997
2974 elif path:
2998 elif path:
2975 # We bypass hg.peer() so we can proxy the sockets.
2999 # We bypass hg.peer() so we can proxy the sockets.
2976 # TODO consider not doing this because we skip
3000 # TODO consider not doing this because we skip
2977 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
3001 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2978 u = util.url(path)
3002 u = util.url(path)
2979 if u.scheme != 'http':
3003 if u.scheme != 'http':
2980 raise error.Abort(_('only http:// paths are currently supported'))
3004 raise error.Abort(_('only http:// paths are currently supported'))
2981
3005
2982 url, authinfo = u.authinfo()
3006 url, authinfo = u.authinfo()
2983 openerargs = {
3007 openerargs = {
2984 r'useragent': b'Mercurial debugwireproto',
3008 r'useragent': b'Mercurial debugwireproto',
2985 }
3009 }
2986
3010
2987 # Turn pipes/sockets into observers so we can log I/O.
3011 # Turn pipes/sockets into observers so we can log I/O.
2988 if ui.verbose:
3012 if ui.verbose:
2989 openerargs.update({
3013 openerargs.update({
2990 r'loggingfh': ui,
3014 r'loggingfh': ui,
2991 r'loggingname': b's',
3015 r'loggingname': b's',
2992 r'loggingopts': {
3016 r'loggingopts': {
2993 r'logdata': True,
3017 r'logdata': True,
2994 r'logdataapis': False,
3018 r'logdataapis': False,
2995 },
3019 },
2996 })
3020 })
2997
3021
2998 if ui.debugflag:
3022 if ui.debugflag:
2999 openerargs[r'loggingopts'][r'logdataapis'] = True
3023 openerargs[r'loggingopts'][r'logdataapis'] = True
3000
3024
3001 # Don't send default headers when in raw mode. This allows us to
3025 # Don't send default headers when in raw mode. This allows us to
3002 # bypass most of the behavior of our URL handling code so we can
3026 # bypass most of the behavior of our URL handling code so we can
3003 # have near complete control over what's sent on the wire.
3027 # have near complete control over what's sent on the wire.
3004 if opts['peer'] == 'raw':
3028 if opts['peer'] == 'raw':
3005 openerargs[r'sendaccept'] = False
3029 openerargs[r'sendaccept'] = False
3006
3030
3007 opener = urlmod.opener(ui, authinfo, **openerargs)
3031 opener = urlmod.opener(ui, authinfo, **openerargs)
3008
3032
3009 if opts['peer'] == 'http2':
3033 if opts['peer'] == 'http2':
3010 ui.write(_('creating http peer for wire protocol version 2\n'))
3034 ui.write(_('creating http peer for wire protocol version 2\n'))
3011 # We go through makepeer() because we need an API descriptor for
3035 # We go through makepeer() because we need an API descriptor for
3012 # the peer instance to be useful.
3036 # the peer instance to be useful.
3013 with ui.configoverride({
3037 with ui.configoverride({
3014 ('experimental', 'httppeer.advertise-v2'): True}):
3038 ('experimental', 'httppeer.advertise-v2'): True}):
3015 if opts['nologhandshake']:
3039 if opts['nologhandshake']:
3016 ui.pushbuffer()
3040 ui.pushbuffer()
3017
3041
3018 peer = httppeer.makepeer(ui, path, opener=opener)
3042 peer = httppeer.makepeer(ui, path, opener=opener)
3019
3043
3020 if opts['nologhandshake']:
3044 if opts['nologhandshake']:
3021 ui.popbuffer()
3045 ui.popbuffer()
3022
3046
3023 if not isinstance(peer, httppeer.httpv2peer):
3047 if not isinstance(peer, httppeer.httpv2peer):
3024 raise error.Abort(_('could not instantiate HTTP peer for '
3048 raise error.Abort(_('could not instantiate HTTP peer for '
3025 'wire protocol version 2'),
3049 'wire protocol version 2'),
3026 hint=_('the server may not have the feature '
3050 hint=_('the server may not have the feature '
3027 'enabled or is not allowing this '
3051 'enabled or is not allowing this '
3028 'client version'))
3052 'client version'))
3029
3053
3030 elif opts['peer'] == 'raw':
3054 elif opts['peer'] == 'raw':
3031 ui.write(_('using raw connection to peer\n'))
3055 ui.write(_('using raw connection to peer\n'))
3032 peer = None
3056 peer = None
3033 elif opts['peer']:
3057 elif opts['peer']:
3034 raise error.Abort(_('--peer %s not supported with HTTP peers') %
3058 raise error.Abort(_('--peer %s not supported with HTTP peers') %
3035 opts['peer'])
3059 opts['peer'])
3036 else:
3060 else:
3037 peer = httppeer.makepeer(ui, path, opener=opener)
3061 peer = httppeer.makepeer(ui, path, opener=opener)
3038
3062
3039 # We /could/ populate stdin/stdout with sock.makefile()...
3063 # We /could/ populate stdin/stdout with sock.makefile()...
3040 else:
3064 else:
3041 raise error.Abort(_('unsupported connection configuration'))
3065 raise error.Abort(_('unsupported connection configuration'))
3042
3066
3043 batchedcommands = None
3067 batchedcommands = None
3044
3068
3045 # Now perform actions based on the parsed wire language instructions.
3069 # Now perform actions based on the parsed wire language instructions.
3046 for action, lines in blocks:
3070 for action, lines in blocks:
3047 if action in ('raw', 'raw+'):
3071 if action in ('raw', 'raw+'):
3048 if not stdin:
3072 if not stdin:
3049 raise error.Abort(_('cannot call raw/raw+ on this peer'))
3073 raise error.Abort(_('cannot call raw/raw+ on this peer'))
3050
3074
3051 # Concatenate the data together.
3075 # Concatenate the data together.
3052 data = ''.join(l.lstrip() for l in lines)
3076 data = ''.join(l.lstrip() for l in lines)
3053 data = stringutil.unescapestr(data)
3077 data = stringutil.unescapestr(data)
3054 stdin.write(data)
3078 stdin.write(data)
3055
3079
3056 if action == 'raw+':
3080 if action == 'raw+':
3057 stdin.flush()
3081 stdin.flush()
3058 elif action == 'flush':
3082 elif action == 'flush':
3059 if not stdin:
3083 if not stdin:
3060 raise error.Abort(_('cannot call flush on this peer'))
3084 raise error.Abort(_('cannot call flush on this peer'))
3061 stdin.flush()
3085 stdin.flush()
3062 elif action.startswith('command'):
3086 elif action.startswith('command'):
3063 if not peer:
3087 if not peer:
3064 raise error.Abort(_('cannot send commands unless peer instance '
3088 raise error.Abort(_('cannot send commands unless peer instance '
3065 'is available'))
3089 'is available'))
3066
3090
3067 command = action.split(' ', 1)[1]
3091 command = action.split(' ', 1)[1]
3068
3092
3069 args = {}
3093 args = {}
3070 for line in lines:
3094 for line in lines:
3071 # We need to allow empty values.
3095 # We need to allow empty values.
3072 fields = line.lstrip().split(' ', 1)
3096 fields = line.lstrip().split(' ', 1)
3073 if len(fields) == 1:
3097 if len(fields) == 1:
3074 key = fields[0]
3098 key = fields[0]
3075 value = ''
3099 value = ''
3076 else:
3100 else:
3077 key, value = fields
3101 key, value = fields
3078
3102
3079 if value.startswith('eval:'):
3103 if value.startswith('eval:'):
3080 value = stringutil.evalpythonliteral(value[5:])
3104 value = stringutil.evalpythonliteral(value[5:])
3081 else:
3105 else:
3082 value = stringutil.unescapestr(value)
3106 value = stringutil.unescapestr(value)
3083
3107
3084 args[key] = value
3108 args[key] = value
3085
3109
3086 if batchedcommands is not None:
3110 if batchedcommands is not None:
3087 batchedcommands.append((command, args))
3111 batchedcommands.append((command, args))
3088 continue
3112 continue
3089
3113
3090 ui.status(_('sending %s command\n') % command)
3114 ui.status(_('sending %s command\n') % command)
3091
3115
3092 if 'PUSHFILE' in args:
3116 if 'PUSHFILE' in args:
3093 with open(args['PUSHFILE'], r'rb') as fh:
3117 with open(args['PUSHFILE'], r'rb') as fh:
3094 del args['PUSHFILE']
3118 del args['PUSHFILE']
3095 res, output = peer._callpush(command, fh,
3119 res, output = peer._callpush(command, fh,
3096 **pycompat.strkwargs(args))
3120 **pycompat.strkwargs(args))
3097 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3121 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3098 ui.status(_('remote output: %s\n') %
3122 ui.status(_('remote output: %s\n') %
3099 stringutil.escapestr(output))
3123 stringutil.escapestr(output))
3100 else:
3124 else:
3101 with peer.commandexecutor() as e:
3125 with peer.commandexecutor() as e:
3102 res = e.callcommand(command, args).result()
3126 res = e.callcommand(command, args).result()
3103
3127
3104 if isinstance(res, wireprotov2peer.commandresponse):
3128 if isinstance(res, wireprotov2peer.commandresponse):
3105 val = list(res.cborobjects())
3129 val = list(res.cborobjects())
3106 ui.status(_('response: %s\n') %
3130 ui.status(_('response: %s\n') %
3107 stringutil.pprint(val, bprefix=True))
3131 stringutil.pprint(val, bprefix=True))
3108
3132
3109 else:
3133 else:
3110 ui.status(_('response: %s\n') %
3134 ui.status(_('response: %s\n') %
3111 stringutil.pprint(res, bprefix=True))
3135 stringutil.pprint(res, bprefix=True))
3112
3136
3113 elif action == 'batchbegin':
3137 elif action == 'batchbegin':
3114 if batchedcommands is not None:
3138 if batchedcommands is not None:
3115 raise error.Abort(_('nested batchbegin not allowed'))
3139 raise error.Abort(_('nested batchbegin not allowed'))
3116
3140
3117 batchedcommands = []
3141 batchedcommands = []
3118 elif action == 'batchsubmit':
3142 elif action == 'batchsubmit':
3119 # There is a batching API we could go through. But it would be
3143 # There is a batching API we could go through. But it would be
3120 # difficult to normalize requests into function calls. It is easier
3144 # difficult to normalize requests into function calls. It is easier
3121 # to bypass this layer and normalize to commands + args.
3145 # to bypass this layer and normalize to commands + args.
3122 ui.status(_('sending batch with %d sub-commands\n') %
3146 ui.status(_('sending batch with %d sub-commands\n') %
3123 len(batchedcommands))
3147 len(batchedcommands))
3124 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3148 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3125 ui.status(_('response #%d: %s\n') %
3149 ui.status(_('response #%d: %s\n') %
3126 (i, stringutil.escapestr(chunk)))
3150 (i, stringutil.escapestr(chunk)))
3127
3151
3128 batchedcommands = None
3152 batchedcommands = None
3129
3153
3130 elif action.startswith('httprequest '):
3154 elif action.startswith('httprequest '):
3131 if not opener:
3155 if not opener:
3132 raise error.Abort(_('cannot use httprequest without an HTTP '
3156 raise error.Abort(_('cannot use httprequest without an HTTP '
3133 'peer'))
3157 'peer'))
3134
3158
3135 request = action.split(' ', 2)
3159 request = action.split(' ', 2)
3136 if len(request) != 3:
3160 if len(request) != 3:
3137 raise error.Abort(_('invalid httprequest: expected format is '
3161 raise error.Abort(_('invalid httprequest: expected format is '
3138 '"httprequest <method> <path>'))
3162 '"httprequest <method> <path>'))
3139
3163
3140 method, httppath = request[1:]
3164 method, httppath = request[1:]
3141 headers = {}
3165 headers = {}
3142 body = None
3166 body = None
3143 frames = []
3167 frames = []
3144 for line in lines:
3168 for line in lines:
3145 line = line.lstrip()
3169 line = line.lstrip()
3146 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3170 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3147 if m:
3171 if m:
3148 headers[m.group(1)] = m.group(2)
3172 headers[m.group(1)] = m.group(2)
3149 continue
3173 continue
3150
3174
3151 if line.startswith(b'BODYFILE '):
3175 if line.startswith(b'BODYFILE '):
3152 with open(line.split(b' ', 1), 'rb') as fh:
3176 with open(line.split(b' ', 1), 'rb') as fh:
3153 body = fh.read()
3177 body = fh.read()
3154 elif line.startswith(b'frame '):
3178 elif line.startswith(b'frame '):
3155 frame = wireprotoframing.makeframefromhumanstring(
3179 frame = wireprotoframing.makeframefromhumanstring(
3156 line[len(b'frame '):])
3180 line[len(b'frame '):])
3157
3181
3158 frames.append(frame)
3182 frames.append(frame)
3159 else:
3183 else:
3160 raise error.Abort(_('unknown argument to httprequest: %s') %
3184 raise error.Abort(_('unknown argument to httprequest: %s') %
3161 line)
3185 line)
3162
3186
3163 url = path + httppath
3187 url = path + httppath
3164
3188
3165 if frames:
3189 if frames:
3166 body = b''.join(bytes(f) for f in frames)
3190 body = b''.join(bytes(f) for f in frames)
3167
3191
3168 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3192 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3169
3193
3170 # urllib.Request insists on using has_data() as a proxy for
3194 # urllib.Request insists on using has_data() as a proxy for
3171 # determining the request method. Override that to use our
3195 # determining the request method. Override that to use our
3172 # explicitly requested method.
3196 # explicitly requested method.
3173 req.get_method = lambda: method
3197 req.get_method = lambda: method
3174
3198
3175 try:
3199 try:
3176 res = opener.open(req)
3200 res = opener.open(req)
3177 body = res.read()
3201 body = res.read()
3178 except util.urlerr.urlerror as e:
3202 except util.urlerr.urlerror as e:
3179 e.read()
3203 e.read()
3180 continue
3204 continue
3181
3205
3182 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3206 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3183 ui.write(_('cbor> %s\n') %
3207 ui.write(_('cbor> %s\n') %
3184 stringutil.pprint(cbor.loads(body), bprefix=True))
3208 stringutil.pprint(cbor.loads(body), bprefix=True))
3185
3209
3186 elif action == 'close':
3210 elif action == 'close':
3187 peer.close()
3211 peer.close()
3188 elif action == 'readavailable':
3212 elif action == 'readavailable':
3189 if not stdout or not stderr:
3213 if not stdout or not stderr:
3190 raise error.Abort(_('readavailable not available on this peer'))
3214 raise error.Abort(_('readavailable not available on this peer'))
3191
3215
3192 stdin.close()
3216 stdin.close()
3193 stdout.read()
3217 stdout.read()
3194 stderr.read()
3218 stderr.read()
3195
3219
3196 elif action == 'readline':
3220 elif action == 'readline':
3197 if not stdout:
3221 if not stdout:
3198 raise error.Abort(_('readline not available on this peer'))
3222 raise error.Abort(_('readline not available on this peer'))
3199 stdout.readline()
3223 stdout.readline()
3200 elif action == 'ereadline':
3224 elif action == 'ereadline':
3201 if not stderr:
3225 if not stderr:
3202 raise error.Abort(_('ereadline not available on this peer'))
3226 raise error.Abort(_('ereadline not available on this peer'))
3203 stderr.readline()
3227 stderr.readline()
3204 elif action.startswith('read '):
3228 elif action.startswith('read '):
3205 count = int(action.split(' ', 1)[1])
3229 count = int(action.split(' ', 1)[1])
3206 if not stdout:
3230 if not stdout:
3207 raise error.Abort(_('read not available on this peer'))
3231 raise error.Abort(_('read not available on this peer'))
3208 stdout.read(count)
3232 stdout.read(count)
3209 elif action.startswith('eread '):
3233 elif action.startswith('eread '):
3210 count = int(action.split(' ', 1)[1])
3234 count = int(action.split(' ', 1)[1])
3211 if not stderr:
3235 if not stderr:
3212 raise error.Abort(_('eread not available on this peer'))
3236 raise error.Abort(_('eread not available on this peer'))
3213 stderr.read(count)
3237 stderr.read(count)
3214 else:
3238 else:
3215 raise error.Abort(_('unknown action: %s') % action)
3239 raise error.Abort(_('unknown action: %s') % action)
3216
3240
3217 if batchedcommands is not None:
3241 if batchedcommands is not None:
3218 raise error.Abort(_('unclosed "batchbegin" request'))
3242 raise error.Abort(_('unclosed "batchbegin" request'))
3219
3243
3220 if peer:
3244 if peer:
3221 peer.close()
3245 peer.close()
3222
3246
3223 if proc:
3247 if proc:
3224 proc.kill()
3248 proc.kill()
@@ -1,404 +1,404 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugapplystreamclonebundle
72 debugapplystreamclonebundle
73 debugbuilddag
73 debugbuilddag
74 debugbundle
74 debugbundle
75 debugcapabilities
75 debugcapabilities
76 debugcheckstate
76 debugcheckstate
77 debugcolor
77 debugcolor
78 debugcommands
78 debugcommands
79 debugcomplete
79 debugcomplete
80 debugconfig
80 debugconfig
81 debugcreatestreamclonebundle
81 debugcreatestreamclonebundle
82 debugdag
82 debugdag
83 debugdata
83 debugdata
84 debugdate
84 debugdate
85 debugdeltachain
85 debugdeltachain
86 debugdirstate
86 debugdirstate
87 debugdiscovery
87 debugdiscovery
88 debugdownload
88 debugdownload
89 debugextensions
89 debugextensions
90 debugfileset
90 debugfileset
91 debugformat
91 debugformat
92 debugfsinfo
92 debugfsinfo
93 debuggetbundle
93 debuggetbundle
94 debugignore
94 debugignore
95 debugindex
95 debugindex
96 debugindexdot
96 debugindexdot
97 debuginstall
97 debuginstall
98 debugknown
98 debugknown
99 debuglabelcomplete
99 debuglabelcomplete
100 debuglocks
100 debuglocks
101 debugmanifestfulltextcache
101 debugmanifestfulltextcache
102 debugmergestate
102 debugmergestate
103 debugnamecomplete
103 debugnamecomplete
104 debugobsolete
104 debugobsolete
105 debugpathcomplete
105 debugpathcomplete
106 debugpeer
106 debugpeer
107 debugpickmergetool
107 debugpickmergetool
108 debugpushkey
108 debugpushkey
109 debugpvec
109 debugpvec
110 debugrebuilddirstate
110 debugrebuilddirstate
111 debugrebuildfncache
111 debugrebuildfncache
112 debugrename
112 debugrename
113 debugrevlog
113 debugrevlog
114 debugrevspec
114 debugrevspec
115 debugserve
115 debugserve
116 debugsetparents
116 debugsetparents
117 debugssl
117 debugssl
118 debugsub
118 debugsub
119 debugsuccessorssets
119 debugsuccessorssets
120 debugtemplate
120 debugtemplate
121 debuguigetpass
121 debuguigetpass
122 debuguiprompt
122 debuguiprompt
123 debugupdatecaches
123 debugupdatecaches
124 debugupgraderepo
124 debugupgraderepo
125 debugwalk
125 debugwalk
126 debugwhyunstable
126 debugwhyunstable
127 debugwireargs
127 debugwireargs
128 debugwireproto
128 debugwireproto
129
129
130 Do not show the alias of a debug command if there are other candidates
130 Do not show the alias of a debug command if there are other candidates
131 (this should hide rawcommit)
131 (this should hide rawcommit)
132 $ hg debugcomplete r
132 $ hg debugcomplete r
133 recover
133 recover
134 remove
134 remove
135 rename
135 rename
136 resolve
136 resolve
137 revert
137 revert
138 rollback
138 rollback
139 root
139 root
140 Show the alias of a debug command if there are no other candidates
140 Show the alias of a debug command if there are no other candidates
141 $ hg debugcomplete rawc
141 $ hg debugcomplete rawc
142
142
143
143
144 Show the global options
144 Show the global options
145 $ hg debugcomplete --options | sort
145 $ hg debugcomplete --options | sort
146 --color
146 --color
147 --config
147 --config
148 --cwd
148 --cwd
149 --debug
149 --debug
150 --debugger
150 --debugger
151 --encoding
151 --encoding
152 --encodingmode
152 --encodingmode
153 --help
153 --help
154 --hidden
154 --hidden
155 --noninteractive
155 --noninteractive
156 --pager
156 --pager
157 --profile
157 --profile
158 --quiet
158 --quiet
159 --repository
159 --repository
160 --time
160 --time
161 --traceback
161 --traceback
162 --verbose
162 --verbose
163 --version
163 --version
164 -R
164 -R
165 -h
165 -h
166 -q
166 -q
167 -v
167 -v
168 -y
168 -y
169
169
170 Show the options for the "serve" command
170 Show the options for the "serve" command
171 $ hg debugcomplete --options serve | sort
171 $ hg debugcomplete --options serve | sort
172 --accesslog
172 --accesslog
173 --address
173 --address
174 --certificate
174 --certificate
175 --cmdserver
175 --cmdserver
176 --color
176 --color
177 --config
177 --config
178 --cwd
178 --cwd
179 --daemon
179 --daemon
180 --daemon-postexec
180 --daemon-postexec
181 --debug
181 --debug
182 --debugger
182 --debugger
183 --encoding
183 --encoding
184 --encodingmode
184 --encodingmode
185 --errorlog
185 --errorlog
186 --help
186 --help
187 --hidden
187 --hidden
188 --ipv6
188 --ipv6
189 --name
189 --name
190 --noninteractive
190 --noninteractive
191 --pager
191 --pager
192 --pid-file
192 --pid-file
193 --port
193 --port
194 --prefix
194 --prefix
195 --print-url
195 --print-url
196 --profile
196 --profile
197 --quiet
197 --quiet
198 --repository
198 --repository
199 --stdio
199 --stdio
200 --style
200 --style
201 --subrepos
201 --subrepos
202 --templates
202 --templates
203 --time
203 --time
204 --traceback
204 --traceback
205 --verbose
205 --verbose
206 --version
206 --version
207 --web-conf
207 --web-conf
208 -6
208 -6
209 -A
209 -A
210 -E
210 -E
211 -R
211 -R
212 -S
212 -S
213 -a
213 -a
214 -d
214 -d
215 -h
215 -h
216 -n
216 -n
217 -p
217 -p
218 -q
218 -q
219 -t
219 -t
220 -v
220 -v
221 -y
221 -y
222
222
223 Show an error if we use --options with an ambiguous abbreviation
223 Show an error if we use --options with an ambiguous abbreviation
224 $ hg debugcomplete --options s
224 $ hg debugcomplete --options s
225 hg: command 's' is ambiguous:
225 hg: command 's' is ambiguous:
226 serve showconfig status summary
226 serve showconfig status summary
227 [255]
227 [255]
228
228
229 Show all commands + options
229 Show all commands + options
230 $ hg debugcommands
230 $ hg debugcommands
231 add: include, exclude, subrepos, dry-run
231 add: include, exclude, subrepos, dry-run
232 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
232 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
233 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
233 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
234 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
234 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
235 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
235 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
236 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
236 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
237 forget: interactive, include, exclude, dry-run
237 forget: interactive, include, exclude, dry-run
238 init: ssh, remotecmd, insecure
238 init: ssh, remotecmd, insecure
239 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
239 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
240 merge: force, rev, preview, abort, tool
240 merge: force, rev, preview, abort, tool
241 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
241 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
242 push: force, rev, bookmark, branch, new-branch, pushvars, ssh, remotecmd, insecure
242 push: force, rev, bookmark, branch, new-branch, pushvars, ssh, remotecmd, insecure
243 remove: after, force, subrepos, include, exclude, dry-run
243 remove: after, force, subrepos, include, exclude, dry-run
244 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
244 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
245 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
245 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
246 summary: remote
246 summary: remote
247 update: clean, check, merge, date, rev, tool
247 update: clean, check, merge, date, rev, tool
248 addremove: similarity, subrepos, include, exclude, dry-run
248 addremove: similarity, subrepos, include, exclude, dry-run
249 archive: no-decode, prefix, rev, type, subrepos, include, exclude
249 archive: no-decode, prefix, rev, type, subrepos, include, exclude
250 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
250 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
251 bisect: reset, good, bad, skip, extend, command, noupdate
251 bisect: reset, good, bad, skip, extend, command, noupdate
252 bookmarks: force, rev, delete, rename, inactive, template
252 bookmarks: force, rev, delete, rename, inactive, template
253 branch: force, clean, rev
253 branch: force, clean, rev
254 branches: active, closed, template
254 branches: active, closed, template
255 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
255 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
256 cat: output, rev, decode, include, exclude, template
256 cat: output, rev, decode, include, exclude, template
257 config: untrusted, edit, local, global, template
257 config: untrusted, edit, local, global, template
258 copy: after, force, include, exclude, dry-run
258 copy: after, force, include, exclude, dry-run
259 debugancestor:
259 debugancestor:
260 debugapplystreamclonebundle:
260 debugapplystreamclonebundle:
261 debugbuilddag: mergeable-file, overwritten-file, new-file
261 debugbuilddag: mergeable-file, overwritten-file, new-file
262 debugbundle: all, part-type, spec
262 debugbundle: all, part-type, spec
263 debugcapabilities:
263 debugcapabilities:
264 debugcheckstate:
264 debugcheckstate:
265 debugcolor: style
265 debugcolor: style
266 debugcommands:
266 debugcommands:
267 debugcomplete: options
267 debugcomplete: options
268 debugcreatestreamclonebundle:
268 debugcreatestreamclonebundle:
269 debugdag: tags, branches, dots, spaces
269 debugdag: tags, branches, dots, spaces
270 debugdata: changelog, manifest, dir
270 debugdata: changelog, manifest, dir
271 debugdate: extended
271 debugdate: extended
272 debugdeltachain: changelog, manifest, dir, template
272 debugdeltachain: changelog, manifest, dir, template
273 debugdirstate: nodates, datesort
273 debugdirstate: nodates, datesort
274 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
274 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
275 debugdownload: output
275 debugdownload: output
276 debugextensions: template
276 debugextensions: template
277 debugfileset: rev, all-files
277 debugfileset: rev, all-files, show-stage
278 debugformat: template
278 debugformat: template
279 debugfsinfo:
279 debugfsinfo:
280 debuggetbundle: head, common, type
280 debuggetbundle: head, common, type
281 debugignore:
281 debugignore:
282 debugindex: changelog, manifest, dir, format
282 debugindex: changelog, manifest, dir, format
283 debugindexdot: changelog, manifest, dir
283 debugindexdot: changelog, manifest, dir
284 debuginstall: template
284 debuginstall: template
285 debugknown:
285 debugknown:
286 debuglabelcomplete:
286 debuglabelcomplete:
287 debuglocks: force-lock, force-wlock, set-lock, set-wlock
287 debuglocks: force-lock, force-wlock, set-lock, set-wlock
288 debugmanifestfulltextcache: clear, add
288 debugmanifestfulltextcache: clear, add
289 debugmergestate:
289 debugmergestate:
290 debugnamecomplete:
290 debugnamecomplete:
291 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
291 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
292 debugpathcomplete: full, normal, added, removed
292 debugpathcomplete: full, normal, added, removed
293 debugpeer:
293 debugpeer:
294 debugpickmergetool: rev, changedelete, include, exclude, tool
294 debugpickmergetool: rev, changedelete, include, exclude, tool
295 debugpushkey:
295 debugpushkey:
296 debugpvec:
296 debugpvec:
297 debugrebuilddirstate: rev, minimal
297 debugrebuilddirstate: rev, minimal
298 debugrebuildfncache:
298 debugrebuildfncache:
299 debugrename: rev
299 debugrename: rev
300 debugrevlog: changelog, manifest, dir, dump
300 debugrevlog: changelog, manifest, dir, dump
301 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
301 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
302 debugserve: sshstdio, logiofd, logiofile
302 debugserve: sshstdio, logiofd, logiofile
303 debugsetparents:
303 debugsetparents:
304 debugssl:
304 debugssl:
305 debugsub: rev
305 debugsub: rev
306 debugsuccessorssets: closest
306 debugsuccessorssets: closest
307 debugtemplate: rev, define
307 debugtemplate: rev, define
308 debuguigetpass: prompt
308 debuguigetpass: prompt
309 debuguiprompt: prompt
309 debuguiprompt: prompt
310 debugupdatecaches:
310 debugupdatecaches:
311 debugupgraderepo: optimize, run
311 debugupgraderepo: optimize, run
312 debugwalk: include, exclude
312 debugwalk: include, exclude
313 debugwhyunstable:
313 debugwhyunstable:
314 debugwireargs: three, four, five, ssh, remotecmd, insecure
314 debugwireargs: three, four, five, ssh, remotecmd, insecure
315 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
315 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
316 files: rev, print0, include, exclude, template, subrepos
316 files: rev, print0, include, exclude, template, subrepos
317 graft: rev, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
317 graft: rev, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
318 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
318 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
319 heads: rev, topo, active, closed, style, template
319 heads: rev, topo, active, closed, style, template
320 help: extension, command, keyword, system
320 help: extension, command, keyword, system
321 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
321 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
322 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
322 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
323 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
323 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
324 locate: rev, print0, fullpath, include, exclude
324 locate: rev, print0, fullpath, include, exclude
325 manifest: rev, all, template
325 manifest: rev, all, template
326 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
326 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
327 parents: rev, style, template
327 parents: rev, style, template
328 paths: template
328 paths: template
329 phase: public, draft, secret, force, rev
329 phase: public, draft, secret, force, rev
330 recover:
330 recover:
331 rename: after, force, include, exclude, dry-run
331 rename: after, force, include, exclude, dry-run
332 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
332 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
333 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
333 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
334 rollback: dry-run, force
334 rollback: dry-run, force
335 root:
335 root:
336 tag: force, local, rev, remove, edit, message, date, user
336 tag: force, local, rev, remove, edit, message, date, user
337 tags: template
337 tags: template
338 tip: patch, git, style, template
338 tip: patch, git, style, template
339 unbundle: update
339 unbundle: update
340 verify:
340 verify:
341 version: template
341 version: template
342
342
343 $ hg init a
343 $ hg init a
344 $ cd a
344 $ cd a
345 $ echo fee > fee
345 $ echo fee > fee
346 $ hg ci -q -Amfee
346 $ hg ci -q -Amfee
347 $ hg tag fee
347 $ hg tag fee
348 $ mkdir fie
348 $ mkdir fie
349 $ echo dead > fie/dead
349 $ echo dead > fie/dead
350 $ echo live > fie/live
350 $ echo live > fie/live
351 $ hg bookmark fo
351 $ hg bookmark fo
352 $ hg branch -q fie
352 $ hg branch -q fie
353 $ hg ci -q -Amfie
353 $ hg ci -q -Amfie
354 $ echo fo > fo
354 $ echo fo > fo
355 $ hg branch -qf default
355 $ hg branch -qf default
356 $ hg ci -q -Amfo
356 $ hg ci -q -Amfo
357 $ echo Fum > Fum
357 $ echo Fum > Fum
358 $ hg ci -q -AmFum
358 $ hg ci -q -AmFum
359 $ hg bookmark Fum
359 $ hg bookmark Fum
360
360
361 Test debugpathcomplete
361 Test debugpathcomplete
362
362
363 $ hg debugpathcomplete f
363 $ hg debugpathcomplete f
364 fee
364 fee
365 fie
365 fie
366 fo
366 fo
367 $ hg debugpathcomplete -f f
367 $ hg debugpathcomplete -f f
368 fee
368 fee
369 fie/dead
369 fie/dead
370 fie/live
370 fie/live
371 fo
371 fo
372
372
373 $ hg rm Fum
373 $ hg rm Fum
374 $ hg debugpathcomplete -r F
374 $ hg debugpathcomplete -r F
375 Fum
375 Fum
376
376
377 Test debugnamecomplete
377 Test debugnamecomplete
378
378
379 $ hg debugnamecomplete
379 $ hg debugnamecomplete
380 Fum
380 Fum
381 default
381 default
382 fee
382 fee
383 fie
383 fie
384 fo
384 fo
385 tip
385 tip
386 $ hg debugnamecomplete f
386 $ hg debugnamecomplete f
387 fee
387 fee
388 fie
388 fie
389 fo
389 fo
390
390
391 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
391 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
392 used for completions in some shells.
392 used for completions in some shells.
393
393
394 $ hg debuglabelcomplete
394 $ hg debuglabelcomplete
395 Fum
395 Fum
396 default
396 default
397 fee
397 fee
398 fie
398 fie
399 fo
399 fo
400 tip
400 tip
401 $ hg debuglabelcomplete f
401 $ hg debuglabelcomplete f
402 fee
402 fee
403 fie
403 fie
404 fo
404 fo
@@ -1,676 +1,714 b''
1 $ fileset() {
1 $ fileset() {
2 > hg debugfileset --all-files "$@"
2 > hg debugfileset --all-files "$@"
3 > }
3 > }
4
4
5 $ hg init repo
5 $ hg init repo
6 $ cd repo
6 $ cd repo
7 $ echo a > a1
7 $ echo a > a1
8 $ echo a > a2
8 $ echo a > a2
9 $ echo b > b1
9 $ echo b > b1
10 $ echo b > b2
10 $ echo b > b2
11 $ hg ci -Am addfiles
11 $ hg ci -Am addfiles
12 adding a1
12 adding a1
13 adding a2
13 adding a2
14 adding b1
14 adding b1
15 adding b2
15 adding b2
16
16
17 Test operators and basic patterns
17 Test operators and basic patterns
18
18
19 $ fileset -v a1
19 $ fileset -v a1
20 (symbol 'a1')
20 (symbol 'a1')
21 a1
21 a1
22 $ fileset -v 'a*'
22 $ fileset -v 'a*'
23 (symbol 'a*')
23 (symbol 'a*')
24 a1
24 a1
25 a2
25 a2
26 $ fileset -v '"re:a\d"'
26 $ fileset -v '"re:a\d"'
27 (string 're:a\\d')
27 (string 're:a\\d')
28 a1
28 a1
29 a2
29 a2
30 $ fileset -v '!re:"a\d"'
30 $ fileset -v '!re:"a\d"'
31 (not
31 (not
32 (kindpat
32 (kindpat
33 (symbol 're')
33 (symbol 're')
34 (string 'a\\d')))
34 (string 'a\\d')))
35 b1
35 b1
36 b2
36 b2
37 $ fileset -v 'path:a1 or glob:b?'
37 $ fileset -v 'path:a1 or glob:b?'
38 (or
38 (or
39 (kindpat
39 (kindpat
40 (symbol 'path')
40 (symbol 'path')
41 (symbol 'a1'))
41 (symbol 'a1'))
42 (kindpat
42 (kindpat
43 (symbol 'glob')
43 (symbol 'glob')
44 (symbol 'b?')))
44 (symbol 'b?')))
45 a1
45 a1
46 b1
46 b1
47 b2
47 b2
48 $ fileset -v 'a1 or a2'
48 $ fileset -v 'a1 or a2'
49 (or
49 (or
50 (symbol 'a1')
50 (symbol 'a1')
51 (symbol 'a2'))
51 (symbol 'a2'))
52 a1
52 a1
53 a2
53 a2
54 $ fileset 'a1 | a2'
54 $ fileset 'a1 | a2'
55 a1
55 a1
56 a2
56 a2
57 $ fileset 'a* and "*1"'
57 $ fileset 'a* and "*1"'
58 a1
58 a1
59 $ fileset 'a* & "*1"'
59 $ fileset 'a* & "*1"'
60 a1
60 a1
61 $ fileset 'not (r"a*")'
61 $ fileset 'not (r"a*")'
62 b1
62 b1
63 b2
63 b2
64 $ fileset '! ("a*")'
64 $ fileset '! ("a*")'
65 b1
65 b1
66 b2
66 b2
67 $ fileset 'a* - a1'
67 $ fileset 'a* - a1'
68 a2
68 a2
69 $ fileset 'a_b'
69 $ fileset 'a_b'
70 $ fileset '"\xy"'
70 $ fileset '"\xy"'
71 hg: parse error: invalid \x escape* (glob)
71 hg: parse error: invalid \x escape* (glob)
72 [255]
72 [255]
73
73
74 Test invalid syntax
74 Test invalid syntax
75
75
76 $ fileset -v '"added"()'
76 $ fileset -v '"added"()'
77 (func
77 (func
78 (string 'added')
78 (string 'added')
79 None)
79 None)
80 hg: parse error: not a symbol
80 hg: parse error: not a symbol
81 [255]
81 [255]
82 $ fileset -v '()()'
82 $ fileset -v '()()'
83 (func
83 (func
84 (group
84 (group
85 None)
85 None)
86 None)
86 None)
87 hg: parse error: not a symbol
87 hg: parse error: not a symbol
88 [255]
88 [255]
89 $ fileset -v -- '-x'
89 $ fileset -v -- '-x'
90 (negate
90 (negate
91 (symbol 'x'))
91 (symbol 'x'))
92 hg: parse error: can't use negate operator in this context
92 hg: parse error: can't use negate operator in this context
93 [255]
93 [255]
94 $ fileset -v -- '-()'
94 $ fileset -v -- '-()'
95 (negate
95 (negate
96 (group
96 (group
97 None))
97 None))
98 hg: parse error: can't use negate operator in this context
98 hg: parse error: can't use negate operator in this context
99 [255]
99 [255]
100
100
101 $ fileset '"path":.'
101 $ fileset '"path":.'
102 hg: parse error: not a symbol
102 hg: parse error: not a symbol
103 [255]
103 [255]
104 $ fileset 'path:foo bar'
104 $ fileset 'path:foo bar'
105 hg: parse error at 9: invalid token
105 hg: parse error at 9: invalid token
106 [255]
106 [255]
107 $ fileset 'foo:bar:baz'
107 $ fileset 'foo:bar:baz'
108 hg: parse error: not a symbol
108 hg: parse error: not a symbol
109 [255]
109 [255]
110 $ fileset 'foo:bar()'
110 $ fileset 'foo:bar()'
111 hg: parse error: pattern must be a string
111 hg: parse error: pattern must be a string
112 [255]
112 [255]
113 $ fileset 'foo:bar'
113 $ fileset 'foo:bar'
114 hg: parse error: invalid pattern kind: foo
114 hg: parse error: invalid pattern kind: foo
115 [255]
115 [255]
116
116
117 Show parsed tree at stages:
118
119 $ fileset -p unknown a
120 abort: invalid stage name: unknown
121 [255]
122
123 $ fileset -p parsed 'path:a1 or glob:b?'
124 * parsed:
125 (or
126 (kindpat
127 (symbol 'path')
128 (symbol 'a1'))
129 (kindpat
130 (symbol 'glob')
131 (symbol 'b?')))
132 a1
133 b1
134 b2
135
136 $ fileset -p all 'a1 or a2 or (grep("b") & clean())'
137 * parsed:
138 (or
139 (or
140 (symbol 'a1')
141 (symbol 'a2'))
142 (group
143 (and
144 (func
145 (symbol 'grep')
146 (string 'b'))
147 (func
148 (symbol 'clean')
149 None))))
150 a1
151 a2
152 b1
153 b2
154
117 Test files status
155 Test files status
118
156
119 $ rm a1
157 $ rm a1
120 $ hg rm a2
158 $ hg rm a2
121 $ echo b >> b2
159 $ echo b >> b2
122 $ hg cp b1 c1
160 $ hg cp b1 c1
123 $ echo c > c2
161 $ echo c > c2
124 $ echo c > c3
162 $ echo c > c3
125 $ cat > .hgignore <<EOF
163 $ cat > .hgignore <<EOF
126 > \.hgignore
164 > \.hgignore
127 > 2$
165 > 2$
128 > EOF
166 > EOF
129 $ fileset 'modified()'
167 $ fileset 'modified()'
130 b2
168 b2
131 $ fileset 'added()'
169 $ fileset 'added()'
132 c1
170 c1
133 $ fileset 'removed()'
171 $ fileset 'removed()'
134 a2
172 a2
135 $ fileset 'deleted()'
173 $ fileset 'deleted()'
136 a1
174 a1
137 $ fileset 'missing()'
175 $ fileset 'missing()'
138 a1
176 a1
139 $ fileset 'unknown()'
177 $ fileset 'unknown()'
140 c3
178 c3
141 $ fileset 'ignored()'
179 $ fileset 'ignored()'
142 .hgignore
180 .hgignore
143 c2
181 c2
144 $ fileset 'hgignore()'
182 $ fileset 'hgignore()'
145 .hgignore
183 .hgignore
146 a2
184 a2
147 b2
185 b2
148 c2
186 c2
149 $ fileset 'clean()'
187 $ fileset 'clean()'
150 b1
188 b1
151 $ fileset 'copied()'
189 $ fileset 'copied()'
152 c1
190 c1
153
191
154 Test files status in different revisions
192 Test files status in different revisions
155
193
156 $ hg status -m
194 $ hg status -m
157 M b2
195 M b2
158 $ fileset -r0 'revs("wdir()", modified())' --traceback
196 $ fileset -r0 'revs("wdir()", modified())' --traceback
159 b2
197 b2
160 $ hg status -a
198 $ hg status -a
161 A c1
199 A c1
162 $ fileset -r0 'revs("wdir()", added())'
200 $ fileset -r0 'revs("wdir()", added())'
163 c1
201 c1
164 $ hg status --change 0 -a
202 $ hg status --change 0 -a
165 A a1
203 A a1
166 A a2
204 A a2
167 A b1
205 A b1
168 A b2
206 A b2
169 $ hg status -mru
207 $ hg status -mru
170 M b2
208 M b2
171 R a2
209 R a2
172 ? c3
210 ? c3
173 $ fileset -r0 'added() and revs("wdir()", modified() or removed() or unknown())'
211 $ fileset -r0 'added() and revs("wdir()", modified() or removed() or unknown())'
174 a2
212 a2
175 b2
213 b2
176 $ fileset -r0 'added() or revs("wdir()", added())'
214 $ fileset -r0 'added() or revs("wdir()", added())'
177 a1
215 a1
178 a2
216 a2
179 b1
217 b1
180 b2
218 b2
181 c1
219 c1
182
220
183 Test files properties
221 Test files properties
184
222
185 >>> open('bin', 'wb').write(b'\0a') and None
223 >>> open('bin', 'wb').write(b'\0a') and None
186 $ fileset 'binary()'
224 $ fileset 'binary()'
187 bin
225 bin
188 $ fileset 'binary() and unknown()'
226 $ fileset 'binary() and unknown()'
189 bin
227 bin
190 $ echo '^bin$' >> .hgignore
228 $ echo '^bin$' >> .hgignore
191 $ fileset 'binary() and ignored()'
229 $ fileset 'binary() and ignored()'
192 bin
230 bin
193 $ hg add bin
231 $ hg add bin
194 $ fileset 'binary()'
232 $ fileset 'binary()'
195 bin
233 bin
196
234
197 $ fileset 'grep("b{1}")'
235 $ fileset 'grep("b{1}")'
198 .hgignore
236 .hgignore
199 b1
237 b1
200 b2
238 b2
201 c1
239 c1
202 $ fileset 'grep("missingparens(")'
240 $ fileset 'grep("missingparens(")'
203 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \)).* (re)
241 hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \)).* (re)
204 [255]
242 [255]
205
243
206 #if execbit
244 #if execbit
207 $ chmod +x b2
245 $ chmod +x b2
208 $ fileset 'exec()'
246 $ fileset 'exec()'
209 b2
247 b2
210 #endif
248 #endif
211
249
212 #if symlink
250 #if symlink
213 $ ln -s b2 b2link
251 $ ln -s b2 b2link
214 $ fileset 'symlink() and unknown()'
252 $ fileset 'symlink() and unknown()'
215 b2link
253 b2link
216 $ hg add b2link
254 $ hg add b2link
217 #endif
255 #endif
218
256
219 #if no-windows
257 #if no-windows
220 $ echo foo > con.xml
258 $ echo foo > con.xml
221 $ fileset 'not portable()'
259 $ fileset 'not portable()'
222 con.xml
260 con.xml
223 $ hg --config ui.portablefilenames=ignore add con.xml
261 $ hg --config ui.portablefilenames=ignore add con.xml
224 #endif
262 #endif
225
263
226 >>> open('1k', 'wb').write(b' '*1024) and None
264 >>> open('1k', 'wb').write(b' '*1024) and None
227 >>> open('2k', 'wb').write(b' '*2048) and None
265 >>> open('2k', 'wb').write(b' '*2048) and None
228 $ hg add 1k 2k
266 $ hg add 1k 2k
229 $ fileset 'size("bar")'
267 $ fileset 'size("bar")'
230 hg: parse error: couldn't parse size: bar
268 hg: parse error: couldn't parse size: bar
231 [255]
269 [255]
232 $ fileset '(1k, 2k)'
270 $ fileset '(1k, 2k)'
233 hg: parse error: can't use a list in this context
271 hg: parse error: can't use a list in this context
234 (see hg help "filesets.x or y")
272 (see hg help "filesets.x or y")
235 [255]
273 [255]
236 $ fileset 'size(1k)'
274 $ fileset 'size(1k)'
237 1k
275 1k
238 $ fileset '(1k or 2k) and size("< 2k")'
276 $ fileset '(1k or 2k) and size("< 2k")'
239 1k
277 1k
240 $ fileset '(1k or 2k) and size("<=2k")'
278 $ fileset '(1k or 2k) and size("<=2k")'
241 1k
279 1k
242 2k
280 2k
243 $ fileset '(1k or 2k) and size("> 1k")'
281 $ fileset '(1k or 2k) and size("> 1k")'
244 2k
282 2k
245 $ fileset '(1k or 2k) and size(">=1K")'
283 $ fileset '(1k or 2k) and size(">=1K")'
246 1k
284 1k
247 2k
285 2k
248 $ fileset '(1k or 2k) and size(".5KB - 1.5kB")'
286 $ fileset '(1k or 2k) and size(".5KB - 1.5kB")'
249 1k
287 1k
250 $ fileset 'size("1M")'
288 $ fileset 'size("1M")'
251 $ fileset 'size("1 GB")'
289 $ fileset 'size("1 GB")'
252
290
253 Test merge states
291 Test merge states
254
292
255 $ hg ci -m manychanges
293 $ hg ci -m manychanges
256 $ hg file -r . 'set:copied() & modified()'
294 $ hg file -r . 'set:copied() & modified()'
257 [1]
295 [1]
258 $ hg up -C 0
296 $ hg up -C 0
259 * files updated, 0 files merged, * files removed, 0 files unresolved (glob)
297 * files updated, 0 files merged, * files removed, 0 files unresolved (glob)
260 $ echo c >> b2
298 $ echo c >> b2
261 $ hg ci -m diverging b2
299 $ hg ci -m diverging b2
262 created new head
300 created new head
263 $ fileset 'resolved()'
301 $ fileset 'resolved()'
264 $ fileset 'unresolved()'
302 $ fileset 'unresolved()'
265 $ hg merge
303 $ hg merge
266 merging b2
304 merging b2
267 warning: conflicts while merging b2! (edit, then use 'hg resolve --mark')
305 warning: conflicts while merging b2! (edit, then use 'hg resolve --mark')
268 * files updated, 0 files merged, 1 files removed, 1 files unresolved (glob)
306 * files updated, 0 files merged, 1 files removed, 1 files unresolved (glob)
269 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
307 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
270 [1]
308 [1]
271 $ fileset 'resolved()'
309 $ fileset 'resolved()'
272 $ fileset 'unresolved()'
310 $ fileset 'unresolved()'
273 b2
311 b2
274 $ echo e > b2
312 $ echo e > b2
275 $ hg resolve -m b2
313 $ hg resolve -m b2
276 (no more unresolved files)
314 (no more unresolved files)
277 $ fileset 'resolved()'
315 $ fileset 'resolved()'
278 b2
316 b2
279 $ fileset 'unresolved()'
317 $ fileset 'unresolved()'
280 $ hg ci -m merge
318 $ hg ci -m merge
281
319
282 Test subrepo predicate
320 Test subrepo predicate
283
321
284 $ hg init sub
322 $ hg init sub
285 $ echo a > sub/suba
323 $ echo a > sub/suba
286 $ hg -R sub add sub/suba
324 $ hg -R sub add sub/suba
287 $ hg -R sub ci -m sub
325 $ hg -R sub ci -m sub
288 $ echo 'sub = sub' > .hgsub
326 $ echo 'sub = sub' > .hgsub
289 $ hg init sub2
327 $ hg init sub2
290 $ echo b > sub2/b
328 $ echo b > sub2/b
291 $ hg -R sub2 ci -Am sub2
329 $ hg -R sub2 ci -Am sub2
292 adding b
330 adding b
293 $ echo 'sub2 = sub2' >> .hgsub
331 $ echo 'sub2 = sub2' >> .hgsub
294 $ fileset 'subrepo()'
332 $ fileset 'subrepo()'
295 $ hg add .hgsub
333 $ hg add .hgsub
296 $ fileset 'subrepo()'
334 $ fileset 'subrepo()'
297 sub
335 sub
298 sub2
336 sub2
299 $ fileset 'subrepo("sub")'
337 $ fileset 'subrepo("sub")'
300 sub
338 sub
301 $ fileset 'subrepo("glob:*")'
339 $ fileset 'subrepo("glob:*")'
302 sub
340 sub
303 sub2
341 sub2
304 $ hg ci -m subrepo
342 $ hg ci -m subrepo
305
343
306 Test that .hgsubstate is updated as appropriate during a conversion. The
344 Test that .hgsubstate is updated as appropriate during a conversion. The
307 saverev property is enough to alter the hashes of the subrepo.
345 saverev property is enough to alter the hashes of the subrepo.
308
346
309 $ hg init ../converted
347 $ hg init ../converted
310 $ hg --config extensions.convert= convert --config convert.hg.saverev=True \
348 $ hg --config extensions.convert= convert --config convert.hg.saverev=True \
311 > sub ../converted/sub
349 > sub ../converted/sub
312 initializing destination ../converted/sub repository
350 initializing destination ../converted/sub repository
313 scanning source...
351 scanning source...
314 sorting...
352 sorting...
315 converting...
353 converting...
316 0 sub
354 0 sub
317 $ hg clone -U sub2 ../converted/sub2
355 $ hg clone -U sub2 ../converted/sub2
318 $ hg --config extensions.convert= convert --config convert.hg.saverev=True \
356 $ hg --config extensions.convert= convert --config convert.hg.saverev=True \
319 > . ../converted
357 > . ../converted
320 scanning source...
358 scanning source...
321 sorting...
359 sorting...
322 converting...
360 converting...
323 4 addfiles
361 4 addfiles
324 3 manychanges
362 3 manychanges
325 2 diverging
363 2 diverging
326 1 merge
364 1 merge
327 0 subrepo
365 0 subrepo
328 no ".hgsubstate" updates will be made for "sub2"
366 no ".hgsubstate" updates will be made for "sub2"
329 $ hg up -q -R ../converted -r tip
367 $ hg up -q -R ../converted -r tip
330 $ hg --cwd ../converted cat sub/suba sub2/b -r tip
368 $ hg --cwd ../converted cat sub/suba sub2/b -r tip
331 a
369 a
332 b
370 b
333 $ oldnode=`hg log -r tip -T "{node}\n"`
371 $ oldnode=`hg log -r tip -T "{node}\n"`
334 $ newnode=`hg log -R ../converted -r tip -T "{node}\n"`
372 $ newnode=`hg log -R ../converted -r tip -T "{node}\n"`
335 $ [ "$oldnode" != "$newnode" ] || echo "nothing changed"
373 $ [ "$oldnode" != "$newnode" ] || echo "nothing changed"
336
374
337 Test with a revision
375 Test with a revision
338
376
339 $ hg log -G --template '{rev} {desc}\n'
377 $ hg log -G --template '{rev} {desc}\n'
340 @ 4 subrepo
378 @ 4 subrepo
341 |
379 |
342 o 3 merge
380 o 3 merge
343 |\
381 |\
344 | o 2 diverging
382 | o 2 diverging
345 | |
383 | |
346 o | 1 manychanges
384 o | 1 manychanges
347 |/
385 |/
348 o 0 addfiles
386 o 0 addfiles
349
387
350 $ echo unknown > unknown
388 $ echo unknown > unknown
351 $ fileset -r1 'modified()'
389 $ fileset -r1 'modified()'
352 b2
390 b2
353 $ fileset -r1 'added() and c1'
391 $ fileset -r1 'added() and c1'
354 c1
392 c1
355 $ fileset -r1 'removed()'
393 $ fileset -r1 'removed()'
356 a2
394 a2
357 $ fileset -r1 'deleted()'
395 $ fileset -r1 'deleted()'
358 $ fileset -r1 'unknown()'
396 $ fileset -r1 'unknown()'
359 $ fileset -r1 'ignored()'
397 $ fileset -r1 'ignored()'
360 $ fileset -r1 'hgignore()'
398 $ fileset -r1 'hgignore()'
361 .hgignore
399 .hgignore
362 a2
400 a2
363 b2
401 b2
364 bin
402 bin
365 c2
403 c2
366 sub2
404 sub2
367 $ fileset -r1 'binary()'
405 $ fileset -r1 'binary()'
368 bin
406 bin
369 $ fileset -r1 'size(1k)'
407 $ fileset -r1 'size(1k)'
370 1k
408 1k
371 $ fileset -r3 'resolved()'
409 $ fileset -r3 'resolved()'
372 $ fileset -r3 'unresolved()'
410 $ fileset -r3 'unresolved()'
373
411
374 #if execbit
412 #if execbit
375 $ fileset -r1 'exec()'
413 $ fileset -r1 'exec()'
376 b2
414 b2
377 #endif
415 #endif
378
416
379 #if symlink
417 #if symlink
380 $ fileset -r1 'symlink()'
418 $ fileset -r1 'symlink()'
381 b2link
419 b2link
382 #endif
420 #endif
383
421
384 #if no-windows
422 #if no-windows
385 $ fileset -r1 'not portable()'
423 $ fileset -r1 'not portable()'
386 con.xml
424 con.xml
387 $ hg forget 'con.xml'
425 $ hg forget 'con.xml'
388 #endif
426 #endif
389
427
390 $ fileset -r4 'subrepo("re:su.*")'
428 $ fileset -r4 'subrepo("re:su.*")'
391 sub
429 sub
392 sub2
430 sub2
393 $ fileset -r4 'subrepo(re:su.*)'
431 $ fileset -r4 'subrepo(re:su.*)'
394 sub
432 sub
395 sub2
433 sub2
396 $ fileset -r4 'subrepo("sub")'
434 $ fileset -r4 'subrepo("sub")'
397 sub
435 sub
398 $ fileset -r4 'b2 or c1'
436 $ fileset -r4 'b2 or c1'
399 b2
437 b2
400 c1
438 c1
401
439
402 >>> open('dos', 'wb').write(b"dos\r\n") and None
440 >>> open('dos', 'wb').write(b"dos\r\n") and None
403 >>> open('mixed', 'wb').write(b"dos\r\nunix\n") and None
441 >>> open('mixed', 'wb').write(b"dos\r\nunix\n") and None
404 >>> open('mac', 'wb').write(b"mac\r") and None
442 >>> open('mac', 'wb').write(b"mac\r") and None
405 $ hg add dos mixed mac
443 $ hg add dos mixed mac
406
444
407 (remove a1, to examine safety of 'eol' on removed files)
445 (remove a1, to examine safety of 'eol' on removed files)
408 $ rm a1
446 $ rm a1
409
447
410 $ fileset 'eol(dos)'
448 $ fileset 'eol(dos)'
411 dos
449 dos
412 mixed
450 mixed
413 $ fileset 'eol(unix)'
451 $ fileset 'eol(unix)'
414 .hgignore
452 .hgignore
415 .hgsub
453 .hgsub
416 .hgsubstate
454 .hgsubstate
417 b1
455 b1
418 b2
456 b2
419 b2.orig
457 b2.orig
420 c1
458 c1
421 c2
459 c2
422 c3
460 c3
423 con.xml (no-windows !)
461 con.xml (no-windows !)
424 mixed
462 mixed
425 unknown
463 unknown
426 $ fileset 'eol(mac)'
464 $ fileset 'eol(mac)'
427 mac
465 mac
428
466
429 Test safety of 'encoding' on removed files
467 Test safety of 'encoding' on removed files
430
468
431 $ fileset 'encoding("ascii")'
469 $ fileset 'encoding("ascii")'
432 .hgignore
470 .hgignore
433 .hgsub
471 .hgsub
434 .hgsubstate
472 .hgsubstate
435 1k
473 1k
436 2k
474 2k
437 b1
475 b1
438 b2
476 b2
439 b2.orig
477 b2.orig
440 b2link (symlink !)
478 b2link (symlink !)
441 bin
479 bin
442 c1
480 c1
443 c2
481 c2
444 c3
482 c3
445 con.xml (no-windows !)
483 con.xml (no-windows !)
446 dos
484 dos
447 mac
485 mac
448 mixed
486 mixed
449 unknown
487 unknown
450
488
451 Test 'revs(...)'
489 Test 'revs(...)'
452 ================
490 ================
453
491
454 small reminder of the repository state
492 small reminder of the repository state
455
493
456 $ hg log -G
494 $ hg log -G
457 @ changeset: 4:* (glob)
495 @ changeset: 4:* (glob)
458 | tag: tip
496 | tag: tip
459 | user: test
497 | user: test
460 | date: Thu Jan 01 00:00:00 1970 +0000
498 | date: Thu Jan 01 00:00:00 1970 +0000
461 | summary: subrepo
499 | summary: subrepo
462 |
500 |
463 o changeset: 3:* (glob)
501 o changeset: 3:* (glob)
464 |\ parent: 2:55b05bdebf36
502 |\ parent: 2:55b05bdebf36
465 | | parent: 1:* (glob)
503 | | parent: 1:* (glob)
466 | | user: test
504 | | user: test
467 | | date: Thu Jan 01 00:00:00 1970 +0000
505 | | date: Thu Jan 01 00:00:00 1970 +0000
468 | | summary: merge
506 | | summary: merge
469 | |
507 | |
470 | o changeset: 2:55b05bdebf36
508 | o changeset: 2:55b05bdebf36
471 | | parent: 0:8a9576c51c1f
509 | | parent: 0:8a9576c51c1f
472 | | user: test
510 | | user: test
473 | | date: Thu Jan 01 00:00:00 1970 +0000
511 | | date: Thu Jan 01 00:00:00 1970 +0000
474 | | summary: diverging
512 | | summary: diverging
475 | |
513 | |
476 o | changeset: 1:* (glob)
514 o | changeset: 1:* (glob)
477 |/ user: test
515 |/ user: test
478 | date: Thu Jan 01 00:00:00 1970 +0000
516 | date: Thu Jan 01 00:00:00 1970 +0000
479 | summary: manychanges
517 | summary: manychanges
480 |
518 |
481 o changeset: 0:8a9576c51c1f
519 o changeset: 0:8a9576c51c1f
482 user: test
520 user: test
483 date: Thu Jan 01 00:00:00 1970 +0000
521 date: Thu Jan 01 00:00:00 1970 +0000
484 summary: addfiles
522 summary: addfiles
485
523
486 $ hg status --change 0
524 $ hg status --change 0
487 A a1
525 A a1
488 A a2
526 A a2
489 A b1
527 A b1
490 A b2
528 A b2
491 $ hg status --change 1
529 $ hg status --change 1
492 M b2
530 M b2
493 A 1k
531 A 1k
494 A 2k
532 A 2k
495 A b2link (no-windows !)
533 A b2link (no-windows !)
496 A bin
534 A bin
497 A c1
535 A c1
498 A con.xml (no-windows !)
536 A con.xml (no-windows !)
499 R a2
537 R a2
500 $ hg status --change 2
538 $ hg status --change 2
501 M b2
539 M b2
502 $ hg status --change 3
540 $ hg status --change 3
503 M b2
541 M b2
504 A 1k
542 A 1k
505 A 2k
543 A 2k
506 A b2link (no-windows !)
544 A b2link (no-windows !)
507 A bin
545 A bin
508 A c1
546 A c1
509 A con.xml (no-windows !)
547 A con.xml (no-windows !)
510 R a2
548 R a2
511 $ hg status --change 4
549 $ hg status --change 4
512 A .hgsub
550 A .hgsub
513 A .hgsubstate
551 A .hgsubstate
514 $ hg status
552 $ hg status
515 A dos
553 A dos
516 A mac
554 A mac
517 A mixed
555 A mixed
518 R con.xml (no-windows !)
556 R con.xml (no-windows !)
519 ! a1
557 ! a1
520 ? b2.orig
558 ? b2.orig
521 ? c3
559 ? c3
522 ? unknown
560 ? unknown
523
561
524 Test files at -r0 should be filtered by files at wdir
562 Test files at -r0 should be filtered by files at wdir
525 -----------------------------------------------------
563 -----------------------------------------------------
526
564
527 $ fileset -r0 'tracked() and revs("wdir()", tracked())'
565 $ fileset -r0 'tracked() and revs("wdir()", tracked())'
528 a1
566 a1
529 b1
567 b1
530 b2
568 b2
531
569
532 Test that "revs()" work at all
570 Test that "revs()" work at all
533 ------------------------------
571 ------------------------------
534
572
535 $ fileset "revs('2', modified())"
573 $ fileset "revs('2', modified())"
536 b2
574 b2
537
575
538 Test that "revs()" work for file missing in the working copy/current context
576 Test that "revs()" work for file missing in the working copy/current context
539 ----------------------------------------------------------------------------
577 ----------------------------------------------------------------------------
540
578
541 (a2 not in working copy)
579 (a2 not in working copy)
542
580
543 $ fileset "revs('0', added())"
581 $ fileset "revs('0', added())"
544 a1
582 a1
545 a2
583 a2
546 b1
584 b1
547 b2
585 b2
548
586
549 (none of the file exist in "0")
587 (none of the file exist in "0")
550
588
551 $ fileset -r 0 "revs('4', added())"
589 $ fileset -r 0 "revs('4', added())"
552 .hgsub
590 .hgsub
553 .hgsubstate
591 .hgsubstate
554
592
555 Call with empty revset
593 Call with empty revset
556 --------------------------
594 --------------------------
557
595
558 $ fileset "revs('2-2', modified())"
596 $ fileset "revs('2-2', modified())"
559
597
560 Call with revset matching multiple revs
598 Call with revset matching multiple revs
561 ---------------------------------------
599 ---------------------------------------
562
600
563 $ fileset "revs('0+4', added())"
601 $ fileset "revs('0+4', added())"
564 .hgsub
602 .hgsub
565 .hgsubstate
603 .hgsubstate
566 a1
604 a1
567 a2
605 a2
568 b1
606 b1
569 b2
607 b2
570
608
571 overlapping set
609 overlapping set
572
610
573 $ fileset "revs('1+2', modified())"
611 $ fileset "revs('1+2', modified())"
574 b2
612 b2
575
613
576 test 'status(...)'
614 test 'status(...)'
577 =================
615 =================
578
616
579 Simple case
617 Simple case
580 -----------
618 -----------
581
619
582 $ fileset "status(3, 4, added())"
620 $ fileset "status(3, 4, added())"
583 .hgsub
621 .hgsub
584 .hgsubstate
622 .hgsubstate
585
623
586 use rev to restrict matched file
624 use rev to restrict matched file
587 -----------------------------------------
625 -----------------------------------------
588
626
589 $ hg status --removed --rev 0 --rev 1
627 $ hg status --removed --rev 0 --rev 1
590 R a2
628 R a2
591 $ fileset "status(0, 1, removed())"
629 $ fileset "status(0, 1, removed())"
592 a2
630 a2
593 $ fileset "tracked() and status(0, 1, removed())"
631 $ fileset "tracked() and status(0, 1, removed())"
594 $ fileset -r 4 "status(0, 1, removed())"
632 $ fileset -r 4 "status(0, 1, removed())"
595 a2
633 a2
596 $ fileset -r 4 "tracked() and status(0, 1, removed())"
634 $ fileset -r 4 "tracked() and status(0, 1, removed())"
597 $ fileset "revs('4', tracked() and status(0, 1, removed()))"
635 $ fileset "revs('4', tracked() and status(0, 1, removed()))"
598 $ fileset "revs('0', tracked() and status(0, 1, removed()))"
636 $ fileset "revs('0', tracked() and status(0, 1, removed()))"
599 a2
637 a2
600
638
601 check wdir()
639 check wdir()
602 ------------
640 ------------
603
641
604 $ hg status --removed --rev 4
642 $ hg status --removed --rev 4
605 R con.xml (no-windows !)
643 R con.xml (no-windows !)
606 $ fileset "status(4, 'wdir()', removed())"
644 $ fileset "status(4, 'wdir()', removed())"
607 con.xml (no-windows !)
645 con.xml (no-windows !)
608
646
609 $ hg status --removed --rev 2
647 $ hg status --removed --rev 2
610 R a2
648 R a2
611 $ fileset "status('2', 'wdir()', removed())"
649 $ fileset "status('2', 'wdir()', removed())"
612 a2
650 a2
613
651
614 test backward status
652 test backward status
615 --------------------
653 --------------------
616
654
617 $ hg status --removed --rev 0 --rev 4
655 $ hg status --removed --rev 0 --rev 4
618 R a2
656 R a2
619 $ hg status --added --rev 4 --rev 0
657 $ hg status --added --rev 4 --rev 0
620 A a2
658 A a2
621 $ fileset "status(4, 0, added())"
659 $ fileset "status(4, 0, added())"
622 a2
660 a2
623
661
624 test cross branch status
662 test cross branch status
625 ------------------------
663 ------------------------
626
664
627 $ hg status --added --rev 1 --rev 2
665 $ hg status --added --rev 1 --rev 2
628 A a2
666 A a2
629 $ fileset "status(1, 2, added())"
667 $ fileset "status(1, 2, added())"
630 a2
668 a2
631
669
632 test with multi revs revset
670 test with multi revs revset
633 ---------------------------
671 ---------------------------
634 $ hg status --added --rev 0:1 --rev 3:4
672 $ hg status --added --rev 0:1 --rev 3:4
635 A .hgsub
673 A .hgsub
636 A .hgsubstate
674 A .hgsubstate
637 A 1k
675 A 1k
638 A 2k
676 A 2k
639 A b2link (no-windows !)
677 A b2link (no-windows !)
640 A bin
678 A bin
641 A c1
679 A c1
642 A con.xml (no-windows !)
680 A con.xml (no-windows !)
643 $ fileset "status('0:1', '3:4', added())"
681 $ fileset "status('0:1', '3:4', added())"
644 .hgsub
682 .hgsub
645 .hgsubstate
683 .hgsubstate
646 1k
684 1k
647 2k
685 2k
648 b2link (no-windows !)
686 b2link (no-windows !)
649 bin
687 bin
650 c1
688 c1
651 con.xml (no-windows !)
689 con.xml (no-windows !)
652
690
653 tests with empty value
691 tests with empty value
654 ----------------------
692 ----------------------
655
693
656 Fully empty revset
694 Fully empty revset
657
695
658 $ fileset "status('', '4', added())"
696 $ fileset "status('', '4', added())"
659 hg: parse error: first argument to status must be a revision
697 hg: parse error: first argument to status must be a revision
660 [255]
698 [255]
661 $ fileset "status('2', '', added())"
699 $ fileset "status('2', '', added())"
662 hg: parse error: second argument to status must be a revision
700 hg: parse error: second argument to status must be a revision
663 [255]
701 [255]
664
702
665 Empty revset will error at the revset layer
703 Empty revset will error at the revset layer
666
704
667 $ fileset "status(' ', '4', added())"
705 $ fileset "status(' ', '4', added())"
668 hg: parse error at 1: not a prefix: end
706 hg: parse error at 1: not a prefix: end
669 (
707 (
670 ^ here)
708 ^ here)
671 [255]
709 [255]
672 $ fileset "status('2', ' ', added())"
710 $ fileset "status('2', ' ', added())"
673 hg: parse error at 1: not a prefix: end
711 hg: parse error at 1: not a prefix: end
674 (
712 (
675 ^ here)
713 ^ here)
676 [255]
714 [255]
General Comments 0
You need to be logged in to leave comments. Login now