##// END OF EJS Templates
debugdiscovery: add flags to run discovery on subsets of the local repo...
marmoute -
r47205:4f5e9a77 default
parent child Browse files
Show More
@@ -1,4678 +1,4732 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 glob
14 import glob
15 import operator
15 import operator
16 import os
16 import os
17 import platform
17 import platform
18 import random
18 import random
19 import re
19 import re
20 import socket
20 import socket
21 import ssl
21 import ssl
22 import stat
22 import stat
23 import string
23 import string
24 import subprocess
24 import subprocess
25 import sys
25 import sys
26 import time
26 import time
27
27
28 from .i18n import _
28 from .i18n import _
29 from .node import (
29 from .node import (
30 bin,
30 bin,
31 hex,
31 hex,
32 nullid,
32 nullid,
33 nullrev,
33 nullrev,
34 short,
34 short,
35 )
35 )
36 from .pycompat import (
36 from .pycompat import (
37 getattr,
37 getattr,
38 open,
38 open,
39 )
39 )
40 from . import (
40 from . import (
41 bundle2,
41 bundle2,
42 bundlerepo,
42 bundlerepo,
43 changegroup,
43 changegroup,
44 cmdutil,
44 cmdutil,
45 color,
45 color,
46 context,
46 context,
47 copies,
47 copies,
48 dagparser,
48 dagparser,
49 encoding,
49 encoding,
50 error,
50 error,
51 exchange,
51 exchange,
52 extensions,
52 extensions,
53 filemerge,
53 filemerge,
54 filesetlang,
54 filesetlang,
55 formatter,
55 formatter,
56 hg,
56 hg,
57 httppeer,
57 httppeer,
58 localrepo,
58 localrepo,
59 lock as lockmod,
59 lock as lockmod,
60 logcmdutil,
60 logcmdutil,
61 mergestate as mergestatemod,
61 mergestate as mergestatemod,
62 metadata,
62 metadata,
63 obsolete,
63 obsolete,
64 obsutil,
64 obsutil,
65 pathutil,
65 pathutil,
66 phases,
66 phases,
67 policy,
67 policy,
68 pvec,
68 pvec,
69 pycompat,
69 pycompat,
70 registrar,
70 registrar,
71 repair,
71 repair,
72 repoview,
72 revlog,
73 revlog,
73 revset,
74 revset,
74 revsetlang,
75 revsetlang,
75 scmutil,
76 scmutil,
76 setdiscovery,
77 setdiscovery,
77 simplemerge,
78 simplemerge,
78 sshpeer,
79 sshpeer,
79 sslutil,
80 sslutil,
80 streamclone,
81 streamclone,
81 strip,
82 strip,
82 tags as tagsmod,
83 tags as tagsmod,
83 templater,
84 templater,
84 treediscovery,
85 treediscovery,
85 upgrade,
86 upgrade,
86 url as urlmod,
87 url as urlmod,
87 util,
88 util,
88 vfs as vfsmod,
89 vfs as vfsmod,
89 wireprotoframing,
90 wireprotoframing,
90 wireprotoserver,
91 wireprotoserver,
91 wireprotov2peer,
92 wireprotov2peer,
92 )
93 )
93 from .utils import (
94 from .utils import (
94 cborutil,
95 cborutil,
95 compression,
96 compression,
96 dateutil,
97 dateutil,
97 procutil,
98 procutil,
98 stringutil,
99 stringutil,
99 )
100 )
100
101
101 from .revlogutils import (
102 from .revlogutils import (
102 deltas as deltautil,
103 deltas as deltautil,
103 nodemap,
104 nodemap,
104 sidedata,
105 sidedata,
105 )
106 )
106
107
107 release = lockmod.release
108 release = lockmod.release
108
109
109 table = {}
110 table = {}
110 table.update(strip.command._table)
111 table.update(strip.command._table)
111 command = registrar.command(table)
112 command = registrar.command(table)
112
113
113
114
114 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
115 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
115 def debugancestor(ui, repo, *args):
116 def debugancestor(ui, repo, *args):
116 """find the ancestor revision of two revisions in a given index"""
117 """find the ancestor revision of two revisions in a given index"""
117 if len(args) == 3:
118 if len(args) == 3:
118 index, rev1, rev2 = args
119 index, rev1, rev2 = args
119 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
120 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
120 lookup = r.lookup
121 lookup = r.lookup
121 elif len(args) == 2:
122 elif len(args) == 2:
122 if not repo:
123 if not repo:
123 raise error.Abort(
124 raise error.Abort(
124 _(b'there is no Mercurial repository here (.hg not found)')
125 _(b'there is no Mercurial repository here (.hg not found)')
125 )
126 )
126 rev1, rev2 = args
127 rev1, rev2 = args
127 r = repo.changelog
128 r = repo.changelog
128 lookup = repo.lookup
129 lookup = repo.lookup
129 else:
130 else:
130 raise error.Abort(_(b'either two or three arguments required'))
131 raise error.Abort(_(b'either two or three arguments required'))
131 a = r.ancestor(lookup(rev1), lookup(rev2))
132 a = r.ancestor(lookup(rev1), lookup(rev2))
132 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
133 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
133
134
134
135
135 @command(b'debugantivirusrunning', [])
136 @command(b'debugantivirusrunning', [])
136 def debugantivirusrunning(ui, repo):
137 def debugantivirusrunning(ui, repo):
137 """attempt to trigger an antivirus scanner to see if one is active"""
138 """attempt to trigger an antivirus scanner to see if one is active"""
138 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
139 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
139 f.write(
140 f.write(
140 util.b85decode(
141 util.b85decode(
141 # This is a base85-armored version of the EICAR test file. See
142 # This is a base85-armored version of the EICAR test file. See
142 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
143 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
143 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
144 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
144 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
145 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
145 )
146 )
146 )
147 )
147 # Give an AV engine time to scan the file.
148 # Give an AV engine time to scan the file.
148 time.sleep(2)
149 time.sleep(2)
149 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
150 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
150
151
151
152
152 @command(b'debugapplystreamclonebundle', [], b'FILE')
153 @command(b'debugapplystreamclonebundle', [], b'FILE')
153 def debugapplystreamclonebundle(ui, repo, fname):
154 def debugapplystreamclonebundle(ui, repo, fname):
154 """apply a stream clone bundle file"""
155 """apply a stream clone bundle file"""
155 f = hg.openpath(ui, fname)
156 f = hg.openpath(ui, fname)
156 gen = exchange.readbundle(ui, f, fname)
157 gen = exchange.readbundle(ui, f, fname)
157 gen.apply(repo)
158 gen.apply(repo)
158
159
159
160
160 @command(
161 @command(
161 b'debugbuilddag',
162 b'debugbuilddag',
162 [
163 [
163 (
164 (
164 b'm',
165 b'm',
165 b'mergeable-file',
166 b'mergeable-file',
166 None,
167 None,
167 _(b'add single file mergeable changes'),
168 _(b'add single file mergeable changes'),
168 ),
169 ),
169 (
170 (
170 b'o',
171 b'o',
171 b'overwritten-file',
172 b'overwritten-file',
172 None,
173 None,
173 _(b'add single file all revs overwrite'),
174 _(b'add single file all revs overwrite'),
174 ),
175 ),
175 (b'n', b'new-file', None, _(b'add new file at each rev')),
176 (b'n', b'new-file', None, _(b'add new file at each rev')),
176 ],
177 ],
177 _(b'[OPTION]... [TEXT]'),
178 _(b'[OPTION]... [TEXT]'),
178 )
179 )
179 def debugbuilddag(
180 def debugbuilddag(
180 ui,
181 ui,
181 repo,
182 repo,
182 text=None,
183 text=None,
183 mergeable_file=False,
184 mergeable_file=False,
184 overwritten_file=False,
185 overwritten_file=False,
185 new_file=False,
186 new_file=False,
186 ):
187 ):
187 """builds a repo with a given DAG from scratch in the current empty repo
188 """builds a repo with a given DAG from scratch in the current empty repo
188
189
189 The description of the DAG is read from stdin if not given on the
190 The description of the DAG is read from stdin if not given on the
190 command line.
191 command line.
191
192
192 Elements:
193 Elements:
193
194
194 - "+n" is a linear run of n nodes based on the current default parent
195 - "+n" is a linear run of n nodes based on the current default parent
195 - "." is a single node based on the current default parent
196 - "." is a single node based on the current default parent
196 - "$" resets the default parent to null (implied at the start);
197 - "$" resets the default parent to null (implied at the start);
197 otherwise the default parent is always the last node created
198 otherwise the default parent is always the last node created
198 - "<p" sets the default parent to the backref p
199 - "<p" sets the default parent to the backref p
199 - "*p" is a fork at parent p, which is a backref
200 - "*p" is a fork at parent p, which is a backref
200 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
201 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
201 - "/p2" is a merge of the preceding node and p2
202 - "/p2" is a merge of the preceding node and p2
202 - ":tag" defines a local tag for the preceding node
203 - ":tag" defines a local tag for the preceding node
203 - "@branch" sets the named branch for subsequent nodes
204 - "@branch" sets the named branch for subsequent nodes
204 - "#...\\n" is a comment up to the end of the line
205 - "#...\\n" is a comment up to the end of the line
205
206
206 Whitespace between the above elements is ignored.
207 Whitespace between the above elements is ignored.
207
208
208 A backref is either
209 A backref is either
209
210
210 - a number n, which references the node curr-n, where curr is the current
211 - a number n, which references the node curr-n, where curr is the current
211 node, or
212 node, or
212 - the name of a local tag you placed earlier using ":tag", or
213 - the name of a local tag you placed earlier using ":tag", or
213 - empty to denote the default parent.
214 - empty to denote the default parent.
214
215
215 All string valued-elements are either strictly alphanumeric, or must
216 All string valued-elements are either strictly alphanumeric, or must
216 be enclosed in double quotes ("..."), with "\\" as escape character.
217 be enclosed in double quotes ("..."), with "\\" as escape character.
217 """
218 """
218
219
219 if text is None:
220 if text is None:
220 ui.status(_(b"reading DAG from stdin\n"))
221 ui.status(_(b"reading DAG from stdin\n"))
221 text = ui.fin.read()
222 text = ui.fin.read()
222
223
223 cl = repo.changelog
224 cl = repo.changelog
224 if len(cl) > 0:
225 if len(cl) > 0:
225 raise error.Abort(_(b'repository is not empty'))
226 raise error.Abort(_(b'repository is not empty'))
226
227
227 # determine number of revs in DAG
228 # determine number of revs in DAG
228 total = 0
229 total = 0
229 for type, data in dagparser.parsedag(text):
230 for type, data in dagparser.parsedag(text):
230 if type == b'n':
231 if type == b'n':
231 total += 1
232 total += 1
232
233
233 if mergeable_file:
234 if mergeable_file:
234 linesperrev = 2
235 linesperrev = 2
235 # make a file with k lines per rev
236 # make a file with k lines per rev
236 initialmergedlines = [
237 initialmergedlines = [
237 b'%d' % i for i in pycompat.xrange(0, total * linesperrev)
238 b'%d' % i for i in pycompat.xrange(0, total * linesperrev)
238 ]
239 ]
239 initialmergedlines.append(b"")
240 initialmergedlines.append(b"")
240
241
241 tags = []
242 tags = []
242 progress = ui.makeprogress(
243 progress = ui.makeprogress(
243 _(b'building'), unit=_(b'revisions'), total=total
244 _(b'building'), unit=_(b'revisions'), total=total
244 )
245 )
245 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
246 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
246 at = -1
247 at = -1
247 atbranch = b'default'
248 atbranch = b'default'
248 nodeids = []
249 nodeids = []
249 id = 0
250 id = 0
250 progress.update(id)
251 progress.update(id)
251 for type, data in dagparser.parsedag(text):
252 for type, data in dagparser.parsedag(text):
252 if type == b'n':
253 if type == b'n':
253 ui.note((b'node %s\n' % pycompat.bytestr(data)))
254 ui.note((b'node %s\n' % pycompat.bytestr(data)))
254 id, ps = data
255 id, ps = data
255
256
256 files = []
257 files = []
257 filecontent = {}
258 filecontent = {}
258
259
259 p2 = None
260 p2 = None
260 if mergeable_file:
261 if mergeable_file:
261 fn = b"mf"
262 fn = b"mf"
262 p1 = repo[ps[0]]
263 p1 = repo[ps[0]]
263 if len(ps) > 1:
264 if len(ps) > 1:
264 p2 = repo[ps[1]]
265 p2 = repo[ps[1]]
265 pa = p1.ancestor(p2)
266 pa = p1.ancestor(p2)
266 base, local, other = [
267 base, local, other = [
267 x[fn].data() for x in (pa, p1, p2)
268 x[fn].data() for x in (pa, p1, p2)
268 ]
269 ]
269 m3 = simplemerge.Merge3Text(base, local, other)
270 m3 = simplemerge.Merge3Text(base, local, other)
270 ml = [l.strip() for l in m3.merge_lines()]
271 ml = [l.strip() for l in m3.merge_lines()]
271 ml.append(b"")
272 ml.append(b"")
272 elif at > 0:
273 elif at > 0:
273 ml = p1[fn].data().split(b"\n")
274 ml = p1[fn].data().split(b"\n")
274 else:
275 else:
275 ml = initialmergedlines
276 ml = initialmergedlines
276 ml[id * linesperrev] += b" r%i" % id
277 ml[id * linesperrev] += b" r%i" % id
277 mergedtext = b"\n".join(ml)
278 mergedtext = b"\n".join(ml)
278 files.append(fn)
279 files.append(fn)
279 filecontent[fn] = mergedtext
280 filecontent[fn] = mergedtext
280
281
281 if overwritten_file:
282 if overwritten_file:
282 fn = b"of"
283 fn = b"of"
283 files.append(fn)
284 files.append(fn)
284 filecontent[fn] = b"r%i\n" % id
285 filecontent[fn] = b"r%i\n" % id
285
286
286 if new_file:
287 if new_file:
287 fn = b"nf%i" % id
288 fn = b"nf%i" % id
288 files.append(fn)
289 files.append(fn)
289 filecontent[fn] = b"r%i\n" % id
290 filecontent[fn] = b"r%i\n" % id
290 if len(ps) > 1:
291 if len(ps) > 1:
291 if not p2:
292 if not p2:
292 p2 = repo[ps[1]]
293 p2 = repo[ps[1]]
293 for fn in p2:
294 for fn in p2:
294 if fn.startswith(b"nf"):
295 if fn.startswith(b"nf"):
295 files.append(fn)
296 files.append(fn)
296 filecontent[fn] = p2[fn].data()
297 filecontent[fn] = p2[fn].data()
297
298
298 def fctxfn(repo, cx, path):
299 def fctxfn(repo, cx, path):
299 if path in filecontent:
300 if path in filecontent:
300 return context.memfilectx(
301 return context.memfilectx(
301 repo, cx, path, filecontent[path]
302 repo, cx, path, filecontent[path]
302 )
303 )
303 return None
304 return None
304
305
305 if len(ps) == 0 or ps[0] < 0:
306 if len(ps) == 0 or ps[0] < 0:
306 pars = [None, None]
307 pars = [None, None]
307 elif len(ps) == 1:
308 elif len(ps) == 1:
308 pars = [nodeids[ps[0]], None]
309 pars = [nodeids[ps[0]], None]
309 else:
310 else:
310 pars = [nodeids[p] for p in ps]
311 pars = [nodeids[p] for p in ps]
311 cx = context.memctx(
312 cx = context.memctx(
312 repo,
313 repo,
313 pars,
314 pars,
314 b"r%i" % id,
315 b"r%i" % id,
315 files,
316 files,
316 fctxfn,
317 fctxfn,
317 date=(id, 0),
318 date=(id, 0),
318 user=b"debugbuilddag",
319 user=b"debugbuilddag",
319 extra={b'branch': atbranch},
320 extra={b'branch': atbranch},
320 )
321 )
321 nodeid = repo.commitctx(cx)
322 nodeid = repo.commitctx(cx)
322 nodeids.append(nodeid)
323 nodeids.append(nodeid)
323 at = id
324 at = id
324 elif type == b'l':
325 elif type == b'l':
325 id, name = data
326 id, name = data
326 ui.note((b'tag %s\n' % name))
327 ui.note((b'tag %s\n' % name))
327 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
328 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
328 elif type == b'a':
329 elif type == b'a':
329 ui.note((b'branch %s\n' % data))
330 ui.note((b'branch %s\n' % data))
330 atbranch = data
331 atbranch = data
331 progress.update(id)
332 progress.update(id)
332
333
333 if tags:
334 if tags:
334 repo.vfs.write(b"localtags", b"".join(tags))
335 repo.vfs.write(b"localtags", b"".join(tags))
335
336
336
337
337 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
338 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
338 indent_string = b' ' * indent
339 indent_string = b' ' * indent
339 if all:
340 if all:
340 ui.writenoi18n(
341 ui.writenoi18n(
341 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
342 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
342 % indent_string
343 % indent_string
343 )
344 )
344
345
345 def showchunks(named):
346 def showchunks(named):
346 ui.write(b"\n%s%s\n" % (indent_string, named))
347 ui.write(b"\n%s%s\n" % (indent_string, named))
347 for deltadata in gen.deltaiter():
348 for deltadata in gen.deltaiter():
348 node, p1, p2, cs, deltabase, delta, flags = deltadata
349 node, p1, p2, cs, deltabase, delta, flags = deltadata
349 ui.write(
350 ui.write(
350 b"%s%s %s %s %s %s %d\n"
351 b"%s%s %s %s %s %s %d\n"
351 % (
352 % (
352 indent_string,
353 indent_string,
353 hex(node),
354 hex(node),
354 hex(p1),
355 hex(p1),
355 hex(p2),
356 hex(p2),
356 hex(cs),
357 hex(cs),
357 hex(deltabase),
358 hex(deltabase),
358 len(delta),
359 len(delta),
359 )
360 )
360 )
361 )
361
362
362 gen.changelogheader()
363 gen.changelogheader()
363 showchunks(b"changelog")
364 showchunks(b"changelog")
364 gen.manifestheader()
365 gen.manifestheader()
365 showchunks(b"manifest")
366 showchunks(b"manifest")
366 for chunkdata in iter(gen.filelogheader, {}):
367 for chunkdata in iter(gen.filelogheader, {}):
367 fname = chunkdata[b'filename']
368 fname = chunkdata[b'filename']
368 showchunks(fname)
369 showchunks(fname)
369 else:
370 else:
370 if isinstance(gen, bundle2.unbundle20):
371 if isinstance(gen, bundle2.unbundle20):
371 raise error.Abort(_(b'use debugbundle2 for this file'))
372 raise error.Abort(_(b'use debugbundle2 for this file'))
372 gen.changelogheader()
373 gen.changelogheader()
373 for deltadata in gen.deltaiter():
374 for deltadata in gen.deltaiter():
374 node, p1, p2, cs, deltabase, delta, flags = deltadata
375 node, p1, p2, cs, deltabase, delta, flags = deltadata
375 ui.write(b"%s%s\n" % (indent_string, hex(node)))
376 ui.write(b"%s%s\n" % (indent_string, hex(node)))
376
377
377
378
378 def _debugobsmarkers(ui, part, indent=0, **opts):
379 def _debugobsmarkers(ui, part, indent=0, **opts):
379 """display version and markers contained in 'data'"""
380 """display version and markers contained in 'data'"""
380 opts = pycompat.byteskwargs(opts)
381 opts = pycompat.byteskwargs(opts)
381 data = part.read()
382 data = part.read()
382 indent_string = b' ' * indent
383 indent_string = b' ' * indent
383 try:
384 try:
384 version, markers = obsolete._readmarkers(data)
385 version, markers = obsolete._readmarkers(data)
385 except error.UnknownVersion as exc:
386 except error.UnknownVersion as exc:
386 msg = b"%sunsupported version: %s (%d bytes)\n"
387 msg = b"%sunsupported version: %s (%d bytes)\n"
387 msg %= indent_string, exc.version, len(data)
388 msg %= indent_string, exc.version, len(data)
388 ui.write(msg)
389 ui.write(msg)
389 else:
390 else:
390 msg = b"%sversion: %d (%d bytes)\n"
391 msg = b"%sversion: %d (%d bytes)\n"
391 msg %= indent_string, version, len(data)
392 msg %= indent_string, version, len(data)
392 ui.write(msg)
393 ui.write(msg)
393 fm = ui.formatter(b'debugobsolete', opts)
394 fm = ui.formatter(b'debugobsolete', opts)
394 for rawmarker in sorted(markers):
395 for rawmarker in sorted(markers):
395 m = obsutil.marker(None, rawmarker)
396 m = obsutil.marker(None, rawmarker)
396 fm.startitem()
397 fm.startitem()
397 fm.plain(indent_string)
398 fm.plain(indent_string)
398 cmdutil.showmarker(fm, m)
399 cmdutil.showmarker(fm, m)
399 fm.end()
400 fm.end()
400
401
401
402
402 def _debugphaseheads(ui, data, indent=0):
403 def _debugphaseheads(ui, data, indent=0):
403 """display version and markers contained in 'data'"""
404 """display version and markers contained in 'data'"""
404 indent_string = b' ' * indent
405 indent_string = b' ' * indent
405 headsbyphase = phases.binarydecode(data)
406 headsbyphase = phases.binarydecode(data)
406 for phase in phases.allphases:
407 for phase in phases.allphases:
407 for head in headsbyphase[phase]:
408 for head in headsbyphase[phase]:
408 ui.write(indent_string)
409 ui.write(indent_string)
409 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
410 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
410
411
411
412
412 def _quasirepr(thing):
413 def _quasirepr(thing):
413 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
414 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
414 return b'{%s}' % (
415 return b'{%s}' % (
415 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
416 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
416 )
417 )
417 return pycompat.bytestr(repr(thing))
418 return pycompat.bytestr(repr(thing))
418
419
419
420
420 def _debugbundle2(ui, gen, all=None, **opts):
421 def _debugbundle2(ui, gen, all=None, **opts):
421 """lists the contents of a bundle2"""
422 """lists the contents of a bundle2"""
422 if not isinstance(gen, bundle2.unbundle20):
423 if not isinstance(gen, bundle2.unbundle20):
423 raise error.Abort(_(b'not a bundle2 file'))
424 raise error.Abort(_(b'not a bundle2 file'))
424 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
425 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
425 parttypes = opts.get('part_type', [])
426 parttypes = opts.get('part_type', [])
426 for part in gen.iterparts():
427 for part in gen.iterparts():
427 if parttypes and part.type not in parttypes:
428 if parttypes and part.type not in parttypes:
428 continue
429 continue
429 msg = b'%s -- %s (mandatory: %r)\n'
430 msg = b'%s -- %s (mandatory: %r)\n'
430 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
431 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
431 if part.type == b'changegroup':
432 if part.type == b'changegroup':
432 version = part.params.get(b'version', b'01')
433 version = part.params.get(b'version', b'01')
433 cg = changegroup.getunbundler(version, part, b'UN')
434 cg = changegroup.getunbundler(version, part, b'UN')
434 if not ui.quiet:
435 if not ui.quiet:
435 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
436 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
436 if part.type == b'obsmarkers':
437 if part.type == b'obsmarkers':
437 if not ui.quiet:
438 if not ui.quiet:
438 _debugobsmarkers(ui, part, indent=4, **opts)
439 _debugobsmarkers(ui, part, indent=4, **opts)
439 if part.type == b'phase-heads':
440 if part.type == b'phase-heads':
440 if not ui.quiet:
441 if not ui.quiet:
441 _debugphaseheads(ui, part, indent=4)
442 _debugphaseheads(ui, part, indent=4)
442
443
443
444
444 @command(
445 @command(
445 b'debugbundle',
446 b'debugbundle',
446 [
447 [
447 (b'a', b'all', None, _(b'show all details')),
448 (b'a', b'all', None, _(b'show all details')),
448 (b'', b'part-type', [], _(b'show only the named part type')),
449 (b'', b'part-type', [], _(b'show only the named part type')),
449 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
450 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
450 ],
451 ],
451 _(b'FILE'),
452 _(b'FILE'),
452 norepo=True,
453 norepo=True,
453 )
454 )
454 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
455 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
455 """lists the contents of a bundle"""
456 """lists the contents of a bundle"""
456 with hg.openpath(ui, bundlepath) as f:
457 with hg.openpath(ui, bundlepath) as f:
457 if spec:
458 if spec:
458 spec = exchange.getbundlespec(ui, f)
459 spec = exchange.getbundlespec(ui, f)
459 ui.write(b'%s\n' % spec)
460 ui.write(b'%s\n' % spec)
460 return
461 return
461
462
462 gen = exchange.readbundle(ui, f, bundlepath)
463 gen = exchange.readbundle(ui, f, bundlepath)
463 if isinstance(gen, bundle2.unbundle20):
464 if isinstance(gen, bundle2.unbundle20):
464 return _debugbundle2(ui, gen, all=all, **opts)
465 return _debugbundle2(ui, gen, all=all, **opts)
465 _debugchangegroup(ui, gen, all=all, **opts)
466 _debugchangegroup(ui, gen, all=all, **opts)
466
467
467
468
468 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
469 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
469 def debugcapabilities(ui, path, **opts):
470 def debugcapabilities(ui, path, **opts):
470 """lists the capabilities of a remote peer"""
471 """lists the capabilities of a remote peer"""
471 opts = pycompat.byteskwargs(opts)
472 opts = pycompat.byteskwargs(opts)
472 peer = hg.peer(ui, opts, path)
473 peer = hg.peer(ui, opts, path)
473 caps = peer.capabilities()
474 caps = peer.capabilities()
474 ui.writenoi18n(b'Main capabilities:\n')
475 ui.writenoi18n(b'Main capabilities:\n')
475 for c in sorted(caps):
476 for c in sorted(caps):
476 ui.write(b' %s\n' % c)
477 ui.write(b' %s\n' % c)
477 b2caps = bundle2.bundle2caps(peer)
478 b2caps = bundle2.bundle2caps(peer)
478 if b2caps:
479 if b2caps:
479 ui.writenoi18n(b'Bundle2 capabilities:\n')
480 ui.writenoi18n(b'Bundle2 capabilities:\n')
480 for key, values in sorted(pycompat.iteritems(b2caps)):
481 for key, values in sorted(pycompat.iteritems(b2caps)):
481 ui.write(b' %s\n' % key)
482 ui.write(b' %s\n' % key)
482 for v in values:
483 for v in values:
483 ui.write(b' %s\n' % v)
484 ui.write(b' %s\n' % v)
484
485
485
486
486 @command(b'debugchangedfiles', [], b'REV')
487 @command(b'debugchangedfiles', [], b'REV')
487 def debugchangedfiles(ui, repo, rev):
488 def debugchangedfiles(ui, repo, rev):
488 """list the stored files changes for a revision"""
489 """list the stored files changes for a revision"""
489 ctx = scmutil.revsingle(repo, rev, None)
490 ctx = scmutil.revsingle(repo, rev, None)
490 sd = repo.changelog.sidedata(ctx.rev())
491 sd = repo.changelog.sidedata(ctx.rev())
491 files_block = sd.get(sidedata.SD_FILES)
492 files_block = sd.get(sidedata.SD_FILES)
492 if files_block is not None:
493 if files_block is not None:
493 files = metadata.decode_files_sidedata(sd)
494 files = metadata.decode_files_sidedata(sd)
494 for f in sorted(files.touched):
495 for f in sorted(files.touched):
495 if f in files.added:
496 if f in files.added:
496 action = b"added"
497 action = b"added"
497 elif f in files.removed:
498 elif f in files.removed:
498 action = b"removed"
499 action = b"removed"
499 elif f in files.merged:
500 elif f in files.merged:
500 action = b"merged"
501 action = b"merged"
501 elif f in files.salvaged:
502 elif f in files.salvaged:
502 action = b"salvaged"
503 action = b"salvaged"
503 else:
504 else:
504 action = b"touched"
505 action = b"touched"
505
506
506 copy_parent = b""
507 copy_parent = b""
507 copy_source = b""
508 copy_source = b""
508 if f in files.copied_from_p1:
509 if f in files.copied_from_p1:
509 copy_parent = b"p1"
510 copy_parent = b"p1"
510 copy_source = files.copied_from_p1[f]
511 copy_source = files.copied_from_p1[f]
511 elif f in files.copied_from_p2:
512 elif f in files.copied_from_p2:
512 copy_parent = b"p2"
513 copy_parent = b"p2"
513 copy_source = files.copied_from_p2[f]
514 copy_source = files.copied_from_p2[f]
514
515
515 data = (action, copy_parent, f, copy_source)
516 data = (action, copy_parent, f, copy_source)
516 template = b"%-8s %2s: %s, %s;\n"
517 template = b"%-8s %2s: %s, %s;\n"
517 ui.write(template % data)
518 ui.write(template % data)
518
519
519
520
520 @command(b'debugcheckstate', [], b'')
521 @command(b'debugcheckstate', [], b'')
521 def debugcheckstate(ui, repo):
522 def debugcheckstate(ui, repo):
522 """validate the correctness of the current dirstate"""
523 """validate the correctness of the current dirstate"""
523 parent1, parent2 = repo.dirstate.parents()
524 parent1, parent2 = repo.dirstate.parents()
524 m1 = repo[parent1].manifest()
525 m1 = repo[parent1].manifest()
525 m2 = repo[parent2].manifest()
526 m2 = repo[parent2].manifest()
526 errors = 0
527 errors = 0
527 for f in repo.dirstate:
528 for f in repo.dirstate:
528 state = repo.dirstate[f]
529 state = repo.dirstate[f]
529 if state in b"nr" and f not in m1:
530 if state in b"nr" and f not in m1:
530 ui.warn(_(b"%s in state %s, but not in manifest1\n") % (f, state))
531 ui.warn(_(b"%s in state %s, but not in manifest1\n") % (f, state))
531 errors += 1
532 errors += 1
532 if state in b"a" and f in m1:
533 if state in b"a" and f in m1:
533 ui.warn(_(b"%s in state %s, but also in manifest1\n") % (f, state))
534 ui.warn(_(b"%s in state %s, but also in manifest1\n") % (f, state))
534 errors += 1
535 errors += 1
535 if state in b"m" and f not in m1 and f not in m2:
536 if state in b"m" and f not in m1 and f not in m2:
536 ui.warn(
537 ui.warn(
537 _(b"%s in state %s, but not in either manifest\n") % (f, state)
538 _(b"%s in state %s, but not in either manifest\n") % (f, state)
538 )
539 )
539 errors += 1
540 errors += 1
540 for f in m1:
541 for f in m1:
541 state = repo.dirstate[f]
542 state = repo.dirstate[f]
542 if state not in b"nrm":
543 if state not in b"nrm":
543 ui.warn(_(b"%s in manifest1, but listed as state %s") % (f, state))
544 ui.warn(_(b"%s in manifest1, but listed as state %s") % (f, state))
544 errors += 1
545 errors += 1
545 if errors:
546 if errors:
546 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
547 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
547 raise error.Abort(errstr)
548 raise error.Abort(errstr)
548
549
549
550
550 @command(
551 @command(
551 b'debugcolor',
552 b'debugcolor',
552 [(b'', b'style', None, _(b'show all configured styles'))],
553 [(b'', b'style', None, _(b'show all configured styles'))],
553 b'hg debugcolor',
554 b'hg debugcolor',
554 )
555 )
555 def debugcolor(ui, repo, **opts):
556 def debugcolor(ui, repo, **opts):
556 """show available color, effects or style"""
557 """show available color, effects or style"""
557 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
558 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
558 if opts.get('style'):
559 if opts.get('style'):
559 return _debugdisplaystyle(ui)
560 return _debugdisplaystyle(ui)
560 else:
561 else:
561 return _debugdisplaycolor(ui)
562 return _debugdisplaycolor(ui)
562
563
563
564
564 def _debugdisplaycolor(ui):
565 def _debugdisplaycolor(ui):
565 ui = ui.copy()
566 ui = ui.copy()
566 ui._styles.clear()
567 ui._styles.clear()
567 for effect in color._activeeffects(ui).keys():
568 for effect in color._activeeffects(ui).keys():
568 ui._styles[effect] = effect
569 ui._styles[effect] = effect
569 if ui._terminfoparams:
570 if ui._terminfoparams:
570 for k, v in ui.configitems(b'color'):
571 for k, v in ui.configitems(b'color'):
571 if k.startswith(b'color.'):
572 if k.startswith(b'color.'):
572 ui._styles[k] = k[6:]
573 ui._styles[k] = k[6:]
573 elif k.startswith(b'terminfo.'):
574 elif k.startswith(b'terminfo.'):
574 ui._styles[k] = k[9:]
575 ui._styles[k] = k[9:]
575 ui.write(_(b'available colors:\n'))
576 ui.write(_(b'available colors:\n'))
576 # sort label with a '_' after the other to group '_background' entry.
577 # sort label with a '_' after the other to group '_background' entry.
577 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
578 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
578 for colorname, label in items:
579 for colorname, label in items:
579 ui.write(b'%s\n' % colorname, label=label)
580 ui.write(b'%s\n' % colorname, label=label)
580
581
581
582
582 def _debugdisplaystyle(ui):
583 def _debugdisplaystyle(ui):
583 ui.write(_(b'available style:\n'))
584 ui.write(_(b'available style:\n'))
584 if not ui._styles:
585 if not ui._styles:
585 return
586 return
586 width = max(len(s) for s in ui._styles)
587 width = max(len(s) for s in ui._styles)
587 for label, effects in sorted(ui._styles.items()):
588 for label, effects in sorted(ui._styles.items()):
588 ui.write(b'%s' % label, label=label)
589 ui.write(b'%s' % label, label=label)
589 if effects:
590 if effects:
590 # 50
591 # 50
591 ui.write(b': ')
592 ui.write(b': ')
592 ui.write(b' ' * (max(0, width - len(label))))
593 ui.write(b' ' * (max(0, width - len(label))))
593 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
594 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
594 ui.write(b'\n')
595 ui.write(b'\n')
595
596
596
597
597 @command(b'debugcreatestreamclonebundle', [], b'FILE')
598 @command(b'debugcreatestreamclonebundle', [], b'FILE')
598 def debugcreatestreamclonebundle(ui, repo, fname):
599 def debugcreatestreamclonebundle(ui, repo, fname):
599 """create a stream clone bundle file
600 """create a stream clone bundle file
600
601
601 Stream bundles are special bundles that are essentially archives of
602 Stream bundles are special bundles that are essentially archives of
602 revlog files. They are commonly used for cloning very quickly.
603 revlog files. They are commonly used for cloning very quickly.
603 """
604 """
604 # TODO we may want to turn this into an abort when this functionality
605 # TODO we may want to turn this into an abort when this functionality
605 # is moved into `hg bundle`.
606 # is moved into `hg bundle`.
606 if phases.hassecret(repo):
607 if phases.hassecret(repo):
607 ui.warn(
608 ui.warn(
608 _(
609 _(
609 b'(warning: stream clone bundle will contain secret '
610 b'(warning: stream clone bundle will contain secret '
610 b'revisions)\n'
611 b'revisions)\n'
611 )
612 )
612 )
613 )
613
614
614 requirements, gen = streamclone.generatebundlev1(repo)
615 requirements, gen = streamclone.generatebundlev1(repo)
615 changegroup.writechunks(ui, gen, fname)
616 changegroup.writechunks(ui, gen, fname)
616
617
617 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
618 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
618
619
619
620
620 @command(
621 @command(
621 b'debugdag',
622 b'debugdag',
622 [
623 [
623 (b't', b'tags', None, _(b'use tags as labels')),
624 (b't', b'tags', None, _(b'use tags as labels')),
624 (b'b', b'branches', None, _(b'annotate with branch names')),
625 (b'b', b'branches', None, _(b'annotate with branch names')),
625 (b'', b'dots', None, _(b'use dots for runs')),
626 (b'', b'dots', None, _(b'use dots for runs')),
626 (b's', b'spaces', None, _(b'separate elements by spaces')),
627 (b's', b'spaces', None, _(b'separate elements by spaces')),
627 ],
628 ],
628 _(b'[OPTION]... [FILE [REV]...]'),
629 _(b'[OPTION]... [FILE [REV]...]'),
629 optionalrepo=True,
630 optionalrepo=True,
630 )
631 )
631 def debugdag(ui, repo, file_=None, *revs, **opts):
632 def debugdag(ui, repo, file_=None, *revs, **opts):
632 """format the changelog or an index DAG as a concise textual description
633 """format the changelog or an index DAG as a concise textual description
633
634
634 If you pass a revlog index, the revlog's DAG is emitted. If you list
635 If you pass a revlog index, the revlog's DAG is emitted. If you list
635 revision numbers, they get labeled in the output as rN.
636 revision numbers, they get labeled in the output as rN.
636
637
637 Otherwise, the changelog DAG of the current repo is emitted.
638 Otherwise, the changelog DAG of the current repo is emitted.
638 """
639 """
639 spaces = opts.get('spaces')
640 spaces = opts.get('spaces')
640 dots = opts.get('dots')
641 dots = opts.get('dots')
641 if file_:
642 if file_:
642 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
643 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
643 revs = {int(r) for r in revs}
644 revs = {int(r) for r in revs}
644
645
645 def events():
646 def events():
646 for r in rlog:
647 for r in rlog:
647 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
648 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
648 if r in revs:
649 if r in revs:
649 yield b'l', (r, b"r%i" % r)
650 yield b'l', (r, b"r%i" % r)
650
651
651 elif repo:
652 elif repo:
652 cl = repo.changelog
653 cl = repo.changelog
653 tags = opts.get('tags')
654 tags = opts.get('tags')
654 branches = opts.get('branches')
655 branches = opts.get('branches')
655 if tags:
656 if tags:
656 labels = {}
657 labels = {}
657 for l, n in repo.tags().items():
658 for l, n in repo.tags().items():
658 labels.setdefault(cl.rev(n), []).append(l)
659 labels.setdefault(cl.rev(n), []).append(l)
659
660
660 def events():
661 def events():
661 b = b"default"
662 b = b"default"
662 for r in cl:
663 for r in cl:
663 if branches:
664 if branches:
664 newb = cl.read(cl.node(r))[5][b'branch']
665 newb = cl.read(cl.node(r))[5][b'branch']
665 if newb != b:
666 if newb != b:
666 yield b'a', newb
667 yield b'a', newb
667 b = newb
668 b = newb
668 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
669 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
669 if tags:
670 if tags:
670 ls = labels.get(r)
671 ls = labels.get(r)
671 if ls:
672 if ls:
672 for l in ls:
673 for l in ls:
673 yield b'l', (r, l)
674 yield b'l', (r, l)
674
675
675 else:
676 else:
676 raise error.Abort(_(b'need repo for changelog dag'))
677 raise error.Abort(_(b'need repo for changelog dag'))
677
678
678 for line in dagparser.dagtextlines(
679 for line in dagparser.dagtextlines(
679 events(),
680 events(),
680 addspaces=spaces,
681 addspaces=spaces,
681 wraplabels=True,
682 wraplabels=True,
682 wrapannotations=True,
683 wrapannotations=True,
683 wrapnonlinear=dots,
684 wrapnonlinear=dots,
684 usedots=dots,
685 usedots=dots,
685 maxlinewidth=70,
686 maxlinewidth=70,
686 ):
687 ):
687 ui.write(line)
688 ui.write(line)
688 ui.write(b"\n")
689 ui.write(b"\n")
689
690
690
691
691 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
692 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
692 def debugdata(ui, repo, file_, rev=None, **opts):
693 def debugdata(ui, repo, file_, rev=None, **opts):
693 """dump the contents of a data file revision"""
694 """dump the contents of a data file revision"""
694 opts = pycompat.byteskwargs(opts)
695 opts = pycompat.byteskwargs(opts)
695 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
696 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
696 if rev is not None:
697 if rev is not None:
697 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
698 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
698 file_, rev = None, file_
699 file_, rev = None, file_
699 elif rev is None:
700 elif rev is None:
700 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
701 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
701 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
702 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
702 try:
703 try:
703 ui.write(r.rawdata(r.lookup(rev)))
704 ui.write(r.rawdata(r.lookup(rev)))
704 except KeyError:
705 except KeyError:
705 raise error.Abort(_(b'invalid revision identifier %s') % rev)
706 raise error.Abort(_(b'invalid revision identifier %s') % rev)
706
707
707
708
708 @command(
709 @command(
709 b'debugdate',
710 b'debugdate',
710 [(b'e', b'extended', None, _(b'try extended date formats'))],
711 [(b'e', b'extended', None, _(b'try extended date formats'))],
711 _(b'[-e] DATE [RANGE]'),
712 _(b'[-e] DATE [RANGE]'),
712 norepo=True,
713 norepo=True,
713 optionalrepo=True,
714 optionalrepo=True,
714 )
715 )
715 def debugdate(ui, date, range=None, **opts):
716 def debugdate(ui, date, range=None, **opts):
716 """parse and display a date"""
717 """parse and display a date"""
717 if opts["extended"]:
718 if opts["extended"]:
718 d = dateutil.parsedate(date, dateutil.extendeddateformats)
719 d = dateutil.parsedate(date, dateutil.extendeddateformats)
719 else:
720 else:
720 d = dateutil.parsedate(date)
721 d = dateutil.parsedate(date)
721 ui.writenoi18n(b"internal: %d %d\n" % d)
722 ui.writenoi18n(b"internal: %d %d\n" % d)
722 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
723 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
723 if range:
724 if range:
724 m = dateutil.matchdate(range)
725 m = dateutil.matchdate(range)
725 ui.writenoi18n(b"match: %s\n" % m(d[0]))
726 ui.writenoi18n(b"match: %s\n" % m(d[0]))
726
727
727
728
728 @command(
729 @command(
729 b'debugdeltachain',
730 b'debugdeltachain',
730 cmdutil.debugrevlogopts + cmdutil.formatteropts,
731 cmdutil.debugrevlogopts + cmdutil.formatteropts,
731 _(b'-c|-m|FILE'),
732 _(b'-c|-m|FILE'),
732 optionalrepo=True,
733 optionalrepo=True,
733 )
734 )
734 def debugdeltachain(ui, repo, file_=None, **opts):
735 def debugdeltachain(ui, repo, file_=None, **opts):
735 """dump information about delta chains in a revlog
736 """dump information about delta chains in a revlog
736
737
737 Output can be templatized. Available template keywords are:
738 Output can be templatized. Available template keywords are:
738
739
739 :``rev``: revision number
740 :``rev``: revision number
740 :``chainid``: delta chain identifier (numbered by unique base)
741 :``chainid``: delta chain identifier (numbered by unique base)
741 :``chainlen``: delta chain length to this revision
742 :``chainlen``: delta chain length to this revision
742 :``prevrev``: previous revision in delta chain
743 :``prevrev``: previous revision in delta chain
743 :``deltatype``: role of delta / how it was computed
744 :``deltatype``: role of delta / how it was computed
744 :``compsize``: compressed size of revision
745 :``compsize``: compressed size of revision
745 :``uncompsize``: uncompressed size of revision
746 :``uncompsize``: uncompressed size of revision
746 :``chainsize``: total size of compressed revisions in chain
747 :``chainsize``: total size of compressed revisions in chain
747 :``chainratio``: total chain size divided by uncompressed revision size
748 :``chainratio``: total chain size divided by uncompressed revision size
748 (new delta chains typically start at ratio 2.00)
749 (new delta chains typically start at ratio 2.00)
749 :``lindist``: linear distance from base revision in delta chain to end
750 :``lindist``: linear distance from base revision in delta chain to end
750 of this revision
751 of this revision
751 :``extradist``: total size of revisions not part of this delta chain from
752 :``extradist``: total size of revisions not part of this delta chain from
752 base of delta chain to end of this revision; a measurement
753 base of delta chain to end of this revision; a measurement
753 of how much extra data we need to read/seek across to read
754 of how much extra data we need to read/seek across to read
754 the delta chain for this revision
755 the delta chain for this revision
755 :``extraratio``: extradist divided by chainsize; another representation of
756 :``extraratio``: extradist divided by chainsize; another representation of
756 how much unrelated data is needed to load this delta chain
757 how much unrelated data is needed to load this delta chain
757
758
758 If the repository is configured to use the sparse read, additional keywords
759 If the repository is configured to use the sparse read, additional keywords
759 are available:
760 are available:
760
761
761 :``readsize``: total size of data read from the disk for a revision
762 :``readsize``: total size of data read from the disk for a revision
762 (sum of the sizes of all the blocks)
763 (sum of the sizes of all the blocks)
763 :``largestblock``: size of the largest block of data read from the disk
764 :``largestblock``: size of the largest block of data read from the disk
764 :``readdensity``: density of useful bytes in the data read from the disk
765 :``readdensity``: density of useful bytes in the data read from the disk
765 :``srchunks``: in how many data hunks the whole revision would be read
766 :``srchunks``: in how many data hunks the whole revision would be read
766
767
767 The sparse read can be enabled with experimental.sparse-read = True
768 The sparse read can be enabled with experimental.sparse-read = True
768 """
769 """
769 opts = pycompat.byteskwargs(opts)
770 opts = pycompat.byteskwargs(opts)
770 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
771 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
771 index = r.index
772 index = r.index
772 start = r.start
773 start = r.start
773 length = r.length
774 length = r.length
774 generaldelta = r.version & revlog.FLAG_GENERALDELTA
775 generaldelta = r.version & revlog.FLAG_GENERALDELTA
775 withsparseread = getattr(r, '_withsparseread', False)
776 withsparseread = getattr(r, '_withsparseread', False)
776
777
777 def revinfo(rev):
778 def revinfo(rev):
778 e = index[rev]
779 e = index[rev]
779 compsize = e[1]
780 compsize = e[1]
780 uncompsize = e[2]
781 uncompsize = e[2]
781 chainsize = 0
782 chainsize = 0
782
783
783 if generaldelta:
784 if generaldelta:
784 if e[3] == e[5]:
785 if e[3] == e[5]:
785 deltatype = b'p1'
786 deltatype = b'p1'
786 elif e[3] == e[6]:
787 elif e[3] == e[6]:
787 deltatype = b'p2'
788 deltatype = b'p2'
788 elif e[3] == rev - 1:
789 elif e[3] == rev - 1:
789 deltatype = b'prev'
790 deltatype = b'prev'
790 elif e[3] == rev:
791 elif e[3] == rev:
791 deltatype = b'base'
792 deltatype = b'base'
792 else:
793 else:
793 deltatype = b'other'
794 deltatype = b'other'
794 else:
795 else:
795 if e[3] == rev:
796 if e[3] == rev:
796 deltatype = b'base'
797 deltatype = b'base'
797 else:
798 else:
798 deltatype = b'prev'
799 deltatype = b'prev'
799
800
800 chain = r._deltachain(rev)[0]
801 chain = r._deltachain(rev)[0]
801 for iterrev in chain:
802 for iterrev in chain:
802 e = index[iterrev]
803 e = index[iterrev]
803 chainsize += e[1]
804 chainsize += e[1]
804
805
805 return compsize, uncompsize, deltatype, chain, chainsize
806 return compsize, uncompsize, deltatype, chain, chainsize
806
807
807 fm = ui.formatter(b'debugdeltachain', opts)
808 fm = ui.formatter(b'debugdeltachain', opts)
808
809
809 fm.plain(
810 fm.plain(
810 b' rev chain# chainlen prev delta '
811 b' rev chain# chainlen prev delta '
811 b'size rawsize chainsize ratio lindist extradist '
812 b'size rawsize chainsize ratio lindist extradist '
812 b'extraratio'
813 b'extraratio'
813 )
814 )
814 if withsparseread:
815 if withsparseread:
815 fm.plain(b' readsize largestblk rddensity srchunks')
816 fm.plain(b' readsize largestblk rddensity srchunks')
816 fm.plain(b'\n')
817 fm.plain(b'\n')
817
818
818 chainbases = {}
819 chainbases = {}
819 for rev in r:
820 for rev in r:
820 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
821 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
821 chainbase = chain[0]
822 chainbase = chain[0]
822 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
823 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
823 basestart = start(chainbase)
824 basestart = start(chainbase)
824 revstart = start(rev)
825 revstart = start(rev)
825 lineardist = revstart + comp - basestart
826 lineardist = revstart + comp - basestart
826 extradist = lineardist - chainsize
827 extradist = lineardist - chainsize
827 try:
828 try:
828 prevrev = chain[-2]
829 prevrev = chain[-2]
829 except IndexError:
830 except IndexError:
830 prevrev = -1
831 prevrev = -1
831
832
832 if uncomp != 0:
833 if uncomp != 0:
833 chainratio = float(chainsize) / float(uncomp)
834 chainratio = float(chainsize) / float(uncomp)
834 else:
835 else:
835 chainratio = chainsize
836 chainratio = chainsize
836
837
837 if chainsize != 0:
838 if chainsize != 0:
838 extraratio = float(extradist) / float(chainsize)
839 extraratio = float(extradist) / float(chainsize)
839 else:
840 else:
840 extraratio = extradist
841 extraratio = extradist
841
842
842 fm.startitem()
843 fm.startitem()
843 fm.write(
844 fm.write(
844 b'rev chainid chainlen prevrev deltatype compsize '
845 b'rev chainid chainlen prevrev deltatype compsize '
845 b'uncompsize chainsize chainratio lindist extradist '
846 b'uncompsize chainsize chainratio lindist extradist '
846 b'extraratio',
847 b'extraratio',
847 b'%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
848 b'%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
848 rev,
849 rev,
849 chainid,
850 chainid,
850 len(chain),
851 len(chain),
851 prevrev,
852 prevrev,
852 deltatype,
853 deltatype,
853 comp,
854 comp,
854 uncomp,
855 uncomp,
855 chainsize,
856 chainsize,
856 chainratio,
857 chainratio,
857 lineardist,
858 lineardist,
858 extradist,
859 extradist,
859 extraratio,
860 extraratio,
860 rev=rev,
861 rev=rev,
861 chainid=chainid,
862 chainid=chainid,
862 chainlen=len(chain),
863 chainlen=len(chain),
863 prevrev=prevrev,
864 prevrev=prevrev,
864 deltatype=deltatype,
865 deltatype=deltatype,
865 compsize=comp,
866 compsize=comp,
866 uncompsize=uncomp,
867 uncompsize=uncomp,
867 chainsize=chainsize,
868 chainsize=chainsize,
868 chainratio=chainratio,
869 chainratio=chainratio,
869 lindist=lineardist,
870 lindist=lineardist,
870 extradist=extradist,
871 extradist=extradist,
871 extraratio=extraratio,
872 extraratio=extraratio,
872 )
873 )
873 if withsparseread:
874 if withsparseread:
874 readsize = 0
875 readsize = 0
875 largestblock = 0
876 largestblock = 0
876 srchunks = 0
877 srchunks = 0
877
878
878 for revschunk in deltautil.slicechunk(r, chain):
879 for revschunk in deltautil.slicechunk(r, chain):
879 srchunks += 1
880 srchunks += 1
880 blkend = start(revschunk[-1]) + length(revschunk[-1])
881 blkend = start(revschunk[-1]) + length(revschunk[-1])
881 blksize = blkend - start(revschunk[0])
882 blksize = blkend - start(revschunk[0])
882
883
883 readsize += blksize
884 readsize += blksize
884 if largestblock < blksize:
885 if largestblock < blksize:
885 largestblock = blksize
886 largestblock = blksize
886
887
887 if readsize:
888 if readsize:
888 readdensity = float(chainsize) / float(readsize)
889 readdensity = float(chainsize) / float(readsize)
889 else:
890 else:
890 readdensity = 1
891 readdensity = 1
891
892
892 fm.write(
893 fm.write(
893 b'readsize largestblock readdensity srchunks',
894 b'readsize largestblock readdensity srchunks',
894 b' %10d %10d %9.5f %8d',
895 b' %10d %10d %9.5f %8d',
895 readsize,
896 readsize,
896 largestblock,
897 largestblock,
897 readdensity,
898 readdensity,
898 srchunks,
899 srchunks,
899 readsize=readsize,
900 readsize=readsize,
900 largestblock=largestblock,
901 largestblock=largestblock,
901 readdensity=readdensity,
902 readdensity=readdensity,
902 srchunks=srchunks,
903 srchunks=srchunks,
903 )
904 )
904
905
905 fm.plain(b'\n')
906 fm.plain(b'\n')
906
907
907 fm.end()
908 fm.end()
908
909
909
910
910 @command(
911 @command(
911 b'debugdirstate|debugstate',
912 b'debugdirstate|debugstate',
912 [
913 [
913 (
914 (
914 b'',
915 b'',
915 b'nodates',
916 b'nodates',
916 None,
917 None,
917 _(b'do not display the saved mtime (DEPRECATED)'),
918 _(b'do not display the saved mtime (DEPRECATED)'),
918 ),
919 ),
919 (b'', b'dates', True, _(b'display the saved mtime')),
920 (b'', b'dates', True, _(b'display the saved mtime')),
920 (b'', b'datesort', None, _(b'sort by saved mtime')),
921 (b'', b'datesort', None, _(b'sort by saved mtime')),
921 ],
922 ],
922 _(b'[OPTION]...'),
923 _(b'[OPTION]...'),
923 )
924 )
924 def debugstate(ui, repo, **opts):
925 def debugstate(ui, repo, **opts):
925 """show the contents of the current dirstate"""
926 """show the contents of the current dirstate"""
926
927
927 nodates = not opts['dates']
928 nodates = not opts['dates']
928 if opts.get('nodates') is not None:
929 if opts.get('nodates') is not None:
929 nodates = True
930 nodates = True
930 datesort = opts.get('datesort')
931 datesort = opts.get('datesort')
931
932
932 if datesort:
933 if datesort:
933 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
934 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
934 else:
935 else:
935 keyfunc = None # sort by filename
936 keyfunc = None # sort by filename
936 for file_, ent in sorted(pycompat.iteritems(repo.dirstate), key=keyfunc):
937 for file_, ent in sorted(pycompat.iteritems(repo.dirstate), key=keyfunc):
937 if ent[3] == -1:
938 if ent[3] == -1:
938 timestr = b'unset '
939 timestr = b'unset '
939 elif nodates:
940 elif nodates:
940 timestr = b'set '
941 timestr = b'set '
941 else:
942 else:
942 timestr = time.strftime(
943 timestr = time.strftime(
943 "%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
944 "%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
944 )
945 )
945 timestr = encoding.strtolocal(timestr)
946 timestr = encoding.strtolocal(timestr)
946 if ent[1] & 0o20000:
947 if ent[1] & 0o20000:
947 mode = b'lnk'
948 mode = b'lnk'
948 else:
949 else:
949 mode = b'%3o' % (ent[1] & 0o777 & ~util.umask)
950 mode = b'%3o' % (ent[1] & 0o777 & ~util.umask)
950 ui.write(b"%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
951 ui.write(b"%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
951 for f in repo.dirstate.copies():
952 for f in repo.dirstate.copies():
952 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
953 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
953
954
954
955
955 @command(
956 @command(
956 b'debugdiscovery',
957 b'debugdiscovery',
957 [
958 [
958 (b'', b'old', None, _(b'use old-style discovery')),
959 (b'', b'old', None, _(b'use old-style discovery')),
959 (
960 (
960 b'',
961 b'',
961 b'nonheads',
962 b'nonheads',
962 None,
963 None,
963 _(b'use old-style discovery with non-heads included'),
964 _(b'use old-style discovery with non-heads included'),
964 ),
965 ),
965 (b'', b'rev', [], b'restrict discovery to this set of revs'),
966 (b'', b'rev', [], b'restrict discovery to this set of revs'),
966 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
967 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
968 (
969 b'',
970 b'local-as-revs',
971 "",
972 'treat local has having these revisions only',
973 ),
974 (
975 b'',
976 b'remote-as-revs',
977 "",
978 'use local as remote, with only these these revisions',
979 ),
967 ]
980 ]
968 + cmdutil.remoteopts,
981 + cmdutil.remoteopts,
969 _(b'[--rev REV] [OTHER]'),
982 _(b'[--rev REV] [OTHER]'),
970 )
983 )
971 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
984 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
972 """runs the changeset discovery protocol in isolation"""
985 """runs the changeset discovery protocol in isolation
986
987 The local peer can be "replaced" by a subset of the local repository by
988 using the `--local-as-revs` flag. Int he same way, usual `remote` peer can
989 be "replaced" by a subset of the local repository using the
990 `--local-as-revs` flag. This is useful to efficiently debug pathological
991 discovery situation.
992 """
973 opts = pycompat.byteskwargs(opts)
993 opts = pycompat.byteskwargs(opts)
974 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
994 unfi = repo.unfiltered()
975 remote = hg.peer(repo, opts, remoteurl)
995
976 ui.status(_(b'comparing with %s\n') % util.hidepassword(remoteurl))
996 # setup potential extra filtering
997 local_revs = opts[b"local_as_revs"]
998 remote_revs = opts[b"remote_as_revs"]
977
999
978 # make sure tests are repeatable
1000 # make sure tests are repeatable
979 random.seed(int(opts[b'seed']))
1001 random.seed(int(opts[b'seed']))
980
1002
1003 if not remote_revs:
1004
1005 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
1006 remote = hg.peer(repo, opts, remoteurl)
1007 ui.status(_(b'comparing with %s\n') % util.hidepassword(remoteurl))
1008 else:
1009 branches = (None, [])
1010 remote_filtered_revs = scmutil.revrange(
1011 unfi, [b"not (::(%s))" % remote_revs]
1012 )
1013 remote_filtered_revs = frozenset(remote_filtered_revs)
1014
1015 def remote_func(x):
1016 return remote_filtered_revs
1017
1018 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1019
1020 remote = repo.peer()
1021 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1022
1023 if local_revs:
1024 local_filtered_revs = scmutil.revrange(
1025 unfi, [b"not (::(%s))" % local_revs]
1026 )
1027 local_filtered_revs = frozenset(local_filtered_revs)
1028
1029 def local_func(x):
1030 return local_filtered_revs
1031
1032 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1033 repo = repo.filtered(b'debug-discovery-local-filter')
1034
981 data = {}
1035 data = {}
982 if opts.get(b'old'):
1036 if opts.get(b'old'):
983
1037
984 def doit(pushedrevs, remoteheads, remote=remote):
1038 def doit(pushedrevs, remoteheads, remote=remote):
985 if not util.safehasattr(remote, b'branches'):
1039 if not util.safehasattr(remote, b'branches'):
986 # enable in-client legacy support
1040 # enable in-client legacy support
987 remote = localrepo.locallegacypeer(remote.local())
1041 remote = localrepo.locallegacypeer(remote.local())
988 common, _in, hds = treediscovery.findcommonincoming(
1042 common, _in, hds = treediscovery.findcommonincoming(
989 repo, remote, force=True, audit=data
1043 repo, remote, force=True, audit=data
990 )
1044 )
991 common = set(common)
1045 common = set(common)
992 if not opts.get(b'nonheads'):
1046 if not opts.get(b'nonheads'):
993 ui.writenoi18n(
1047 ui.writenoi18n(
994 b"unpruned common: %s\n"
1048 b"unpruned common: %s\n"
995 % b" ".join(sorted(short(n) for n in common))
1049 % b" ".join(sorted(short(n) for n in common))
996 )
1050 )
997
1051
998 clnode = repo.changelog.node
1052 clnode = repo.changelog.node
999 common = repo.revs(b'heads(::%ln)', common)
1053 common = repo.revs(b'heads(::%ln)', common)
1000 common = {clnode(r) for r in common}
1054 common = {clnode(r) for r in common}
1001 return common, hds
1055 return common, hds
1002
1056
1003 else:
1057 else:
1004
1058
1005 def doit(pushedrevs, remoteheads, remote=remote):
1059 def doit(pushedrevs, remoteheads, remote=remote):
1006 nodes = None
1060 nodes = None
1007 if pushedrevs:
1061 if pushedrevs:
1008 revs = scmutil.revrange(repo, pushedrevs)
1062 revs = scmutil.revrange(repo, pushedrevs)
1009 nodes = [repo[r].node() for r in revs]
1063 nodes = [repo[r].node() for r in revs]
1010 common, any, hds = setdiscovery.findcommonheads(
1064 common, any, hds = setdiscovery.findcommonheads(
1011 ui, repo, remote, ancestorsof=nodes, audit=data
1065 ui, repo, remote, ancestorsof=nodes, audit=data
1012 )
1066 )
1013 return common, hds
1067 return common, hds
1014
1068
1015 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1069 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1016 localrevs = opts[b'rev']
1070 localrevs = opts[b'rev']
1017 with util.timedcm('debug-discovery') as t:
1071 with util.timedcm('debug-discovery') as t:
1018 common, hds = doit(localrevs, remoterevs)
1072 common, hds = doit(localrevs, remoterevs)
1019
1073
1020 # compute all statistics
1074 # compute all statistics
1021 heads_common = set(common)
1075 heads_common = set(common)
1022 heads_remote = set(hds)
1076 heads_remote = set(hds)
1023 heads_local = set(repo.heads())
1077 heads_local = set(repo.heads())
1024 # note: they cannot be a local or remote head that is in common and not
1078 # note: they cannot be a local or remote head that is in common and not
1025 # itself a head of common.
1079 # itself a head of common.
1026 heads_common_local = heads_common & heads_local
1080 heads_common_local = heads_common & heads_local
1027 heads_common_remote = heads_common & heads_remote
1081 heads_common_remote = heads_common & heads_remote
1028 heads_common_both = heads_common & heads_remote & heads_local
1082 heads_common_both = heads_common & heads_remote & heads_local
1029
1083
1030 all = repo.revs(b'all()')
1084 all = repo.revs(b'all()')
1031 common = repo.revs(b'::%ln', common)
1085 common = repo.revs(b'::%ln', common)
1032 roots_common = repo.revs(b'roots(::%ld)', common)
1086 roots_common = repo.revs(b'roots(::%ld)', common)
1033 missing = repo.revs(b'not ::%ld', common)
1087 missing = repo.revs(b'not ::%ld', common)
1034 heads_missing = repo.revs(b'heads(%ld)', missing)
1088 heads_missing = repo.revs(b'heads(%ld)', missing)
1035 roots_missing = repo.revs(b'roots(%ld)', missing)
1089 roots_missing = repo.revs(b'roots(%ld)', missing)
1036 assert len(common) + len(missing) == len(all)
1090 assert len(common) + len(missing) == len(all)
1037
1091
1038 initial_undecided = repo.revs(
1092 initial_undecided = repo.revs(
1039 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1093 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1040 )
1094 )
1041 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1095 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1042 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1096 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1043 common_initial_undecided = initial_undecided & common
1097 common_initial_undecided = initial_undecided & common
1044 missing_initial_undecided = initial_undecided & missing
1098 missing_initial_undecided = initial_undecided & missing
1045
1099
1046 data[b'elapsed'] = t.elapsed
1100 data[b'elapsed'] = t.elapsed
1047 data[b'nb-common-heads'] = len(heads_common)
1101 data[b'nb-common-heads'] = len(heads_common)
1048 data[b'nb-common-heads-local'] = len(heads_common_local)
1102 data[b'nb-common-heads-local'] = len(heads_common_local)
1049 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1103 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1050 data[b'nb-common-heads-both'] = len(heads_common_both)
1104 data[b'nb-common-heads-both'] = len(heads_common_both)
1051 data[b'nb-common-roots'] = len(roots_common)
1105 data[b'nb-common-roots'] = len(roots_common)
1052 data[b'nb-head-local'] = len(heads_local)
1106 data[b'nb-head-local'] = len(heads_local)
1053 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1107 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1054 data[b'nb-head-remote'] = len(heads_remote)
1108 data[b'nb-head-remote'] = len(heads_remote)
1055 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1109 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1056 heads_common_remote
1110 heads_common_remote
1057 )
1111 )
1058 data[b'nb-revs'] = len(all)
1112 data[b'nb-revs'] = len(all)
1059 data[b'nb-revs-common'] = len(common)
1113 data[b'nb-revs-common'] = len(common)
1060 data[b'nb-revs-missing'] = len(missing)
1114 data[b'nb-revs-missing'] = len(missing)
1061 data[b'nb-missing-heads'] = len(heads_missing)
1115 data[b'nb-missing-heads'] = len(heads_missing)
1062 data[b'nb-missing-roots'] = len(roots_missing)
1116 data[b'nb-missing-roots'] = len(roots_missing)
1063 data[b'nb-ini_und'] = len(initial_undecided)
1117 data[b'nb-ini_und'] = len(initial_undecided)
1064 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1118 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1065 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1119 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1066 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1120 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1067 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1121 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1068
1122
1069 # display discovery summary
1123 # display discovery summary
1070 ui.writenoi18n(b"elapsed time: %(elapsed)f seconds\n" % data)
1124 ui.writenoi18n(b"elapsed time: %(elapsed)f seconds\n" % data)
1071 ui.writenoi18n(b"round-trips: %(total-roundtrips)9d\n" % data)
1125 ui.writenoi18n(b"round-trips: %(total-roundtrips)9d\n" % data)
1072 ui.writenoi18n(b"heads summary:\n")
1126 ui.writenoi18n(b"heads summary:\n")
1073 ui.writenoi18n(b" total common heads: %(nb-common-heads)9d\n" % data)
1127 ui.writenoi18n(b" total common heads: %(nb-common-heads)9d\n" % data)
1074 ui.writenoi18n(
1128 ui.writenoi18n(
1075 b" also local heads: %(nb-common-heads-local)9d\n" % data
1129 b" also local heads: %(nb-common-heads-local)9d\n" % data
1076 )
1130 )
1077 ui.writenoi18n(
1131 ui.writenoi18n(
1078 b" also remote heads: %(nb-common-heads-remote)9d\n" % data
1132 b" also remote heads: %(nb-common-heads-remote)9d\n" % data
1079 )
1133 )
1080 ui.writenoi18n(b" both: %(nb-common-heads-both)9d\n" % data)
1134 ui.writenoi18n(b" both: %(nb-common-heads-both)9d\n" % data)
1081 ui.writenoi18n(b" local heads: %(nb-head-local)9d\n" % data)
1135 ui.writenoi18n(b" local heads: %(nb-head-local)9d\n" % data)
1082 ui.writenoi18n(
1136 ui.writenoi18n(
1083 b" common: %(nb-common-heads-local)9d\n" % data
1137 b" common: %(nb-common-heads-local)9d\n" % data
1084 )
1138 )
1085 ui.writenoi18n(
1139 ui.writenoi18n(
1086 b" missing: %(nb-head-local-missing)9d\n" % data
1140 b" missing: %(nb-head-local-missing)9d\n" % data
1087 )
1141 )
1088 ui.writenoi18n(b" remote heads: %(nb-head-remote)9d\n" % data)
1142 ui.writenoi18n(b" remote heads: %(nb-head-remote)9d\n" % data)
1089 ui.writenoi18n(
1143 ui.writenoi18n(
1090 b" common: %(nb-common-heads-remote)9d\n" % data
1144 b" common: %(nb-common-heads-remote)9d\n" % data
1091 )
1145 )
1092 ui.writenoi18n(
1146 ui.writenoi18n(
1093 b" unknown: %(nb-head-remote-unknown)9d\n" % data
1147 b" unknown: %(nb-head-remote-unknown)9d\n" % data
1094 )
1148 )
1095 ui.writenoi18n(b"local changesets: %(nb-revs)9d\n" % data)
1149 ui.writenoi18n(b"local changesets: %(nb-revs)9d\n" % data)
1096 ui.writenoi18n(b" common: %(nb-revs-common)9d\n" % data)
1150 ui.writenoi18n(b" common: %(nb-revs-common)9d\n" % data)
1097 ui.writenoi18n(b" heads: %(nb-common-heads)9d\n" % data)
1151 ui.writenoi18n(b" heads: %(nb-common-heads)9d\n" % data)
1098 ui.writenoi18n(b" roots: %(nb-common-roots)9d\n" % data)
1152 ui.writenoi18n(b" roots: %(nb-common-roots)9d\n" % data)
1099 ui.writenoi18n(b" missing: %(nb-revs-missing)9d\n" % data)
1153 ui.writenoi18n(b" missing: %(nb-revs-missing)9d\n" % data)
1100 ui.writenoi18n(b" heads: %(nb-missing-heads)9d\n" % data)
1154 ui.writenoi18n(b" heads: %(nb-missing-heads)9d\n" % data)
1101 ui.writenoi18n(b" roots: %(nb-missing-roots)9d\n" % data)
1155 ui.writenoi18n(b" roots: %(nb-missing-roots)9d\n" % data)
1102 ui.writenoi18n(b" first undecided set: %(nb-ini_und)9d\n" % data)
1156 ui.writenoi18n(b" first undecided set: %(nb-ini_und)9d\n" % data)
1103 ui.writenoi18n(b" heads: %(nb-ini_und-heads)9d\n" % data)
1157 ui.writenoi18n(b" heads: %(nb-ini_und-heads)9d\n" % data)
1104 ui.writenoi18n(b" roots: %(nb-ini_und-roots)9d\n" % data)
1158 ui.writenoi18n(b" roots: %(nb-ini_und-roots)9d\n" % data)
1105 ui.writenoi18n(b" common: %(nb-ini_und-common)9d\n" % data)
1159 ui.writenoi18n(b" common: %(nb-ini_und-common)9d\n" % data)
1106 ui.writenoi18n(b" missing: %(nb-ini_und-missing)9d\n" % data)
1160 ui.writenoi18n(b" missing: %(nb-ini_und-missing)9d\n" % data)
1107
1161
1108 if ui.verbose:
1162 if ui.verbose:
1109 ui.writenoi18n(
1163 ui.writenoi18n(
1110 b"common heads: %s\n"
1164 b"common heads: %s\n"
1111 % b" ".join(sorted(short(n) for n in heads_common))
1165 % b" ".join(sorted(short(n) for n in heads_common))
1112 )
1166 )
1113
1167
1114
1168
1115 _chunksize = 4 << 10
1169 _chunksize = 4 << 10
1116
1170
1117
1171
1118 @command(
1172 @command(
1119 b'debugdownload',
1173 b'debugdownload',
1120 [
1174 [
1121 (b'o', b'output', b'', _(b'path')),
1175 (b'o', b'output', b'', _(b'path')),
1122 ],
1176 ],
1123 optionalrepo=True,
1177 optionalrepo=True,
1124 )
1178 )
1125 def debugdownload(ui, repo, url, output=None, **opts):
1179 def debugdownload(ui, repo, url, output=None, **opts):
1126 """download a resource using Mercurial logic and config"""
1180 """download a resource using Mercurial logic and config"""
1127 fh = urlmod.open(ui, url, output)
1181 fh = urlmod.open(ui, url, output)
1128
1182
1129 dest = ui
1183 dest = ui
1130 if output:
1184 if output:
1131 dest = open(output, b"wb", _chunksize)
1185 dest = open(output, b"wb", _chunksize)
1132 try:
1186 try:
1133 data = fh.read(_chunksize)
1187 data = fh.read(_chunksize)
1134 while data:
1188 while data:
1135 dest.write(data)
1189 dest.write(data)
1136 data = fh.read(_chunksize)
1190 data = fh.read(_chunksize)
1137 finally:
1191 finally:
1138 if output:
1192 if output:
1139 dest.close()
1193 dest.close()
1140
1194
1141
1195
1142 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1196 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1143 def debugextensions(ui, repo, **opts):
1197 def debugextensions(ui, repo, **opts):
1144 '''show information about active extensions'''
1198 '''show information about active extensions'''
1145 opts = pycompat.byteskwargs(opts)
1199 opts = pycompat.byteskwargs(opts)
1146 exts = extensions.extensions(ui)
1200 exts = extensions.extensions(ui)
1147 hgver = util.version()
1201 hgver = util.version()
1148 fm = ui.formatter(b'debugextensions', opts)
1202 fm = ui.formatter(b'debugextensions', opts)
1149 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1203 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1150 isinternal = extensions.ismoduleinternal(extmod)
1204 isinternal = extensions.ismoduleinternal(extmod)
1151 extsource = None
1205 extsource = None
1152
1206
1153 if util.safehasattr(extmod, '__file__'):
1207 if util.safehasattr(extmod, '__file__'):
1154 extsource = pycompat.fsencode(extmod.__file__)
1208 extsource = pycompat.fsencode(extmod.__file__)
1155 elif getattr(sys, 'oxidized', False):
1209 elif getattr(sys, 'oxidized', False):
1156 extsource = pycompat.sysexecutable
1210 extsource = pycompat.sysexecutable
1157 if isinternal:
1211 if isinternal:
1158 exttestedwith = [] # never expose magic string to users
1212 exttestedwith = [] # never expose magic string to users
1159 else:
1213 else:
1160 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1214 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1161 extbuglink = getattr(extmod, 'buglink', None)
1215 extbuglink = getattr(extmod, 'buglink', None)
1162
1216
1163 fm.startitem()
1217 fm.startitem()
1164
1218
1165 if ui.quiet or ui.verbose:
1219 if ui.quiet or ui.verbose:
1166 fm.write(b'name', b'%s\n', extname)
1220 fm.write(b'name', b'%s\n', extname)
1167 else:
1221 else:
1168 fm.write(b'name', b'%s', extname)
1222 fm.write(b'name', b'%s', extname)
1169 if isinternal or hgver in exttestedwith:
1223 if isinternal or hgver in exttestedwith:
1170 fm.plain(b'\n')
1224 fm.plain(b'\n')
1171 elif not exttestedwith:
1225 elif not exttestedwith:
1172 fm.plain(_(b' (untested!)\n'))
1226 fm.plain(_(b' (untested!)\n'))
1173 else:
1227 else:
1174 lasttestedversion = exttestedwith[-1]
1228 lasttestedversion = exttestedwith[-1]
1175 fm.plain(b' (%s!)\n' % lasttestedversion)
1229 fm.plain(b' (%s!)\n' % lasttestedversion)
1176
1230
1177 fm.condwrite(
1231 fm.condwrite(
1178 ui.verbose and extsource,
1232 ui.verbose and extsource,
1179 b'source',
1233 b'source',
1180 _(b' location: %s\n'),
1234 _(b' location: %s\n'),
1181 extsource or b"",
1235 extsource or b"",
1182 )
1236 )
1183
1237
1184 if ui.verbose:
1238 if ui.verbose:
1185 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1239 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1186 fm.data(bundled=isinternal)
1240 fm.data(bundled=isinternal)
1187
1241
1188 fm.condwrite(
1242 fm.condwrite(
1189 ui.verbose and exttestedwith,
1243 ui.verbose and exttestedwith,
1190 b'testedwith',
1244 b'testedwith',
1191 _(b' tested with: %s\n'),
1245 _(b' tested with: %s\n'),
1192 fm.formatlist(exttestedwith, name=b'ver'),
1246 fm.formatlist(exttestedwith, name=b'ver'),
1193 )
1247 )
1194
1248
1195 fm.condwrite(
1249 fm.condwrite(
1196 ui.verbose and extbuglink,
1250 ui.verbose and extbuglink,
1197 b'buglink',
1251 b'buglink',
1198 _(b' bug reporting: %s\n'),
1252 _(b' bug reporting: %s\n'),
1199 extbuglink or b"",
1253 extbuglink or b"",
1200 )
1254 )
1201
1255
1202 fm.end()
1256 fm.end()
1203
1257
1204
1258
1205 @command(
1259 @command(
1206 b'debugfileset',
1260 b'debugfileset',
1207 [
1261 [
1208 (
1262 (
1209 b'r',
1263 b'r',
1210 b'rev',
1264 b'rev',
1211 b'',
1265 b'',
1212 _(b'apply the filespec on this revision'),
1266 _(b'apply the filespec on this revision'),
1213 _(b'REV'),
1267 _(b'REV'),
1214 ),
1268 ),
1215 (
1269 (
1216 b'',
1270 b'',
1217 b'all-files',
1271 b'all-files',
1218 False,
1272 False,
1219 _(b'test files from all revisions and working directory'),
1273 _(b'test files from all revisions and working directory'),
1220 ),
1274 ),
1221 (
1275 (
1222 b's',
1276 b's',
1223 b'show-matcher',
1277 b'show-matcher',
1224 None,
1278 None,
1225 _(b'print internal representation of matcher'),
1279 _(b'print internal representation of matcher'),
1226 ),
1280 ),
1227 (
1281 (
1228 b'p',
1282 b'p',
1229 b'show-stage',
1283 b'show-stage',
1230 [],
1284 [],
1231 _(b'print parsed tree at the given stage'),
1285 _(b'print parsed tree at the given stage'),
1232 _(b'NAME'),
1286 _(b'NAME'),
1233 ),
1287 ),
1234 ],
1288 ],
1235 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1289 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1236 )
1290 )
1237 def debugfileset(ui, repo, expr, **opts):
1291 def debugfileset(ui, repo, expr, **opts):
1238 '''parse and apply a fileset specification'''
1292 '''parse and apply a fileset specification'''
1239 from . import fileset
1293 from . import fileset
1240
1294
1241 fileset.symbols # force import of fileset so we have predicates to optimize
1295 fileset.symbols # force import of fileset so we have predicates to optimize
1242 opts = pycompat.byteskwargs(opts)
1296 opts = pycompat.byteskwargs(opts)
1243 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
1297 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
1244
1298
1245 stages = [
1299 stages = [
1246 (b'parsed', pycompat.identity),
1300 (b'parsed', pycompat.identity),
1247 (b'analyzed', filesetlang.analyze),
1301 (b'analyzed', filesetlang.analyze),
1248 (b'optimized', filesetlang.optimize),
1302 (b'optimized', filesetlang.optimize),
1249 ]
1303 ]
1250 stagenames = {n for n, f in stages}
1304 stagenames = {n for n, f in stages}
1251
1305
1252 showalways = set()
1306 showalways = set()
1253 if ui.verbose and not opts[b'show_stage']:
1307 if ui.verbose and not opts[b'show_stage']:
1254 # show parsed tree by --verbose (deprecated)
1308 # show parsed tree by --verbose (deprecated)
1255 showalways.add(b'parsed')
1309 showalways.add(b'parsed')
1256 if opts[b'show_stage'] == [b'all']:
1310 if opts[b'show_stage'] == [b'all']:
1257 showalways.update(stagenames)
1311 showalways.update(stagenames)
1258 else:
1312 else:
1259 for n in opts[b'show_stage']:
1313 for n in opts[b'show_stage']:
1260 if n not in stagenames:
1314 if n not in stagenames:
1261 raise error.Abort(_(b'invalid stage name: %s') % n)
1315 raise error.Abort(_(b'invalid stage name: %s') % n)
1262 showalways.update(opts[b'show_stage'])
1316 showalways.update(opts[b'show_stage'])
1263
1317
1264 tree = filesetlang.parse(expr)
1318 tree = filesetlang.parse(expr)
1265 for n, f in stages:
1319 for n, f in stages:
1266 tree = f(tree)
1320 tree = f(tree)
1267 if n in showalways:
1321 if n in showalways:
1268 if opts[b'show_stage'] or n != b'parsed':
1322 if opts[b'show_stage'] or n != b'parsed':
1269 ui.write(b"* %s:\n" % n)
1323 ui.write(b"* %s:\n" % n)
1270 ui.write(filesetlang.prettyformat(tree), b"\n")
1324 ui.write(filesetlang.prettyformat(tree), b"\n")
1271
1325
1272 files = set()
1326 files = set()
1273 if opts[b'all_files']:
1327 if opts[b'all_files']:
1274 for r in repo:
1328 for r in repo:
1275 c = repo[r]
1329 c = repo[r]
1276 files.update(c.files())
1330 files.update(c.files())
1277 files.update(c.substate)
1331 files.update(c.substate)
1278 if opts[b'all_files'] or ctx.rev() is None:
1332 if opts[b'all_files'] or ctx.rev() is None:
1279 wctx = repo[None]
1333 wctx = repo[None]
1280 files.update(
1334 files.update(
1281 repo.dirstate.walk(
1335 repo.dirstate.walk(
1282 scmutil.matchall(repo),
1336 scmutil.matchall(repo),
1283 subrepos=list(wctx.substate),
1337 subrepos=list(wctx.substate),
1284 unknown=True,
1338 unknown=True,
1285 ignored=True,
1339 ignored=True,
1286 )
1340 )
1287 )
1341 )
1288 files.update(wctx.substate)
1342 files.update(wctx.substate)
1289 else:
1343 else:
1290 files.update(ctx.files())
1344 files.update(ctx.files())
1291 files.update(ctx.substate)
1345 files.update(ctx.substate)
1292
1346
1293 m = ctx.matchfileset(repo.getcwd(), expr)
1347 m = ctx.matchfileset(repo.getcwd(), expr)
1294 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1348 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1295 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1349 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1296 for f in sorted(files):
1350 for f in sorted(files):
1297 if not m(f):
1351 if not m(f):
1298 continue
1352 continue
1299 ui.write(b"%s\n" % f)
1353 ui.write(b"%s\n" % f)
1300
1354
1301
1355
1302 @command(b'debugformat', [] + cmdutil.formatteropts)
1356 @command(b'debugformat', [] + cmdutil.formatteropts)
1303 def debugformat(ui, repo, **opts):
1357 def debugformat(ui, repo, **opts):
1304 """display format information about the current repository
1358 """display format information about the current repository
1305
1359
1306 Use --verbose to get extra information about current config value and
1360 Use --verbose to get extra information about current config value and
1307 Mercurial default."""
1361 Mercurial default."""
1308 opts = pycompat.byteskwargs(opts)
1362 opts = pycompat.byteskwargs(opts)
1309 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1363 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1310 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1364 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1311
1365
1312 def makeformatname(name):
1366 def makeformatname(name):
1313 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1367 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1314
1368
1315 fm = ui.formatter(b'debugformat', opts)
1369 fm = ui.formatter(b'debugformat', opts)
1316 if fm.isplain():
1370 if fm.isplain():
1317
1371
1318 def formatvalue(value):
1372 def formatvalue(value):
1319 if util.safehasattr(value, b'startswith'):
1373 if util.safehasattr(value, b'startswith'):
1320 return value
1374 return value
1321 if value:
1375 if value:
1322 return b'yes'
1376 return b'yes'
1323 else:
1377 else:
1324 return b'no'
1378 return b'no'
1325
1379
1326 else:
1380 else:
1327 formatvalue = pycompat.identity
1381 formatvalue = pycompat.identity
1328
1382
1329 fm.plain(b'format-variant')
1383 fm.plain(b'format-variant')
1330 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1384 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1331 fm.plain(b' repo')
1385 fm.plain(b' repo')
1332 if ui.verbose:
1386 if ui.verbose:
1333 fm.plain(b' config default')
1387 fm.plain(b' config default')
1334 fm.plain(b'\n')
1388 fm.plain(b'\n')
1335 for fv in upgrade.allformatvariant:
1389 for fv in upgrade.allformatvariant:
1336 fm.startitem()
1390 fm.startitem()
1337 repovalue = fv.fromrepo(repo)
1391 repovalue = fv.fromrepo(repo)
1338 configvalue = fv.fromconfig(repo)
1392 configvalue = fv.fromconfig(repo)
1339
1393
1340 if repovalue != configvalue:
1394 if repovalue != configvalue:
1341 namelabel = b'formatvariant.name.mismatchconfig'
1395 namelabel = b'formatvariant.name.mismatchconfig'
1342 repolabel = b'formatvariant.repo.mismatchconfig'
1396 repolabel = b'formatvariant.repo.mismatchconfig'
1343 elif repovalue != fv.default:
1397 elif repovalue != fv.default:
1344 namelabel = b'formatvariant.name.mismatchdefault'
1398 namelabel = b'formatvariant.name.mismatchdefault'
1345 repolabel = b'formatvariant.repo.mismatchdefault'
1399 repolabel = b'formatvariant.repo.mismatchdefault'
1346 else:
1400 else:
1347 namelabel = b'formatvariant.name.uptodate'
1401 namelabel = b'formatvariant.name.uptodate'
1348 repolabel = b'formatvariant.repo.uptodate'
1402 repolabel = b'formatvariant.repo.uptodate'
1349
1403
1350 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1404 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1351 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1405 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1352 if fv.default != configvalue:
1406 if fv.default != configvalue:
1353 configlabel = b'formatvariant.config.special'
1407 configlabel = b'formatvariant.config.special'
1354 else:
1408 else:
1355 configlabel = b'formatvariant.config.default'
1409 configlabel = b'formatvariant.config.default'
1356 fm.condwrite(
1410 fm.condwrite(
1357 ui.verbose,
1411 ui.verbose,
1358 b'config',
1412 b'config',
1359 b' %6s',
1413 b' %6s',
1360 formatvalue(configvalue),
1414 formatvalue(configvalue),
1361 label=configlabel,
1415 label=configlabel,
1362 )
1416 )
1363 fm.condwrite(
1417 fm.condwrite(
1364 ui.verbose,
1418 ui.verbose,
1365 b'default',
1419 b'default',
1366 b' %7s',
1420 b' %7s',
1367 formatvalue(fv.default),
1421 formatvalue(fv.default),
1368 label=b'formatvariant.default',
1422 label=b'formatvariant.default',
1369 )
1423 )
1370 fm.plain(b'\n')
1424 fm.plain(b'\n')
1371 fm.end()
1425 fm.end()
1372
1426
1373
1427
1374 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1428 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1375 def debugfsinfo(ui, path=b"."):
1429 def debugfsinfo(ui, path=b"."):
1376 """show information detected about current filesystem"""
1430 """show information detected about current filesystem"""
1377 ui.writenoi18n(b'path: %s\n' % path)
1431 ui.writenoi18n(b'path: %s\n' % path)
1378 ui.writenoi18n(
1432 ui.writenoi18n(
1379 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1433 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1380 )
1434 )
1381 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1435 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1382 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1436 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1383 ui.writenoi18n(
1437 ui.writenoi18n(
1384 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1438 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1385 )
1439 )
1386 ui.writenoi18n(
1440 ui.writenoi18n(
1387 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1441 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1388 )
1442 )
1389 casesensitive = b'(unknown)'
1443 casesensitive = b'(unknown)'
1390 try:
1444 try:
1391 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1445 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1392 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1446 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1393 except OSError:
1447 except OSError:
1394 pass
1448 pass
1395 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1449 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1396
1450
1397
1451
1398 @command(
1452 @command(
1399 b'debuggetbundle',
1453 b'debuggetbundle',
1400 [
1454 [
1401 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1455 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1402 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1456 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1403 (
1457 (
1404 b't',
1458 b't',
1405 b'type',
1459 b'type',
1406 b'bzip2',
1460 b'bzip2',
1407 _(b'bundle compression type to use'),
1461 _(b'bundle compression type to use'),
1408 _(b'TYPE'),
1462 _(b'TYPE'),
1409 ),
1463 ),
1410 ],
1464 ],
1411 _(b'REPO FILE [-H|-C ID]...'),
1465 _(b'REPO FILE [-H|-C ID]...'),
1412 norepo=True,
1466 norepo=True,
1413 )
1467 )
1414 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1468 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1415 """retrieves a bundle from a repo
1469 """retrieves a bundle from a repo
1416
1470
1417 Every ID must be a full-length hex node id string. Saves the bundle to the
1471 Every ID must be a full-length hex node id string. Saves the bundle to the
1418 given file.
1472 given file.
1419 """
1473 """
1420 opts = pycompat.byteskwargs(opts)
1474 opts = pycompat.byteskwargs(opts)
1421 repo = hg.peer(ui, opts, repopath)
1475 repo = hg.peer(ui, opts, repopath)
1422 if not repo.capable(b'getbundle'):
1476 if not repo.capable(b'getbundle'):
1423 raise error.Abort(b"getbundle() not supported by target repository")
1477 raise error.Abort(b"getbundle() not supported by target repository")
1424 args = {}
1478 args = {}
1425 if common:
1479 if common:
1426 args['common'] = [bin(s) for s in common]
1480 args['common'] = [bin(s) for s in common]
1427 if head:
1481 if head:
1428 args['heads'] = [bin(s) for s in head]
1482 args['heads'] = [bin(s) for s in head]
1429 # TODO: get desired bundlecaps from command line.
1483 # TODO: get desired bundlecaps from command line.
1430 args['bundlecaps'] = None
1484 args['bundlecaps'] = None
1431 bundle = repo.getbundle(b'debug', **args)
1485 bundle = repo.getbundle(b'debug', **args)
1432
1486
1433 bundletype = opts.get(b'type', b'bzip2').lower()
1487 bundletype = opts.get(b'type', b'bzip2').lower()
1434 btypes = {
1488 btypes = {
1435 b'none': b'HG10UN',
1489 b'none': b'HG10UN',
1436 b'bzip2': b'HG10BZ',
1490 b'bzip2': b'HG10BZ',
1437 b'gzip': b'HG10GZ',
1491 b'gzip': b'HG10GZ',
1438 b'bundle2': b'HG20',
1492 b'bundle2': b'HG20',
1439 }
1493 }
1440 bundletype = btypes.get(bundletype)
1494 bundletype = btypes.get(bundletype)
1441 if bundletype not in bundle2.bundletypes:
1495 if bundletype not in bundle2.bundletypes:
1442 raise error.Abort(_(b'unknown bundle type specified with --type'))
1496 raise error.Abort(_(b'unknown bundle type specified with --type'))
1443 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1497 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1444
1498
1445
1499
1446 @command(b'debugignore', [], b'[FILE]')
1500 @command(b'debugignore', [], b'[FILE]')
1447 def debugignore(ui, repo, *files, **opts):
1501 def debugignore(ui, repo, *files, **opts):
1448 """display the combined ignore pattern and information about ignored files
1502 """display the combined ignore pattern and information about ignored files
1449
1503
1450 With no argument display the combined ignore pattern.
1504 With no argument display the combined ignore pattern.
1451
1505
1452 Given space separated file names, shows if the given file is ignored and
1506 Given space separated file names, shows if the given file is ignored and
1453 if so, show the ignore rule (file and line number) that matched it.
1507 if so, show the ignore rule (file and line number) that matched it.
1454 """
1508 """
1455 ignore = repo.dirstate._ignore
1509 ignore = repo.dirstate._ignore
1456 if not files:
1510 if not files:
1457 # Show all the patterns
1511 # Show all the patterns
1458 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1512 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1459 else:
1513 else:
1460 m = scmutil.match(repo[None], pats=files)
1514 m = scmutil.match(repo[None], pats=files)
1461 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1515 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1462 for f in m.files():
1516 for f in m.files():
1463 nf = util.normpath(f)
1517 nf = util.normpath(f)
1464 ignored = None
1518 ignored = None
1465 ignoredata = None
1519 ignoredata = None
1466 if nf != b'.':
1520 if nf != b'.':
1467 if ignore(nf):
1521 if ignore(nf):
1468 ignored = nf
1522 ignored = nf
1469 ignoredata = repo.dirstate._ignorefileandline(nf)
1523 ignoredata = repo.dirstate._ignorefileandline(nf)
1470 else:
1524 else:
1471 for p in pathutil.finddirs(nf):
1525 for p in pathutil.finddirs(nf):
1472 if ignore(p):
1526 if ignore(p):
1473 ignored = p
1527 ignored = p
1474 ignoredata = repo.dirstate._ignorefileandline(p)
1528 ignoredata = repo.dirstate._ignorefileandline(p)
1475 break
1529 break
1476 if ignored:
1530 if ignored:
1477 if ignored == nf:
1531 if ignored == nf:
1478 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1532 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1479 else:
1533 else:
1480 ui.write(
1534 ui.write(
1481 _(
1535 _(
1482 b"%s is ignored because of "
1536 b"%s is ignored because of "
1483 b"containing directory %s\n"
1537 b"containing directory %s\n"
1484 )
1538 )
1485 % (uipathfn(f), ignored)
1539 % (uipathfn(f), ignored)
1486 )
1540 )
1487 ignorefile, lineno, line = ignoredata
1541 ignorefile, lineno, line = ignoredata
1488 ui.write(
1542 ui.write(
1489 _(b"(ignore rule in %s, line %d: '%s')\n")
1543 _(b"(ignore rule in %s, line %d: '%s')\n")
1490 % (ignorefile, lineno, line)
1544 % (ignorefile, lineno, line)
1491 )
1545 )
1492 else:
1546 else:
1493 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1547 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1494
1548
1495
1549
1496 @command(
1550 @command(
1497 b'debugindex',
1551 b'debugindex',
1498 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1552 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1499 _(b'-c|-m|FILE'),
1553 _(b'-c|-m|FILE'),
1500 )
1554 )
1501 def debugindex(ui, repo, file_=None, **opts):
1555 def debugindex(ui, repo, file_=None, **opts):
1502 """dump index data for a storage primitive"""
1556 """dump index data for a storage primitive"""
1503 opts = pycompat.byteskwargs(opts)
1557 opts = pycompat.byteskwargs(opts)
1504 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1558 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1505
1559
1506 if ui.debugflag:
1560 if ui.debugflag:
1507 shortfn = hex
1561 shortfn = hex
1508 else:
1562 else:
1509 shortfn = short
1563 shortfn = short
1510
1564
1511 idlen = 12
1565 idlen = 12
1512 for i in store:
1566 for i in store:
1513 idlen = len(shortfn(store.node(i)))
1567 idlen = len(shortfn(store.node(i)))
1514 break
1568 break
1515
1569
1516 fm = ui.formatter(b'debugindex', opts)
1570 fm = ui.formatter(b'debugindex', opts)
1517 fm.plain(
1571 fm.plain(
1518 b' rev linkrev %s %s p2\n'
1572 b' rev linkrev %s %s p2\n'
1519 % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
1573 % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
1520 )
1574 )
1521
1575
1522 for rev in store:
1576 for rev in store:
1523 node = store.node(rev)
1577 node = store.node(rev)
1524 parents = store.parents(node)
1578 parents = store.parents(node)
1525
1579
1526 fm.startitem()
1580 fm.startitem()
1527 fm.write(b'rev', b'%6d ', rev)
1581 fm.write(b'rev', b'%6d ', rev)
1528 fm.write(b'linkrev', b'%7d ', store.linkrev(rev))
1582 fm.write(b'linkrev', b'%7d ', store.linkrev(rev))
1529 fm.write(b'node', b'%s ', shortfn(node))
1583 fm.write(b'node', b'%s ', shortfn(node))
1530 fm.write(b'p1', b'%s ', shortfn(parents[0]))
1584 fm.write(b'p1', b'%s ', shortfn(parents[0]))
1531 fm.write(b'p2', b'%s', shortfn(parents[1]))
1585 fm.write(b'p2', b'%s', shortfn(parents[1]))
1532 fm.plain(b'\n')
1586 fm.plain(b'\n')
1533
1587
1534 fm.end()
1588 fm.end()
1535
1589
1536
1590
1537 @command(
1591 @command(
1538 b'debugindexdot',
1592 b'debugindexdot',
1539 cmdutil.debugrevlogopts,
1593 cmdutil.debugrevlogopts,
1540 _(b'-c|-m|FILE'),
1594 _(b'-c|-m|FILE'),
1541 optionalrepo=True,
1595 optionalrepo=True,
1542 )
1596 )
1543 def debugindexdot(ui, repo, file_=None, **opts):
1597 def debugindexdot(ui, repo, file_=None, **opts):
1544 """dump an index DAG as a graphviz dot file"""
1598 """dump an index DAG as a graphviz dot file"""
1545 opts = pycompat.byteskwargs(opts)
1599 opts = pycompat.byteskwargs(opts)
1546 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1600 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1547 ui.writenoi18n(b"digraph G {\n")
1601 ui.writenoi18n(b"digraph G {\n")
1548 for i in r:
1602 for i in r:
1549 node = r.node(i)
1603 node = r.node(i)
1550 pp = r.parents(node)
1604 pp = r.parents(node)
1551 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1605 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1552 if pp[1] != nullid:
1606 if pp[1] != nullid:
1553 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1607 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1554 ui.write(b"}\n")
1608 ui.write(b"}\n")
1555
1609
1556
1610
1557 @command(b'debugindexstats', [])
1611 @command(b'debugindexstats', [])
1558 def debugindexstats(ui, repo):
1612 def debugindexstats(ui, repo):
1559 """show stats related to the changelog index"""
1613 """show stats related to the changelog index"""
1560 repo.changelog.shortest(nullid, 1)
1614 repo.changelog.shortest(nullid, 1)
1561 index = repo.changelog.index
1615 index = repo.changelog.index
1562 if not util.safehasattr(index, b'stats'):
1616 if not util.safehasattr(index, b'stats'):
1563 raise error.Abort(_(b'debugindexstats only works with native code'))
1617 raise error.Abort(_(b'debugindexstats only works with native code'))
1564 for k, v in sorted(index.stats().items()):
1618 for k, v in sorted(index.stats().items()):
1565 ui.write(b'%s: %d\n' % (k, v))
1619 ui.write(b'%s: %d\n' % (k, v))
1566
1620
1567
1621
1568 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1622 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1569 def debuginstall(ui, **opts):
1623 def debuginstall(ui, **opts):
1570 """test Mercurial installation
1624 """test Mercurial installation
1571
1625
1572 Returns 0 on success.
1626 Returns 0 on success.
1573 """
1627 """
1574 opts = pycompat.byteskwargs(opts)
1628 opts = pycompat.byteskwargs(opts)
1575
1629
1576 problems = 0
1630 problems = 0
1577
1631
1578 fm = ui.formatter(b'debuginstall', opts)
1632 fm = ui.formatter(b'debuginstall', opts)
1579 fm.startitem()
1633 fm.startitem()
1580
1634
1581 # encoding might be unknown or wrong. don't translate these messages.
1635 # encoding might be unknown or wrong. don't translate these messages.
1582 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1636 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1583 err = None
1637 err = None
1584 try:
1638 try:
1585 codecs.lookup(pycompat.sysstr(encoding.encoding))
1639 codecs.lookup(pycompat.sysstr(encoding.encoding))
1586 except LookupError as inst:
1640 except LookupError as inst:
1587 err = stringutil.forcebytestr(inst)
1641 err = stringutil.forcebytestr(inst)
1588 problems += 1
1642 problems += 1
1589 fm.condwrite(
1643 fm.condwrite(
1590 err,
1644 err,
1591 b'encodingerror',
1645 b'encodingerror',
1592 b" %s\n (check that your locale is properly set)\n",
1646 b" %s\n (check that your locale is properly set)\n",
1593 err,
1647 err,
1594 )
1648 )
1595
1649
1596 # Python
1650 # Python
1597 pythonlib = None
1651 pythonlib = None
1598 if util.safehasattr(os, '__file__'):
1652 if util.safehasattr(os, '__file__'):
1599 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1653 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1600 elif getattr(sys, 'oxidized', False):
1654 elif getattr(sys, 'oxidized', False):
1601 pythonlib = pycompat.sysexecutable
1655 pythonlib = pycompat.sysexecutable
1602
1656
1603 fm.write(
1657 fm.write(
1604 b'pythonexe',
1658 b'pythonexe',
1605 _(b"checking Python executable (%s)\n"),
1659 _(b"checking Python executable (%s)\n"),
1606 pycompat.sysexecutable or _(b"unknown"),
1660 pycompat.sysexecutable or _(b"unknown"),
1607 )
1661 )
1608 fm.write(
1662 fm.write(
1609 b'pythonimplementation',
1663 b'pythonimplementation',
1610 _(b"checking Python implementation (%s)\n"),
1664 _(b"checking Python implementation (%s)\n"),
1611 pycompat.sysbytes(platform.python_implementation()),
1665 pycompat.sysbytes(platform.python_implementation()),
1612 )
1666 )
1613 fm.write(
1667 fm.write(
1614 b'pythonver',
1668 b'pythonver',
1615 _(b"checking Python version (%s)\n"),
1669 _(b"checking Python version (%s)\n"),
1616 (b"%d.%d.%d" % sys.version_info[:3]),
1670 (b"%d.%d.%d" % sys.version_info[:3]),
1617 )
1671 )
1618 fm.write(
1672 fm.write(
1619 b'pythonlib',
1673 b'pythonlib',
1620 _(b"checking Python lib (%s)...\n"),
1674 _(b"checking Python lib (%s)...\n"),
1621 pythonlib or _(b"unknown"),
1675 pythonlib or _(b"unknown"),
1622 )
1676 )
1623
1677
1624 try:
1678 try:
1625 from . import rustext
1679 from . import rustext
1626
1680
1627 rustext.__doc__ # trigger lazy import
1681 rustext.__doc__ # trigger lazy import
1628 except ImportError:
1682 except ImportError:
1629 rustext = None
1683 rustext = None
1630
1684
1631 security = set(sslutil.supportedprotocols)
1685 security = set(sslutil.supportedprotocols)
1632 if sslutil.hassni:
1686 if sslutil.hassni:
1633 security.add(b'sni')
1687 security.add(b'sni')
1634
1688
1635 fm.write(
1689 fm.write(
1636 b'pythonsecurity',
1690 b'pythonsecurity',
1637 _(b"checking Python security support (%s)\n"),
1691 _(b"checking Python security support (%s)\n"),
1638 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1692 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1639 )
1693 )
1640
1694
1641 # These are warnings, not errors. So don't increment problem count. This
1695 # These are warnings, not errors. So don't increment problem count. This
1642 # may change in the future.
1696 # may change in the future.
1643 if b'tls1.2' not in security:
1697 if b'tls1.2' not in security:
1644 fm.plain(
1698 fm.plain(
1645 _(
1699 _(
1646 b' TLS 1.2 not supported by Python install; '
1700 b' TLS 1.2 not supported by Python install; '
1647 b'network connections lack modern security\n'
1701 b'network connections lack modern security\n'
1648 )
1702 )
1649 )
1703 )
1650 if b'sni' not in security:
1704 if b'sni' not in security:
1651 fm.plain(
1705 fm.plain(
1652 _(
1706 _(
1653 b' SNI not supported by Python install; may have '
1707 b' SNI not supported by Python install; may have '
1654 b'connectivity issues with some servers\n'
1708 b'connectivity issues with some servers\n'
1655 )
1709 )
1656 )
1710 )
1657
1711
1658 fm.plain(
1712 fm.plain(
1659 _(
1713 _(
1660 b"checking Rust extensions (%s)\n"
1714 b"checking Rust extensions (%s)\n"
1661 % (b'missing' if rustext is None else b'installed')
1715 % (b'missing' if rustext is None else b'installed')
1662 ),
1716 ),
1663 )
1717 )
1664
1718
1665 # TODO print CA cert info
1719 # TODO print CA cert info
1666
1720
1667 # hg version
1721 # hg version
1668 hgver = util.version()
1722 hgver = util.version()
1669 fm.write(
1723 fm.write(
1670 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1724 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1671 )
1725 )
1672 fm.write(
1726 fm.write(
1673 b'hgverextra',
1727 b'hgverextra',
1674 _(b"checking Mercurial custom build (%s)\n"),
1728 _(b"checking Mercurial custom build (%s)\n"),
1675 b'+'.join(hgver.split(b'+')[1:]),
1729 b'+'.join(hgver.split(b'+')[1:]),
1676 )
1730 )
1677
1731
1678 # compiled modules
1732 # compiled modules
1679 hgmodules = None
1733 hgmodules = None
1680 if util.safehasattr(sys.modules[__name__], '__file__'):
1734 if util.safehasattr(sys.modules[__name__], '__file__'):
1681 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1735 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1682 elif getattr(sys, 'oxidized', False):
1736 elif getattr(sys, 'oxidized', False):
1683 hgmodules = pycompat.sysexecutable
1737 hgmodules = pycompat.sysexecutable
1684
1738
1685 fm.write(
1739 fm.write(
1686 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1740 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1687 )
1741 )
1688 fm.write(
1742 fm.write(
1689 b'hgmodules',
1743 b'hgmodules',
1690 _(b"checking installed modules (%s)...\n"),
1744 _(b"checking installed modules (%s)...\n"),
1691 hgmodules or _(b"unknown"),
1745 hgmodules or _(b"unknown"),
1692 )
1746 )
1693
1747
1694 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1748 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1695 rustext = rustandc # for now, that's the only case
1749 rustext = rustandc # for now, that's the only case
1696 cext = policy.policy in (b'c', b'allow') or rustandc
1750 cext = policy.policy in (b'c', b'allow') or rustandc
1697 nopure = cext or rustext
1751 nopure = cext or rustext
1698 if nopure:
1752 if nopure:
1699 err = None
1753 err = None
1700 try:
1754 try:
1701 if cext:
1755 if cext:
1702 from .cext import ( # pytype: disable=import-error
1756 from .cext import ( # pytype: disable=import-error
1703 base85,
1757 base85,
1704 bdiff,
1758 bdiff,
1705 mpatch,
1759 mpatch,
1706 osutil,
1760 osutil,
1707 )
1761 )
1708
1762
1709 # quiet pyflakes
1763 # quiet pyflakes
1710 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
1764 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
1711 if rustext:
1765 if rustext:
1712 from .rustext import ( # pytype: disable=import-error
1766 from .rustext import ( # pytype: disable=import-error
1713 ancestor,
1767 ancestor,
1714 dirstate,
1768 dirstate,
1715 )
1769 )
1716
1770
1717 dir(ancestor), dir(dirstate) # quiet pyflakes
1771 dir(ancestor), dir(dirstate) # quiet pyflakes
1718 except Exception as inst:
1772 except Exception as inst:
1719 err = stringutil.forcebytestr(inst)
1773 err = stringutil.forcebytestr(inst)
1720 problems += 1
1774 problems += 1
1721 fm.condwrite(err, b'extensionserror', b" %s\n", err)
1775 fm.condwrite(err, b'extensionserror', b" %s\n", err)
1722
1776
1723 compengines = util.compengines._engines.values()
1777 compengines = util.compengines._engines.values()
1724 fm.write(
1778 fm.write(
1725 b'compengines',
1779 b'compengines',
1726 _(b'checking registered compression engines (%s)\n'),
1780 _(b'checking registered compression engines (%s)\n'),
1727 fm.formatlist(
1781 fm.formatlist(
1728 sorted(e.name() for e in compengines),
1782 sorted(e.name() for e in compengines),
1729 name=b'compengine',
1783 name=b'compengine',
1730 fmt=b'%s',
1784 fmt=b'%s',
1731 sep=b', ',
1785 sep=b', ',
1732 ),
1786 ),
1733 )
1787 )
1734 fm.write(
1788 fm.write(
1735 b'compenginesavail',
1789 b'compenginesavail',
1736 _(b'checking available compression engines (%s)\n'),
1790 _(b'checking available compression engines (%s)\n'),
1737 fm.formatlist(
1791 fm.formatlist(
1738 sorted(e.name() for e in compengines if e.available()),
1792 sorted(e.name() for e in compengines if e.available()),
1739 name=b'compengine',
1793 name=b'compengine',
1740 fmt=b'%s',
1794 fmt=b'%s',
1741 sep=b', ',
1795 sep=b', ',
1742 ),
1796 ),
1743 )
1797 )
1744 wirecompengines = compression.compengines.supportedwireengines(
1798 wirecompengines = compression.compengines.supportedwireengines(
1745 compression.SERVERROLE
1799 compression.SERVERROLE
1746 )
1800 )
1747 fm.write(
1801 fm.write(
1748 b'compenginesserver',
1802 b'compenginesserver',
1749 _(
1803 _(
1750 b'checking available compression engines '
1804 b'checking available compression engines '
1751 b'for wire protocol (%s)\n'
1805 b'for wire protocol (%s)\n'
1752 ),
1806 ),
1753 fm.formatlist(
1807 fm.formatlist(
1754 [e.name() for e in wirecompengines if e.wireprotosupport()],
1808 [e.name() for e in wirecompengines if e.wireprotosupport()],
1755 name=b'compengine',
1809 name=b'compengine',
1756 fmt=b'%s',
1810 fmt=b'%s',
1757 sep=b', ',
1811 sep=b', ',
1758 ),
1812 ),
1759 )
1813 )
1760 re2 = b'missing'
1814 re2 = b'missing'
1761 if util._re2:
1815 if util._re2:
1762 re2 = b'available'
1816 re2 = b'available'
1763 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
1817 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
1764 fm.data(re2=bool(util._re2))
1818 fm.data(re2=bool(util._re2))
1765
1819
1766 # templates
1820 # templates
1767 p = templater.templatedir()
1821 p = templater.templatedir()
1768 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
1822 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
1769 fm.condwrite(not p, b'', _(b" no template directories found\n"))
1823 fm.condwrite(not p, b'', _(b" no template directories found\n"))
1770 if p:
1824 if p:
1771 (m, fp) = templater.try_open_template(b"map-cmdline.default")
1825 (m, fp) = templater.try_open_template(b"map-cmdline.default")
1772 if m:
1826 if m:
1773 # template found, check if it is working
1827 # template found, check if it is working
1774 err = None
1828 err = None
1775 try:
1829 try:
1776 templater.templater.frommapfile(m)
1830 templater.templater.frommapfile(m)
1777 except Exception as inst:
1831 except Exception as inst:
1778 err = stringutil.forcebytestr(inst)
1832 err = stringutil.forcebytestr(inst)
1779 p = None
1833 p = None
1780 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
1834 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
1781 else:
1835 else:
1782 p = None
1836 p = None
1783 fm.condwrite(
1837 fm.condwrite(
1784 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
1838 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
1785 )
1839 )
1786 fm.condwrite(
1840 fm.condwrite(
1787 not m,
1841 not m,
1788 b'defaulttemplatenotfound',
1842 b'defaulttemplatenotfound',
1789 _(b" template '%s' not found\n"),
1843 _(b" template '%s' not found\n"),
1790 b"default",
1844 b"default",
1791 )
1845 )
1792 if not p:
1846 if not p:
1793 problems += 1
1847 problems += 1
1794 fm.condwrite(
1848 fm.condwrite(
1795 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
1849 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
1796 )
1850 )
1797
1851
1798 # editor
1852 # editor
1799 editor = ui.geteditor()
1853 editor = ui.geteditor()
1800 editor = util.expandpath(editor)
1854 editor = util.expandpath(editor)
1801 editorbin = procutil.shellsplit(editor)[0]
1855 editorbin = procutil.shellsplit(editor)[0]
1802 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
1856 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
1803 cmdpath = procutil.findexe(editorbin)
1857 cmdpath = procutil.findexe(editorbin)
1804 fm.condwrite(
1858 fm.condwrite(
1805 not cmdpath and editor == b'vi',
1859 not cmdpath and editor == b'vi',
1806 b'vinotfound',
1860 b'vinotfound',
1807 _(
1861 _(
1808 b" No commit editor set and can't find %s in PATH\n"
1862 b" No commit editor set and can't find %s in PATH\n"
1809 b" (specify a commit editor in your configuration"
1863 b" (specify a commit editor in your configuration"
1810 b" file)\n"
1864 b" file)\n"
1811 ),
1865 ),
1812 not cmdpath and editor == b'vi' and editorbin,
1866 not cmdpath and editor == b'vi' and editorbin,
1813 )
1867 )
1814 fm.condwrite(
1868 fm.condwrite(
1815 not cmdpath and editor != b'vi',
1869 not cmdpath and editor != b'vi',
1816 b'editornotfound',
1870 b'editornotfound',
1817 _(
1871 _(
1818 b" Can't find editor '%s' in PATH\n"
1872 b" Can't find editor '%s' in PATH\n"
1819 b" (specify a commit editor in your configuration"
1873 b" (specify a commit editor in your configuration"
1820 b" file)\n"
1874 b" file)\n"
1821 ),
1875 ),
1822 not cmdpath and editorbin,
1876 not cmdpath and editorbin,
1823 )
1877 )
1824 if not cmdpath and editor != b'vi':
1878 if not cmdpath and editor != b'vi':
1825 problems += 1
1879 problems += 1
1826
1880
1827 # check username
1881 # check username
1828 username = None
1882 username = None
1829 err = None
1883 err = None
1830 try:
1884 try:
1831 username = ui.username()
1885 username = ui.username()
1832 except error.Abort as e:
1886 except error.Abort as e:
1833 err = e.message
1887 err = e.message
1834 problems += 1
1888 problems += 1
1835
1889
1836 fm.condwrite(
1890 fm.condwrite(
1837 username, b'username', _(b"checking username (%s)\n"), username
1891 username, b'username', _(b"checking username (%s)\n"), username
1838 )
1892 )
1839 fm.condwrite(
1893 fm.condwrite(
1840 err,
1894 err,
1841 b'usernameerror',
1895 b'usernameerror',
1842 _(
1896 _(
1843 b"checking username...\n %s\n"
1897 b"checking username...\n %s\n"
1844 b" (specify a username in your configuration file)\n"
1898 b" (specify a username in your configuration file)\n"
1845 ),
1899 ),
1846 err,
1900 err,
1847 )
1901 )
1848
1902
1849 for name, mod in extensions.extensions():
1903 for name, mod in extensions.extensions():
1850 handler = getattr(mod, 'debuginstall', None)
1904 handler = getattr(mod, 'debuginstall', None)
1851 if handler is not None:
1905 if handler is not None:
1852 problems += handler(ui, fm)
1906 problems += handler(ui, fm)
1853
1907
1854 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
1908 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
1855 if not problems:
1909 if not problems:
1856 fm.data(problems=problems)
1910 fm.data(problems=problems)
1857 fm.condwrite(
1911 fm.condwrite(
1858 problems,
1912 problems,
1859 b'problems',
1913 b'problems',
1860 _(b"%d problems detected, please check your install!\n"),
1914 _(b"%d problems detected, please check your install!\n"),
1861 problems,
1915 problems,
1862 )
1916 )
1863 fm.end()
1917 fm.end()
1864
1918
1865 return problems
1919 return problems
1866
1920
1867
1921
1868 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
1922 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
1869 def debugknown(ui, repopath, *ids, **opts):
1923 def debugknown(ui, repopath, *ids, **opts):
1870 """test whether node ids are known to a repo
1924 """test whether node ids are known to a repo
1871
1925
1872 Every ID must be a full-length hex node id string. Returns a list of 0s
1926 Every ID must be a full-length hex node id string. Returns a list of 0s
1873 and 1s indicating unknown/known.
1927 and 1s indicating unknown/known.
1874 """
1928 """
1875 opts = pycompat.byteskwargs(opts)
1929 opts = pycompat.byteskwargs(opts)
1876 repo = hg.peer(ui, opts, repopath)
1930 repo = hg.peer(ui, opts, repopath)
1877 if not repo.capable(b'known'):
1931 if not repo.capable(b'known'):
1878 raise error.Abort(b"known() not supported by target repository")
1932 raise error.Abort(b"known() not supported by target repository")
1879 flags = repo.known([bin(s) for s in ids])
1933 flags = repo.known([bin(s) for s in ids])
1880 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
1934 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
1881
1935
1882
1936
1883 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
1937 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
1884 def debuglabelcomplete(ui, repo, *args):
1938 def debuglabelcomplete(ui, repo, *args):
1885 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1939 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1886 debugnamecomplete(ui, repo, *args)
1940 debugnamecomplete(ui, repo, *args)
1887
1941
1888
1942
1889 @command(
1943 @command(
1890 b'debuglocks',
1944 b'debuglocks',
1891 [
1945 [
1892 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
1946 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
1893 (
1947 (
1894 b'W',
1948 b'W',
1895 b'force-free-wlock',
1949 b'force-free-wlock',
1896 None,
1950 None,
1897 _(b'free the working state lock (DANGEROUS)'),
1951 _(b'free the working state lock (DANGEROUS)'),
1898 ),
1952 ),
1899 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
1953 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
1900 (
1954 (
1901 b'S',
1955 b'S',
1902 b'set-wlock',
1956 b'set-wlock',
1903 None,
1957 None,
1904 _(b'set the working state lock until stopped'),
1958 _(b'set the working state lock until stopped'),
1905 ),
1959 ),
1906 ],
1960 ],
1907 _(b'[OPTION]...'),
1961 _(b'[OPTION]...'),
1908 )
1962 )
1909 def debuglocks(ui, repo, **opts):
1963 def debuglocks(ui, repo, **opts):
1910 """show or modify state of locks
1964 """show or modify state of locks
1911
1965
1912 By default, this command will show which locks are held. This
1966 By default, this command will show which locks are held. This
1913 includes the user and process holding the lock, the amount of time
1967 includes the user and process holding the lock, the amount of time
1914 the lock has been held, and the machine name where the process is
1968 the lock has been held, and the machine name where the process is
1915 running if it's not local.
1969 running if it's not local.
1916
1970
1917 Locks protect the integrity of Mercurial's data, so should be
1971 Locks protect the integrity of Mercurial's data, so should be
1918 treated with care. System crashes or other interruptions may cause
1972 treated with care. System crashes or other interruptions may cause
1919 locks to not be properly released, though Mercurial will usually
1973 locks to not be properly released, though Mercurial will usually
1920 detect and remove such stale locks automatically.
1974 detect and remove such stale locks automatically.
1921
1975
1922 However, detecting stale locks may not always be possible (for
1976 However, detecting stale locks may not always be possible (for
1923 instance, on a shared filesystem). Removing locks may also be
1977 instance, on a shared filesystem). Removing locks may also be
1924 blocked by filesystem permissions.
1978 blocked by filesystem permissions.
1925
1979
1926 Setting a lock will prevent other commands from changing the data.
1980 Setting a lock will prevent other commands from changing the data.
1927 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1981 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1928 The set locks are removed when the command exits.
1982 The set locks are removed when the command exits.
1929
1983
1930 Returns 0 if no locks are held.
1984 Returns 0 if no locks are held.
1931
1985
1932 """
1986 """
1933
1987
1934 if opts.get('force_free_lock'):
1988 if opts.get('force_free_lock'):
1935 repo.svfs.unlink(b'lock')
1989 repo.svfs.unlink(b'lock')
1936 if opts.get('force_free_wlock'):
1990 if opts.get('force_free_wlock'):
1937 repo.vfs.unlink(b'wlock')
1991 repo.vfs.unlink(b'wlock')
1938 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
1992 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
1939 return 0
1993 return 0
1940
1994
1941 locks = []
1995 locks = []
1942 try:
1996 try:
1943 if opts.get('set_wlock'):
1997 if opts.get('set_wlock'):
1944 try:
1998 try:
1945 locks.append(repo.wlock(False))
1999 locks.append(repo.wlock(False))
1946 except error.LockHeld:
2000 except error.LockHeld:
1947 raise error.Abort(_(b'wlock is already held'))
2001 raise error.Abort(_(b'wlock is already held'))
1948 if opts.get('set_lock'):
2002 if opts.get('set_lock'):
1949 try:
2003 try:
1950 locks.append(repo.lock(False))
2004 locks.append(repo.lock(False))
1951 except error.LockHeld:
2005 except error.LockHeld:
1952 raise error.Abort(_(b'lock is already held'))
2006 raise error.Abort(_(b'lock is already held'))
1953 if len(locks):
2007 if len(locks):
1954 ui.promptchoice(_(b"ready to release the lock (y)? $$ &Yes"))
2008 ui.promptchoice(_(b"ready to release the lock (y)? $$ &Yes"))
1955 return 0
2009 return 0
1956 finally:
2010 finally:
1957 release(*locks)
2011 release(*locks)
1958
2012
1959 now = time.time()
2013 now = time.time()
1960 held = 0
2014 held = 0
1961
2015
1962 def report(vfs, name, method):
2016 def report(vfs, name, method):
1963 # this causes stale locks to get reaped for more accurate reporting
2017 # this causes stale locks to get reaped for more accurate reporting
1964 try:
2018 try:
1965 l = method(False)
2019 l = method(False)
1966 except error.LockHeld:
2020 except error.LockHeld:
1967 l = None
2021 l = None
1968
2022
1969 if l:
2023 if l:
1970 l.release()
2024 l.release()
1971 else:
2025 else:
1972 try:
2026 try:
1973 st = vfs.lstat(name)
2027 st = vfs.lstat(name)
1974 age = now - st[stat.ST_MTIME]
2028 age = now - st[stat.ST_MTIME]
1975 user = util.username(st.st_uid)
2029 user = util.username(st.st_uid)
1976 locker = vfs.readlock(name)
2030 locker = vfs.readlock(name)
1977 if b":" in locker:
2031 if b":" in locker:
1978 host, pid = locker.split(b':')
2032 host, pid = locker.split(b':')
1979 if host == socket.gethostname():
2033 if host == socket.gethostname():
1980 locker = b'user %s, process %s' % (user or b'None', pid)
2034 locker = b'user %s, process %s' % (user or b'None', pid)
1981 else:
2035 else:
1982 locker = b'user %s, process %s, host %s' % (
2036 locker = b'user %s, process %s, host %s' % (
1983 user or b'None',
2037 user or b'None',
1984 pid,
2038 pid,
1985 host,
2039 host,
1986 )
2040 )
1987 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2041 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
1988 return 1
2042 return 1
1989 except OSError as e:
2043 except OSError as e:
1990 if e.errno != errno.ENOENT:
2044 if e.errno != errno.ENOENT:
1991 raise
2045 raise
1992
2046
1993 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2047 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
1994 return 0
2048 return 0
1995
2049
1996 held += report(repo.svfs, b"lock", repo.lock)
2050 held += report(repo.svfs, b"lock", repo.lock)
1997 held += report(repo.vfs, b"wlock", repo.wlock)
2051 held += report(repo.vfs, b"wlock", repo.wlock)
1998
2052
1999 return held
2053 return held
2000
2054
2001
2055
2002 @command(
2056 @command(
2003 b'debugmanifestfulltextcache',
2057 b'debugmanifestfulltextcache',
2004 [
2058 [
2005 (b'', b'clear', False, _(b'clear the cache')),
2059 (b'', b'clear', False, _(b'clear the cache')),
2006 (
2060 (
2007 b'a',
2061 b'a',
2008 b'add',
2062 b'add',
2009 [],
2063 [],
2010 _(b'add the given manifest nodes to the cache'),
2064 _(b'add the given manifest nodes to the cache'),
2011 _(b'NODE'),
2065 _(b'NODE'),
2012 ),
2066 ),
2013 ],
2067 ],
2014 b'',
2068 b'',
2015 )
2069 )
2016 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2070 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2017 """show, clear or amend the contents of the manifest fulltext cache"""
2071 """show, clear or amend the contents of the manifest fulltext cache"""
2018
2072
2019 def getcache():
2073 def getcache():
2020 r = repo.manifestlog.getstorage(b'')
2074 r = repo.manifestlog.getstorage(b'')
2021 try:
2075 try:
2022 return r._fulltextcache
2076 return r._fulltextcache
2023 except AttributeError:
2077 except AttributeError:
2024 msg = _(
2078 msg = _(
2025 b"Current revlog implementation doesn't appear to have a "
2079 b"Current revlog implementation doesn't appear to have a "
2026 b"manifest fulltext cache\n"
2080 b"manifest fulltext cache\n"
2027 )
2081 )
2028 raise error.Abort(msg)
2082 raise error.Abort(msg)
2029
2083
2030 if opts.get('clear'):
2084 if opts.get('clear'):
2031 with repo.wlock():
2085 with repo.wlock():
2032 cache = getcache()
2086 cache = getcache()
2033 cache.clear(clear_persisted_data=True)
2087 cache.clear(clear_persisted_data=True)
2034 return
2088 return
2035
2089
2036 if add:
2090 if add:
2037 with repo.wlock():
2091 with repo.wlock():
2038 m = repo.manifestlog
2092 m = repo.manifestlog
2039 store = m.getstorage(b'')
2093 store = m.getstorage(b'')
2040 for n in add:
2094 for n in add:
2041 try:
2095 try:
2042 manifest = m[store.lookup(n)]
2096 manifest = m[store.lookup(n)]
2043 except error.LookupError as e:
2097 except error.LookupError as e:
2044 raise error.Abort(e, hint=b"Check your manifest node id")
2098 raise error.Abort(e, hint=b"Check your manifest node id")
2045 manifest.read() # stores revisision in cache too
2099 manifest.read() # stores revisision in cache too
2046 return
2100 return
2047
2101
2048 cache = getcache()
2102 cache = getcache()
2049 if not len(cache):
2103 if not len(cache):
2050 ui.write(_(b'cache empty\n'))
2104 ui.write(_(b'cache empty\n'))
2051 else:
2105 else:
2052 ui.write(
2106 ui.write(
2053 _(
2107 _(
2054 b'cache contains %d manifest entries, in order of most to '
2108 b'cache contains %d manifest entries, in order of most to '
2055 b'least recent:\n'
2109 b'least recent:\n'
2056 )
2110 )
2057 % (len(cache),)
2111 % (len(cache),)
2058 )
2112 )
2059 totalsize = 0
2113 totalsize = 0
2060 for nodeid in cache:
2114 for nodeid in cache:
2061 # Use cache.get to not update the LRU order
2115 # Use cache.get to not update the LRU order
2062 data = cache.peek(nodeid)
2116 data = cache.peek(nodeid)
2063 size = len(data)
2117 size = len(data)
2064 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2118 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2065 ui.write(
2119 ui.write(
2066 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2120 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2067 )
2121 )
2068 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2122 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2069 ui.write(
2123 ui.write(
2070 _(b'total cache data size %s, on-disk %s\n')
2124 _(b'total cache data size %s, on-disk %s\n')
2071 % (util.bytecount(totalsize), util.bytecount(ondisk))
2125 % (util.bytecount(totalsize), util.bytecount(ondisk))
2072 )
2126 )
2073
2127
2074
2128
2075 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2129 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2076 def debugmergestate(ui, repo, *args, **opts):
2130 def debugmergestate(ui, repo, *args, **opts):
2077 """print merge state
2131 """print merge state
2078
2132
2079 Use --verbose to print out information about whether v1 or v2 merge state
2133 Use --verbose to print out information about whether v1 or v2 merge state
2080 was chosen."""
2134 was chosen."""
2081
2135
2082 if ui.verbose:
2136 if ui.verbose:
2083 ms = mergestatemod.mergestate(repo)
2137 ms = mergestatemod.mergestate(repo)
2084
2138
2085 # sort so that reasonable information is on top
2139 # sort so that reasonable information is on top
2086 v1records = ms._readrecordsv1()
2140 v1records = ms._readrecordsv1()
2087 v2records = ms._readrecordsv2()
2141 v2records = ms._readrecordsv2()
2088
2142
2089 if not v1records and not v2records:
2143 if not v1records and not v2records:
2090 pass
2144 pass
2091 elif not v2records:
2145 elif not v2records:
2092 ui.writenoi18n(b'no version 2 merge state\n')
2146 ui.writenoi18n(b'no version 2 merge state\n')
2093 elif ms._v1v2match(v1records, v2records):
2147 elif ms._v1v2match(v1records, v2records):
2094 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2148 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2095 else:
2149 else:
2096 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2150 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2097
2151
2098 opts = pycompat.byteskwargs(opts)
2152 opts = pycompat.byteskwargs(opts)
2099 if not opts[b'template']:
2153 if not opts[b'template']:
2100 opts[b'template'] = (
2154 opts[b'template'] = (
2101 b'{if(commits, "", "no merge state found\n")}'
2155 b'{if(commits, "", "no merge state found\n")}'
2102 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2156 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2103 b'{files % "file: {path} (state \\"{state}\\")\n'
2157 b'{files % "file: {path} (state \\"{state}\\")\n'
2104 b'{if(local_path, "'
2158 b'{if(local_path, "'
2105 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2159 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2106 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2160 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2107 b' other path: {other_path} (node {other_node})\n'
2161 b' other path: {other_path} (node {other_node})\n'
2108 b'")}'
2162 b'")}'
2109 b'{if(rename_side, "'
2163 b'{if(rename_side, "'
2110 b' rename side: {rename_side}\n'
2164 b' rename side: {rename_side}\n'
2111 b' renamed path: {renamed_path}\n'
2165 b' renamed path: {renamed_path}\n'
2112 b'")}'
2166 b'")}'
2113 b'{extras % " extra: {key} = {value}\n"}'
2167 b'{extras % " extra: {key} = {value}\n"}'
2114 b'"}'
2168 b'"}'
2115 b'{extras % "extra: {file} ({key} = {value})\n"}'
2169 b'{extras % "extra: {file} ({key} = {value})\n"}'
2116 )
2170 )
2117
2171
2118 ms = mergestatemod.mergestate.read(repo)
2172 ms = mergestatemod.mergestate.read(repo)
2119
2173
2120 fm = ui.formatter(b'debugmergestate', opts)
2174 fm = ui.formatter(b'debugmergestate', opts)
2121 fm.startitem()
2175 fm.startitem()
2122
2176
2123 fm_commits = fm.nested(b'commits')
2177 fm_commits = fm.nested(b'commits')
2124 if ms.active():
2178 if ms.active():
2125 for name, node, label_index in (
2179 for name, node, label_index in (
2126 (b'local', ms.local, 0),
2180 (b'local', ms.local, 0),
2127 (b'other', ms.other, 1),
2181 (b'other', ms.other, 1),
2128 ):
2182 ):
2129 fm_commits.startitem()
2183 fm_commits.startitem()
2130 fm_commits.data(name=name)
2184 fm_commits.data(name=name)
2131 fm_commits.data(node=hex(node))
2185 fm_commits.data(node=hex(node))
2132 if ms._labels and len(ms._labels) > label_index:
2186 if ms._labels and len(ms._labels) > label_index:
2133 fm_commits.data(label=ms._labels[label_index])
2187 fm_commits.data(label=ms._labels[label_index])
2134 fm_commits.end()
2188 fm_commits.end()
2135
2189
2136 fm_files = fm.nested(b'files')
2190 fm_files = fm.nested(b'files')
2137 if ms.active():
2191 if ms.active():
2138 for f in ms:
2192 for f in ms:
2139 fm_files.startitem()
2193 fm_files.startitem()
2140 fm_files.data(path=f)
2194 fm_files.data(path=f)
2141 state = ms._state[f]
2195 state = ms._state[f]
2142 fm_files.data(state=state[0])
2196 fm_files.data(state=state[0])
2143 if state[0] in (
2197 if state[0] in (
2144 mergestatemod.MERGE_RECORD_UNRESOLVED,
2198 mergestatemod.MERGE_RECORD_UNRESOLVED,
2145 mergestatemod.MERGE_RECORD_RESOLVED,
2199 mergestatemod.MERGE_RECORD_RESOLVED,
2146 ):
2200 ):
2147 fm_files.data(local_key=state[1])
2201 fm_files.data(local_key=state[1])
2148 fm_files.data(local_path=state[2])
2202 fm_files.data(local_path=state[2])
2149 fm_files.data(ancestor_path=state[3])
2203 fm_files.data(ancestor_path=state[3])
2150 fm_files.data(ancestor_node=state[4])
2204 fm_files.data(ancestor_node=state[4])
2151 fm_files.data(other_path=state[5])
2205 fm_files.data(other_path=state[5])
2152 fm_files.data(other_node=state[6])
2206 fm_files.data(other_node=state[6])
2153 fm_files.data(local_flags=state[7])
2207 fm_files.data(local_flags=state[7])
2154 elif state[0] in (
2208 elif state[0] in (
2155 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2209 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2156 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2210 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2157 ):
2211 ):
2158 fm_files.data(renamed_path=state[1])
2212 fm_files.data(renamed_path=state[1])
2159 fm_files.data(rename_side=state[2])
2213 fm_files.data(rename_side=state[2])
2160 fm_extras = fm_files.nested(b'extras')
2214 fm_extras = fm_files.nested(b'extras')
2161 for k, v in sorted(ms.extras(f).items()):
2215 for k, v in sorted(ms.extras(f).items()):
2162 fm_extras.startitem()
2216 fm_extras.startitem()
2163 fm_extras.data(key=k)
2217 fm_extras.data(key=k)
2164 fm_extras.data(value=v)
2218 fm_extras.data(value=v)
2165 fm_extras.end()
2219 fm_extras.end()
2166
2220
2167 fm_files.end()
2221 fm_files.end()
2168
2222
2169 fm_extras = fm.nested(b'extras')
2223 fm_extras = fm.nested(b'extras')
2170 for f, d in sorted(pycompat.iteritems(ms.allextras())):
2224 for f, d in sorted(pycompat.iteritems(ms.allextras())):
2171 if f in ms:
2225 if f in ms:
2172 # If file is in mergestate, we have already processed it's extras
2226 # If file is in mergestate, we have already processed it's extras
2173 continue
2227 continue
2174 for k, v in pycompat.iteritems(d):
2228 for k, v in pycompat.iteritems(d):
2175 fm_extras.startitem()
2229 fm_extras.startitem()
2176 fm_extras.data(file=f)
2230 fm_extras.data(file=f)
2177 fm_extras.data(key=k)
2231 fm_extras.data(key=k)
2178 fm_extras.data(value=v)
2232 fm_extras.data(value=v)
2179 fm_extras.end()
2233 fm_extras.end()
2180
2234
2181 fm.end()
2235 fm.end()
2182
2236
2183
2237
2184 @command(b'debugnamecomplete', [], _(b'NAME...'))
2238 @command(b'debugnamecomplete', [], _(b'NAME...'))
2185 def debugnamecomplete(ui, repo, *args):
2239 def debugnamecomplete(ui, repo, *args):
2186 '''complete "names" - tags, open branch names, bookmark names'''
2240 '''complete "names" - tags, open branch names, bookmark names'''
2187
2241
2188 names = set()
2242 names = set()
2189 # since we previously only listed open branches, we will handle that
2243 # since we previously only listed open branches, we will handle that
2190 # specially (after this for loop)
2244 # specially (after this for loop)
2191 for name, ns in pycompat.iteritems(repo.names):
2245 for name, ns in pycompat.iteritems(repo.names):
2192 if name != b'branches':
2246 if name != b'branches':
2193 names.update(ns.listnames(repo))
2247 names.update(ns.listnames(repo))
2194 names.update(
2248 names.update(
2195 tag
2249 tag
2196 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2250 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2197 if not closed
2251 if not closed
2198 )
2252 )
2199 completions = set()
2253 completions = set()
2200 if not args:
2254 if not args:
2201 args = [b'']
2255 args = [b'']
2202 for a in args:
2256 for a in args:
2203 completions.update(n for n in names if n.startswith(a))
2257 completions.update(n for n in names if n.startswith(a))
2204 ui.write(b'\n'.join(sorted(completions)))
2258 ui.write(b'\n'.join(sorted(completions)))
2205 ui.write(b'\n')
2259 ui.write(b'\n')
2206
2260
2207
2261
2208 @command(
2262 @command(
2209 b'debugnodemap',
2263 b'debugnodemap',
2210 [
2264 [
2211 (
2265 (
2212 b'',
2266 b'',
2213 b'dump-new',
2267 b'dump-new',
2214 False,
2268 False,
2215 _(b'write a (new) persistent binary nodemap on stdout'),
2269 _(b'write a (new) persistent binary nodemap on stdout'),
2216 ),
2270 ),
2217 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2271 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2218 (
2272 (
2219 b'',
2273 b'',
2220 b'check',
2274 b'check',
2221 False,
2275 False,
2222 _(b'check that the data on disk data are correct.'),
2276 _(b'check that the data on disk data are correct.'),
2223 ),
2277 ),
2224 (
2278 (
2225 b'',
2279 b'',
2226 b'metadata',
2280 b'metadata',
2227 False,
2281 False,
2228 _(b'display the on disk meta data for the nodemap'),
2282 _(b'display the on disk meta data for the nodemap'),
2229 ),
2283 ),
2230 ],
2284 ],
2231 )
2285 )
2232 def debugnodemap(ui, repo, **opts):
2286 def debugnodemap(ui, repo, **opts):
2233 """write and inspect on disk nodemap"""
2287 """write and inspect on disk nodemap"""
2234 if opts['dump_new']:
2288 if opts['dump_new']:
2235 unfi = repo.unfiltered()
2289 unfi = repo.unfiltered()
2236 cl = unfi.changelog
2290 cl = unfi.changelog
2237 if util.safehasattr(cl.index, "nodemap_data_all"):
2291 if util.safehasattr(cl.index, "nodemap_data_all"):
2238 data = cl.index.nodemap_data_all()
2292 data = cl.index.nodemap_data_all()
2239 else:
2293 else:
2240 data = nodemap.persistent_data(cl.index)
2294 data = nodemap.persistent_data(cl.index)
2241 ui.write(data)
2295 ui.write(data)
2242 elif opts['dump_disk']:
2296 elif opts['dump_disk']:
2243 unfi = repo.unfiltered()
2297 unfi = repo.unfiltered()
2244 cl = unfi.changelog
2298 cl = unfi.changelog
2245 nm_data = nodemap.persisted_data(cl)
2299 nm_data = nodemap.persisted_data(cl)
2246 if nm_data is not None:
2300 if nm_data is not None:
2247 docket, data = nm_data
2301 docket, data = nm_data
2248 ui.write(data[:])
2302 ui.write(data[:])
2249 elif opts['check']:
2303 elif opts['check']:
2250 unfi = repo.unfiltered()
2304 unfi = repo.unfiltered()
2251 cl = unfi.changelog
2305 cl = unfi.changelog
2252 nm_data = nodemap.persisted_data(cl)
2306 nm_data = nodemap.persisted_data(cl)
2253 if nm_data is not None:
2307 if nm_data is not None:
2254 docket, data = nm_data
2308 docket, data = nm_data
2255 return nodemap.check_data(ui, cl.index, data)
2309 return nodemap.check_data(ui, cl.index, data)
2256 elif opts['metadata']:
2310 elif opts['metadata']:
2257 unfi = repo.unfiltered()
2311 unfi = repo.unfiltered()
2258 cl = unfi.changelog
2312 cl = unfi.changelog
2259 nm_data = nodemap.persisted_data(cl)
2313 nm_data = nodemap.persisted_data(cl)
2260 if nm_data is not None:
2314 if nm_data is not None:
2261 docket, data = nm_data
2315 docket, data = nm_data
2262 ui.write((b"uid: %s\n") % docket.uid)
2316 ui.write((b"uid: %s\n") % docket.uid)
2263 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2317 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2264 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2318 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2265 ui.write((b"data-length: %d\n") % docket.data_length)
2319 ui.write((b"data-length: %d\n") % docket.data_length)
2266 ui.write((b"data-unused: %d\n") % docket.data_unused)
2320 ui.write((b"data-unused: %d\n") % docket.data_unused)
2267 unused_perc = docket.data_unused * 100.0 / docket.data_length
2321 unused_perc = docket.data_unused * 100.0 / docket.data_length
2268 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2322 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2269
2323
2270
2324
2271 @command(
2325 @command(
2272 b'debugobsolete',
2326 b'debugobsolete',
2273 [
2327 [
2274 (b'', b'flags', 0, _(b'markers flag')),
2328 (b'', b'flags', 0, _(b'markers flag')),
2275 (
2329 (
2276 b'',
2330 b'',
2277 b'record-parents',
2331 b'record-parents',
2278 False,
2332 False,
2279 _(b'record parent information for the precursor'),
2333 _(b'record parent information for the precursor'),
2280 ),
2334 ),
2281 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2335 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2282 (
2336 (
2283 b'',
2337 b'',
2284 b'exclusive',
2338 b'exclusive',
2285 False,
2339 False,
2286 _(b'restrict display to markers only relevant to REV'),
2340 _(b'restrict display to markers only relevant to REV'),
2287 ),
2341 ),
2288 (b'', b'index', False, _(b'display index of the marker')),
2342 (b'', b'index', False, _(b'display index of the marker')),
2289 (b'', b'delete', [], _(b'delete markers specified by indices')),
2343 (b'', b'delete', [], _(b'delete markers specified by indices')),
2290 ]
2344 ]
2291 + cmdutil.commitopts2
2345 + cmdutil.commitopts2
2292 + cmdutil.formatteropts,
2346 + cmdutil.formatteropts,
2293 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2347 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2294 )
2348 )
2295 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2349 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2296 """create arbitrary obsolete marker
2350 """create arbitrary obsolete marker
2297
2351
2298 With no arguments, displays the list of obsolescence markers."""
2352 With no arguments, displays the list of obsolescence markers."""
2299
2353
2300 opts = pycompat.byteskwargs(opts)
2354 opts = pycompat.byteskwargs(opts)
2301
2355
2302 def parsenodeid(s):
2356 def parsenodeid(s):
2303 try:
2357 try:
2304 # We do not use revsingle/revrange functions here to accept
2358 # We do not use revsingle/revrange functions here to accept
2305 # arbitrary node identifiers, possibly not present in the
2359 # arbitrary node identifiers, possibly not present in the
2306 # local repository.
2360 # local repository.
2307 n = bin(s)
2361 n = bin(s)
2308 if len(n) != len(nullid):
2362 if len(n) != len(nullid):
2309 raise TypeError()
2363 raise TypeError()
2310 return n
2364 return n
2311 except TypeError:
2365 except TypeError:
2312 raise error.InputError(
2366 raise error.InputError(
2313 b'changeset references must be full hexadecimal '
2367 b'changeset references must be full hexadecimal '
2314 b'node identifiers'
2368 b'node identifiers'
2315 )
2369 )
2316
2370
2317 if opts.get(b'delete'):
2371 if opts.get(b'delete'):
2318 indices = []
2372 indices = []
2319 for v in opts.get(b'delete'):
2373 for v in opts.get(b'delete'):
2320 try:
2374 try:
2321 indices.append(int(v))
2375 indices.append(int(v))
2322 except ValueError:
2376 except ValueError:
2323 raise error.InputError(
2377 raise error.InputError(
2324 _(b'invalid index value: %r') % v,
2378 _(b'invalid index value: %r') % v,
2325 hint=_(b'use integers for indices'),
2379 hint=_(b'use integers for indices'),
2326 )
2380 )
2327
2381
2328 if repo.currenttransaction():
2382 if repo.currenttransaction():
2329 raise error.Abort(
2383 raise error.Abort(
2330 _(b'cannot delete obsmarkers in the middle of transaction.')
2384 _(b'cannot delete obsmarkers in the middle of transaction.')
2331 )
2385 )
2332
2386
2333 with repo.lock():
2387 with repo.lock():
2334 n = repair.deleteobsmarkers(repo.obsstore, indices)
2388 n = repair.deleteobsmarkers(repo.obsstore, indices)
2335 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2389 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2336
2390
2337 return
2391 return
2338
2392
2339 if precursor is not None:
2393 if precursor is not None:
2340 if opts[b'rev']:
2394 if opts[b'rev']:
2341 raise error.InputError(
2395 raise error.InputError(
2342 b'cannot select revision when creating marker'
2396 b'cannot select revision when creating marker'
2343 )
2397 )
2344 metadata = {}
2398 metadata = {}
2345 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2399 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2346 succs = tuple(parsenodeid(succ) for succ in successors)
2400 succs = tuple(parsenodeid(succ) for succ in successors)
2347 l = repo.lock()
2401 l = repo.lock()
2348 try:
2402 try:
2349 tr = repo.transaction(b'debugobsolete')
2403 tr = repo.transaction(b'debugobsolete')
2350 try:
2404 try:
2351 date = opts.get(b'date')
2405 date = opts.get(b'date')
2352 if date:
2406 if date:
2353 date = dateutil.parsedate(date)
2407 date = dateutil.parsedate(date)
2354 else:
2408 else:
2355 date = None
2409 date = None
2356 prec = parsenodeid(precursor)
2410 prec = parsenodeid(precursor)
2357 parents = None
2411 parents = None
2358 if opts[b'record_parents']:
2412 if opts[b'record_parents']:
2359 if prec not in repo.unfiltered():
2413 if prec not in repo.unfiltered():
2360 raise error.Abort(
2414 raise error.Abort(
2361 b'cannot used --record-parents on '
2415 b'cannot used --record-parents on '
2362 b'unknown changesets'
2416 b'unknown changesets'
2363 )
2417 )
2364 parents = repo.unfiltered()[prec].parents()
2418 parents = repo.unfiltered()[prec].parents()
2365 parents = tuple(p.node() for p in parents)
2419 parents = tuple(p.node() for p in parents)
2366 repo.obsstore.create(
2420 repo.obsstore.create(
2367 tr,
2421 tr,
2368 prec,
2422 prec,
2369 succs,
2423 succs,
2370 opts[b'flags'],
2424 opts[b'flags'],
2371 parents=parents,
2425 parents=parents,
2372 date=date,
2426 date=date,
2373 metadata=metadata,
2427 metadata=metadata,
2374 ui=ui,
2428 ui=ui,
2375 )
2429 )
2376 tr.close()
2430 tr.close()
2377 except ValueError as exc:
2431 except ValueError as exc:
2378 raise error.Abort(
2432 raise error.Abort(
2379 _(b'bad obsmarker input: %s') % pycompat.bytestr(exc)
2433 _(b'bad obsmarker input: %s') % pycompat.bytestr(exc)
2380 )
2434 )
2381 finally:
2435 finally:
2382 tr.release()
2436 tr.release()
2383 finally:
2437 finally:
2384 l.release()
2438 l.release()
2385 else:
2439 else:
2386 if opts[b'rev']:
2440 if opts[b'rev']:
2387 revs = scmutil.revrange(repo, opts[b'rev'])
2441 revs = scmutil.revrange(repo, opts[b'rev'])
2388 nodes = [repo[r].node() for r in revs]
2442 nodes = [repo[r].node() for r in revs]
2389 markers = list(
2443 markers = list(
2390 obsutil.getmarkers(
2444 obsutil.getmarkers(
2391 repo, nodes=nodes, exclusive=opts[b'exclusive']
2445 repo, nodes=nodes, exclusive=opts[b'exclusive']
2392 )
2446 )
2393 )
2447 )
2394 markers.sort(key=lambda x: x._data)
2448 markers.sort(key=lambda x: x._data)
2395 else:
2449 else:
2396 markers = obsutil.getmarkers(repo)
2450 markers = obsutil.getmarkers(repo)
2397
2451
2398 markerstoiter = markers
2452 markerstoiter = markers
2399 isrelevant = lambda m: True
2453 isrelevant = lambda m: True
2400 if opts.get(b'rev') and opts.get(b'index'):
2454 if opts.get(b'rev') and opts.get(b'index'):
2401 markerstoiter = obsutil.getmarkers(repo)
2455 markerstoiter = obsutil.getmarkers(repo)
2402 markerset = set(markers)
2456 markerset = set(markers)
2403 isrelevant = lambda m: m in markerset
2457 isrelevant = lambda m: m in markerset
2404
2458
2405 fm = ui.formatter(b'debugobsolete', opts)
2459 fm = ui.formatter(b'debugobsolete', opts)
2406 for i, m in enumerate(markerstoiter):
2460 for i, m in enumerate(markerstoiter):
2407 if not isrelevant(m):
2461 if not isrelevant(m):
2408 # marker can be irrelevant when we're iterating over a set
2462 # marker can be irrelevant when we're iterating over a set
2409 # of markers (markerstoiter) which is bigger than the set
2463 # of markers (markerstoiter) which is bigger than the set
2410 # of markers we want to display (markers)
2464 # of markers we want to display (markers)
2411 # this can happen if both --index and --rev options are
2465 # this can happen if both --index and --rev options are
2412 # provided and thus we need to iterate over all of the markers
2466 # provided and thus we need to iterate over all of the markers
2413 # to get the correct indices, but only display the ones that
2467 # to get the correct indices, but only display the ones that
2414 # are relevant to --rev value
2468 # are relevant to --rev value
2415 continue
2469 continue
2416 fm.startitem()
2470 fm.startitem()
2417 ind = i if opts.get(b'index') else None
2471 ind = i if opts.get(b'index') else None
2418 cmdutil.showmarker(fm, m, index=ind)
2472 cmdutil.showmarker(fm, m, index=ind)
2419 fm.end()
2473 fm.end()
2420
2474
2421
2475
2422 @command(
2476 @command(
2423 b'debugp1copies',
2477 b'debugp1copies',
2424 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2478 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2425 _(b'[-r REV]'),
2479 _(b'[-r REV]'),
2426 )
2480 )
2427 def debugp1copies(ui, repo, **opts):
2481 def debugp1copies(ui, repo, **opts):
2428 """dump copy information compared to p1"""
2482 """dump copy information compared to p1"""
2429
2483
2430 opts = pycompat.byteskwargs(opts)
2484 opts = pycompat.byteskwargs(opts)
2431 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2485 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2432 for dst, src in ctx.p1copies().items():
2486 for dst, src in ctx.p1copies().items():
2433 ui.write(b'%s -> %s\n' % (src, dst))
2487 ui.write(b'%s -> %s\n' % (src, dst))
2434
2488
2435
2489
2436 @command(
2490 @command(
2437 b'debugp2copies',
2491 b'debugp2copies',
2438 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2492 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2439 _(b'[-r REV]'),
2493 _(b'[-r REV]'),
2440 )
2494 )
2441 def debugp1copies(ui, repo, **opts):
2495 def debugp1copies(ui, repo, **opts):
2442 """dump copy information compared to p2"""
2496 """dump copy information compared to p2"""
2443
2497
2444 opts = pycompat.byteskwargs(opts)
2498 opts = pycompat.byteskwargs(opts)
2445 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2499 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2446 for dst, src in ctx.p2copies().items():
2500 for dst, src in ctx.p2copies().items():
2447 ui.write(b'%s -> %s\n' % (src, dst))
2501 ui.write(b'%s -> %s\n' % (src, dst))
2448
2502
2449
2503
2450 @command(
2504 @command(
2451 b'debugpathcomplete',
2505 b'debugpathcomplete',
2452 [
2506 [
2453 (b'f', b'full', None, _(b'complete an entire path')),
2507 (b'f', b'full', None, _(b'complete an entire path')),
2454 (b'n', b'normal', None, _(b'show only normal files')),
2508 (b'n', b'normal', None, _(b'show only normal files')),
2455 (b'a', b'added', None, _(b'show only added files')),
2509 (b'a', b'added', None, _(b'show only added files')),
2456 (b'r', b'removed', None, _(b'show only removed files')),
2510 (b'r', b'removed', None, _(b'show only removed files')),
2457 ],
2511 ],
2458 _(b'FILESPEC...'),
2512 _(b'FILESPEC...'),
2459 )
2513 )
2460 def debugpathcomplete(ui, repo, *specs, **opts):
2514 def debugpathcomplete(ui, repo, *specs, **opts):
2461 """complete part or all of a tracked path
2515 """complete part or all of a tracked path
2462
2516
2463 This command supports shells that offer path name completion. It
2517 This command supports shells that offer path name completion. It
2464 currently completes only files already known to the dirstate.
2518 currently completes only files already known to the dirstate.
2465
2519
2466 Completion extends only to the next path segment unless
2520 Completion extends only to the next path segment unless
2467 --full is specified, in which case entire paths are used."""
2521 --full is specified, in which case entire paths are used."""
2468
2522
2469 def complete(path, acceptable):
2523 def complete(path, acceptable):
2470 dirstate = repo.dirstate
2524 dirstate = repo.dirstate
2471 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2525 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2472 rootdir = repo.root + pycompat.ossep
2526 rootdir = repo.root + pycompat.ossep
2473 if spec != repo.root and not spec.startswith(rootdir):
2527 if spec != repo.root and not spec.startswith(rootdir):
2474 return [], []
2528 return [], []
2475 if os.path.isdir(spec):
2529 if os.path.isdir(spec):
2476 spec += b'/'
2530 spec += b'/'
2477 spec = spec[len(rootdir) :]
2531 spec = spec[len(rootdir) :]
2478 fixpaths = pycompat.ossep != b'/'
2532 fixpaths = pycompat.ossep != b'/'
2479 if fixpaths:
2533 if fixpaths:
2480 spec = spec.replace(pycompat.ossep, b'/')
2534 spec = spec.replace(pycompat.ossep, b'/')
2481 speclen = len(spec)
2535 speclen = len(spec)
2482 fullpaths = opts['full']
2536 fullpaths = opts['full']
2483 files, dirs = set(), set()
2537 files, dirs = set(), set()
2484 adddir, addfile = dirs.add, files.add
2538 adddir, addfile = dirs.add, files.add
2485 for f, st in pycompat.iteritems(dirstate):
2539 for f, st in pycompat.iteritems(dirstate):
2486 if f.startswith(spec) and st[0] in acceptable:
2540 if f.startswith(spec) and st[0] in acceptable:
2487 if fixpaths:
2541 if fixpaths:
2488 f = f.replace(b'/', pycompat.ossep)
2542 f = f.replace(b'/', pycompat.ossep)
2489 if fullpaths:
2543 if fullpaths:
2490 addfile(f)
2544 addfile(f)
2491 continue
2545 continue
2492 s = f.find(pycompat.ossep, speclen)
2546 s = f.find(pycompat.ossep, speclen)
2493 if s >= 0:
2547 if s >= 0:
2494 adddir(f[:s])
2548 adddir(f[:s])
2495 else:
2549 else:
2496 addfile(f)
2550 addfile(f)
2497 return files, dirs
2551 return files, dirs
2498
2552
2499 acceptable = b''
2553 acceptable = b''
2500 if opts['normal']:
2554 if opts['normal']:
2501 acceptable += b'nm'
2555 acceptable += b'nm'
2502 if opts['added']:
2556 if opts['added']:
2503 acceptable += b'a'
2557 acceptable += b'a'
2504 if opts['removed']:
2558 if opts['removed']:
2505 acceptable += b'r'
2559 acceptable += b'r'
2506 cwd = repo.getcwd()
2560 cwd = repo.getcwd()
2507 if not specs:
2561 if not specs:
2508 specs = [b'.']
2562 specs = [b'.']
2509
2563
2510 files, dirs = set(), set()
2564 files, dirs = set(), set()
2511 for spec in specs:
2565 for spec in specs:
2512 f, d = complete(spec, acceptable or b'nmar')
2566 f, d = complete(spec, acceptable or b'nmar')
2513 files.update(f)
2567 files.update(f)
2514 dirs.update(d)
2568 dirs.update(d)
2515 files.update(dirs)
2569 files.update(dirs)
2516 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2570 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2517 ui.write(b'\n')
2571 ui.write(b'\n')
2518
2572
2519
2573
2520 @command(
2574 @command(
2521 b'debugpathcopies',
2575 b'debugpathcopies',
2522 cmdutil.walkopts,
2576 cmdutil.walkopts,
2523 b'hg debugpathcopies REV1 REV2 [FILE]',
2577 b'hg debugpathcopies REV1 REV2 [FILE]',
2524 inferrepo=True,
2578 inferrepo=True,
2525 )
2579 )
2526 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2580 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2527 """show copies between two revisions"""
2581 """show copies between two revisions"""
2528 ctx1 = scmutil.revsingle(repo, rev1)
2582 ctx1 = scmutil.revsingle(repo, rev1)
2529 ctx2 = scmutil.revsingle(repo, rev2)
2583 ctx2 = scmutil.revsingle(repo, rev2)
2530 m = scmutil.match(ctx1, pats, opts)
2584 m = scmutil.match(ctx1, pats, opts)
2531 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2585 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2532 ui.write(b'%s -> %s\n' % (src, dst))
2586 ui.write(b'%s -> %s\n' % (src, dst))
2533
2587
2534
2588
2535 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2589 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2536 def debugpeer(ui, path):
2590 def debugpeer(ui, path):
2537 """establish a connection to a peer repository"""
2591 """establish a connection to a peer repository"""
2538 # Always enable peer request logging. Requires --debug to display
2592 # Always enable peer request logging. Requires --debug to display
2539 # though.
2593 # though.
2540 overrides = {
2594 overrides = {
2541 (b'devel', b'debug.peer-request'): True,
2595 (b'devel', b'debug.peer-request'): True,
2542 }
2596 }
2543
2597
2544 with ui.configoverride(overrides):
2598 with ui.configoverride(overrides):
2545 peer = hg.peer(ui, {}, path)
2599 peer = hg.peer(ui, {}, path)
2546
2600
2547 local = peer.local() is not None
2601 local = peer.local() is not None
2548 canpush = peer.canpush()
2602 canpush = peer.canpush()
2549
2603
2550 ui.write(_(b'url: %s\n') % peer.url())
2604 ui.write(_(b'url: %s\n') % peer.url())
2551 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2605 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2552 ui.write(_(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no')))
2606 ui.write(_(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no')))
2553
2607
2554
2608
2555 @command(
2609 @command(
2556 b'debugpickmergetool',
2610 b'debugpickmergetool',
2557 [
2611 [
2558 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2612 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2559 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2613 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2560 ]
2614 ]
2561 + cmdutil.walkopts
2615 + cmdutil.walkopts
2562 + cmdutil.mergetoolopts,
2616 + cmdutil.mergetoolopts,
2563 _(b'[PATTERN]...'),
2617 _(b'[PATTERN]...'),
2564 inferrepo=True,
2618 inferrepo=True,
2565 )
2619 )
2566 def debugpickmergetool(ui, repo, *pats, **opts):
2620 def debugpickmergetool(ui, repo, *pats, **opts):
2567 """examine which merge tool is chosen for specified file
2621 """examine which merge tool is chosen for specified file
2568
2622
2569 As described in :hg:`help merge-tools`, Mercurial examines
2623 As described in :hg:`help merge-tools`, Mercurial examines
2570 configurations below in this order to decide which merge tool is
2624 configurations below in this order to decide which merge tool is
2571 chosen for specified file.
2625 chosen for specified file.
2572
2626
2573 1. ``--tool`` option
2627 1. ``--tool`` option
2574 2. ``HGMERGE`` environment variable
2628 2. ``HGMERGE`` environment variable
2575 3. configurations in ``merge-patterns`` section
2629 3. configurations in ``merge-patterns`` section
2576 4. configuration of ``ui.merge``
2630 4. configuration of ``ui.merge``
2577 5. configurations in ``merge-tools`` section
2631 5. configurations in ``merge-tools`` section
2578 6. ``hgmerge`` tool (for historical reason only)
2632 6. ``hgmerge`` tool (for historical reason only)
2579 7. default tool for fallback (``:merge`` or ``:prompt``)
2633 7. default tool for fallback (``:merge`` or ``:prompt``)
2580
2634
2581 This command writes out examination result in the style below::
2635 This command writes out examination result in the style below::
2582
2636
2583 FILE = MERGETOOL
2637 FILE = MERGETOOL
2584
2638
2585 By default, all files known in the first parent context of the
2639 By default, all files known in the first parent context of the
2586 working directory are examined. Use file patterns and/or -I/-X
2640 working directory are examined. Use file patterns and/or -I/-X
2587 options to limit target files. -r/--rev is also useful to examine
2641 options to limit target files. -r/--rev is also useful to examine
2588 files in another context without actual updating to it.
2642 files in another context without actual updating to it.
2589
2643
2590 With --debug, this command shows warning messages while matching
2644 With --debug, this command shows warning messages while matching
2591 against ``merge-patterns`` and so on, too. It is recommended to
2645 against ``merge-patterns`` and so on, too. It is recommended to
2592 use this option with explicit file patterns and/or -I/-X options,
2646 use this option with explicit file patterns and/or -I/-X options,
2593 because this option increases amount of output per file according
2647 because this option increases amount of output per file according
2594 to configurations in hgrc.
2648 to configurations in hgrc.
2595
2649
2596 With -v/--verbose, this command shows configurations below at
2650 With -v/--verbose, this command shows configurations below at
2597 first (only if specified).
2651 first (only if specified).
2598
2652
2599 - ``--tool`` option
2653 - ``--tool`` option
2600 - ``HGMERGE`` environment variable
2654 - ``HGMERGE`` environment variable
2601 - configuration of ``ui.merge``
2655 - configuration of ``ui.merge``
2602
2656
2603 If merge tool is chosen before matching against
2657 If merge tool is chosen before matching against
2604 ``merge-patterns``, this command can't show any helpful
2658 ``merge-patterns``, this command can't show any helpful
2605 information, even with --debug. In such case, information above is
2659 information, even with --debug. In such case, information above is
2606 useful to know why a merge tool is chosen.
2660 useful to know why a merge tool is chosen.
2607 """
2661 """
2608 opts = pycompat.byteskwargs(opts)
2662 opts = pycompat.byteskwargs(opts)
2609 overrides = {}
2663 overrides = {}
2610 if opts[b'tool']:
2664 if opts[b'tool']:
2611 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
2665 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
2612 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
2666 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
2613
2667
2614 with ui.configoverride(overrides, b'debugmergepatterns'):
2668 with ui.configoverride(overrides, b'debugmergepatterns'):
2615 hgmerge = encoding.environ.get(b"HGMERGE")
2669 hgmerge = encoding.environ.get(b"HGMERGE")
2616 if hgmerge is not None:
2670 if hgmerge is not None:
2617 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2671 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2618 uimerge = ui.config(b"ui", b"merge")
2672 uimerge = ui.config(b"ui", b"merge")
2619 if uimerge:
2673 if uimerge:
2620 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2674 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2621
2675
2622 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2676 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2623 m = scmutil.match(ctx, pats, opts)
2677 m = scmutil.match(ctx, pats, opts)
2624 changedelete = opts[b'changedelete']
2678 changedelete = opts[b'changedelete']
2625 for path in ctx.walk(m):
2679 for path in ctx.walk(m):
2626 fctx = ctx[path]
2680 fctx = ctx[path]
2627 try:
2681 try:
2628 if not ui.debugflag:
2682 if not ui.debugflag:
2629 ui.pushbuffer(error=True)
2683 ui.pushbuffer(error=True)
2630 tool, toolpath = filemerge._picktool(
2684 tool, toolpath = filemerge._picktool(
2631 repo,
2685 repo,
2632 ui,
2686 ui,
2633 path,
2687 path,
2634 fctx.isbinary(),
2688 fctx.isbinary(),
2635 b'l' in fctx.flags(),
2689 b'l' in fctx.flags(),
2636 changedelete,
2690 changedelete,
2637 )
2691 )
2638 finally:
2692 finally:
2639 if not ui.debugflag:
2693 if not ui.debugflag:
2640 ui.popbuffer()
2694 ui.popbuffer()
2641 ui.write(b'%s = %s\n' % (path, tool))
2695 ui.write(b'%s = %s\n' % (path, tool))
2642
2696
2643
2697
2644 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2698 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2645 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2699 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2646 """access the pushkey key/value protocol
2700 """access the pushkey key/value protocol
2647
2701
2648 With two args, list the keys in the given namespace.
2702 With two args, list the keys in the given namespace.
2649
2703
2650 With five args, set a key to new if it currently is set to old.
2704 With five args, set a key to new if it currently is set to old.
2651 Reports success or failure.
2705 Reports success or failure.
2652 """
2706 """
2653
2707
2654 target = hg.peer(ui, {}, repopath)
2708 target = hg.peer(ui, {}, repopath)
2655 if keyinfo:
2709 if keyinfo:
2656 key, old, new = keyinfo
2710 key, old, new = keyinfo
2657 with target.commandexecutor() as e:
2711 with target.commandexecutor() as e:
2658 r = e.callcommand(
2712 r = e.callcommand(
2659 b'pushkey',
2713 b'pushkey',
2660 {
2714 {
2661 b'namespace': namespace,
2715 b'namespace': namespace,
2662 b'key': key,
2716 b'key': key,
2663 b'old': old,
2717 b'old': old,
2664 b'new': new,
2718 b'new': new,
2665 },
2719 },
2666 ).result()
2720 ).result()
2667
2721
2668 ui.status(pycompat.bytestr(r) + b'\n')
2722 ui.status(pycompat.bytestr(r) + b'\n')
2669 return not r
2723 return not r
2670 else:
2724 else:
2671 for k, v in sorted(pycompat.iteritems(target.listkeys(namespace))):
2725 for k, v in sorted(pycompat.iteritems(target.listkeys(namespace))):
2672 ui.write(
2726 ui.write(
2673 b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
2727 b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
2674 )
2728 )
2675
2729
2676
2730
2677 @command(b'debugpvec', [], _(b'A B'))
2731 @command(b'debugpvec', [], _(b'A B'))
2678 def debugpvec(ui, repo, a, b=None):
2732 def debugpvec(ui, repo, a, b=None):
2679 ca = scmutil.revsingle(repo, a)
2733 ca = scmutil.revsingle(repo, a)
2680 cb = scmutil.revsingle(repo, b)
2734 cb = scmutil.revsingle(repo, b)
2681 pa = pvec.ctxpvec(ca)
2735 pa = pvec.ctxpvec(ca)
2682 pb = pvec.ctxpvec(cb)
2736 pb = pvec.ctxpvec(cb)
2683 if pa == pb:
2737 if pa == pb:
2684 rel = b"="
2738 rel = b"="
2685 elif pa > pb:
2739 elif pa > pb:
2686 rel = b">"
2740 rel = b">"
2687 elif pa < pb:
2741 elif pa < pb:
2688 rel = b"<"
2742 rel = b"<"
2689 elif pa | pb:
2743 elif pa | pb:
2690 rel = b"|"
2744 rel = b"|"
2691 ui.write(_(b"a: %s\n") % pa)
2745 ui.write(_(b"a: %s\n") % pa)
2692 ui.write(_(b"b: %s\n") % pb)
2746 ui.write(_(b"b: %s\n") % pb)
2693 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2747 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2694 ui.write(
2748 ui.write(
2695 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
2749 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
2696 % (
2750 % (
2697 abs(pa._depth - pb._depth),
2751 abs(pa._depth - pb._depth),
2698 pvec._hamming(pa._vec, pb._vec),
2752 pvec._hamming(pa._vec, pb._vec),
2699 pa.distance(pb),
2753 pa.distance(pb),
2700 rel,
2754 rel,
2701 )
2755 )
2702 )
2756 )
2703
2757
2704
2758
2705 @command(
2759 @command(
2706 b'debugrebuilddirstate|debugrebuildstate',
2760 b'debugrebuilddirstate|debugrebuildstate',
2707 [
2761 [
2708 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
2762 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
2709 (
2763 (
2710 b'',
2764 b'',
2711 b'minimal',
2765 b'minimal',
2712 None,
2766 None,
2713 _(
2767 _(
2714 b'only rebuild files that are inconsistent with '
2768 b'only rebuild files that are inconsistent with '
2715 b'the working copy parent'
2769 b'the working copy parent'
2716 ),
2770 ),
2717 ),
2771 ),
2718 ],
2772 ],
2719 _(b'[-r REV]'),
2773 _(b'[-r REV]'),
2720 )
2774 )
2721 def debugrebuilddirstate(ui, repo, rev, **opts):
2775 def debugrebuilddirstate(ui, repo, rev, **opts):
2722 """rebuild the dirstate as it would look like for the given revision
2776 """rebuild the dirstate as it would look like for the given revision
2723
2777
2724 If no revision is specified the first current parent will be used.
2778 If no revision is specified the first current parent will be used.
2725
2779
2726 The dirstate will be set to the files of the given revision.
2780 The dirstate will be set to the files of the given revision.
2727 The actual working directory content or existing dirstate
2781 The actual working directory content or existing dirstate
2728 information such as adds or removes is not considered.
2782 information such as adds or removes is not considered.
2729
2783
2730 ``minimal`` will only rebuild the dirstate status for files that claim to be
2784 ``minimal`` will only rebuild the dirstate status for files that claim to be
2731 tracked but are not in the parent manifest, or that exist in the parent
2785 tracked but are not in the parent manifest, or that exist in the parent
2732 manifest but are not in the dirstate. It will not change adds, removes, or
2786 manifest but are not in the dirstate. It will not change adds, removes, or
2733 modified files that are in the working copy parent.
2787 modified files that are in the working copy parent.
2734
2788
2735 One use of this command is to make the next :hg:`status` invocation
2789 One use of this command is to make the next :hg:`status` invocation
2736 check the actual file content.
2790 check the actual file content.
2737 """
2791 """
2738 ctx = scmutil.revsingle(repo, rev)
2792 ctx = scmutil.revsingle(repo, rev)
2739 with repo.wlock():
2793 with repo.wlock():
2740 dirstate = repo.dirstate
2794 dirstate = repo.dirstate
2741 changedfiles = None
2795 changedfiles = None
2742 # See command doc for what minimal does.
2796 # See command doc for what minimal does.
2743 if opts.get('minimal'):
2797 if opts.get('minimal'):
2744 manifestfiles = set(ctx.manifest().keys())
2798 manifestfiles = set(ctx.manifest().keys())
2745 dirstatefiles = set(dirstate)
2799 dirstatefiles = set(dirstate)
2746 manifestonly = manifestfiles - dirstatefiles
2800 manifestonly = manifestfiles - dirstatefiles
2747 dsonly = dirstatefiles - manifestfiles
2801 dsonly = dirstatefiles - manifestfiles
2748 dsnotadded = {f for f in dsonly if dirstate[f] != b'a'}
2802 dsnotadded = {f for f in dsonly if dirstate[f] != b'a'}
2749 changedfiles = manifestonly | dsnotadded
2803 changedfiles = manifestonly | dsnotadded
2750
2804
2751 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2805 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2752
2806
2753
2807
2754 @command(b'debugrebuildfncache', [], b'')
2808 @command(b'debugrebuildfncache', [], b'')
2755 def debugrebuildfncache(ui, repo):
2809 def debugrebuildfncache(ui, repo):
2756 """rebuild the fncache file"""
2810 """rebuild the fncache file"""
2757 repair.rebuildfncache(ui, repo)
2811 repair.rebuildfncache(ui, repo)
2758
2812
2759
2813
2760 @command(
2814 @command(
2761 b'debugrename',
2815 b'debugrename',
2762 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2816 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2763 _(b'[-r REV] [FILE]...'),
2817 _(b'[-r REV] [FILE]...'),
2764 )
2818 )
2765 def debugrename(ui, repo, *pats, **opts):
2819 def debugrename(ui, repo, *pats, **opts):
2766 """dump rename information"""
2820 """dump rename information"""
2767
2821
2768 opts = pycompat.byteskwargs(opts)
2822 opts = pycompat.byteskwargs(opts)
2769 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2823 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2770 m = scmutil.match(ctx, pats, opts)
2824 m = scmutil.match(ctx, pats, opts)
2771 for abs in ctx.walk(m):
2825 for abs in ctx.walk(m):
2772 fctx = ctx[abs]
2826 fctx = ctx[abs]
2773 o = fctx.filelog().renamed(fctx.filenode())
2827 o = fctx.filelog().renamed(fctx.filenode())
2774 rel = repo.pathto(abs)
2828 rel = repo.pathto(abs)
2775 if o:
2829 if o:
2776 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2830 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2777 else:
2831 else:
2778 ui.write(_(b"%s not renamed\n") % rel)
2832 ui.write(_(b"%s not renamed\n") % rel)
2779
2833
2780
2834
2781 @command(b'debugrequires|debugrequirements', [], b'')
2835 @command(b'debugrequires|debugrequirements', [], b'')
2782 def debugrequirements(ui, repo):
2836 def debugrequirements(ui, repo):
2783 """ print the current repo requirements """
2837 """ print the current repo requirements """
2784 for r in sorted(repo.requirements):
2838 for r in sorted(repo.requirements):
2785 ui.write(b"%s\n" % r)
2839 ui.write(b"%s\n" % r)
2786
2840
2787
2841
2788 @command(
2842 @command(
2789 b'debugrevlog',
2843 b'debugrevlog',
2790 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
2844 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
2791 _(b'-c|-m|FILE'),
2845 _(b'-c|-m|FILE'),
2792 optionalrepo=True,
2846 optionalrepo=True,
2793 )
2847 )
2794 def debugrevlog(ui, repo, file_=None, **opts):
2848 def debugrevlog(ui, repo, file_=None, **opts):
2795 """show data and statistics about a revlog"""
2849 """show data and statistics about a revlog"""
2796 opts = pycompat.byteskwargs(opts)
2850 opts = pycompat.byteskwargs(opts)
2797 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
2851 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
2798
2852
2799 if opts.get(b"dump"):
2853 if opts.get(b"dump"):
2800 numrevs = len(r)
2854 numrevs = len(r)
2801 ui.write(
2855 ui.write(
2802 (
2856 (
2803 b"# rev p1rev p2rev start end deltastart base p1 p2"
2857 b"# rev p1rev p2rev start end deltastart base p1 p2"
2804 b" rawsize totalsize compression heads chainlen\n"
2858 b" rawsize totalsize compression heads chainlen\n"
2805 )
2859 )
2806 )
2860 )
2807 ts = 0
2861 ts = 0
2808 heads = set()
2862 heads = set()
2809
2863
2810 for rev in pycompat.xrange(numrevs):
2864 for rev in pycompat.xrange(numrevs):
2811 dbase = r.deltaparent(rev)
2865 dbase = r.deltaparent(rev)
2812 if dbase == -1:
2866 if dbase == -1:
2813 dbase = rev
2867 dbase = rev
2814 cbase = r.chainbase(rev)
2868 cbase = r.chainbase(rev)
2815 clen = r.chainlen(rev)
2869 clen = r.chainlen(rev)
2816 p1, p2 = r.parentrevs(rev)
2870 p1, p2 = r.parentrevs(rev)
2817 rs = r.rawsize(rev)
2871 rs = r.rawsize(rev)
2818 ts = ts + rs
2872 ts = ts + rs
2819 heads -= set(r.parentrevs(rev))
2873 heads -= set(r.parentrevs(rev))
2820 heads.add(rev)
2874 heads.add(rev)
2821 try:
2875 try:
2822 compression = ts / r.end(rev)
2876 compression = ts / r.end(rev)
2823 except ZeroDivisionError:
2877 except ZeroDivisionError:
2824 compression = 0
2878 compression = 0
2825 ui.write(
2879 ui.write(
2826 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2880 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2827 b"%11d %5d %8d\n"
2881 b"%11d %5d %8d\n"
2828 % (
2882 % (
2829 rev,
2883 rev,
2830 p1,
2884 p1,
2831 p2,
2885 p2,
2832 r.start(rev),
2886 r.start(rev),
2833 r.end(rev),
2887 r.end(rev),
2834 r.start(dbase),
2888 r.start(dbase),
2835 r.start(cbase),
2889 r.start(cbase),
2836 r.start(p1),
2890 r.start(p1),
2837 r.start(p2),
2891 r.start(p2),
2838 rs,
2892 rs,
2839 ts,
2893 ts,
2840 compression,
2894 compression,
2841 len(heads),
2895 len(heads),
2842 clen,
2896 clen,
2843 )
2897 )
2844 )
2898 )
2845 return 0
2899 return 0
2846
2900
2847 v = r.version
2901 v = r.version
2848 format = v & 0xFFFF
2902 format = v & 0xFFFF
2849 flags = []
2903 flags = []
2850 gdelta = False
2904 gdelta = False
2851 if v & revlog.FLAG_INLINE_DATA:
2905 if v & revlog.FLAG_INLINE_DATA:
2852 flags.append(b'inline')
2906 flags.append(b'inline')
2853 if v & revlog.FLAG_GENERALDELTA:
2907 if v & revlog.FLAG_GENERALDELTA:
2854 gdelta = True
2908 gdelta = True
2855 flags.append(b'generaldelta')
2909 flags.append(b'generaldelta')
2856 if not flags:
2910 if not flags:
2857 flags = [b'(none)']
2911 flags = [b'(none)']
2858
2912
2859 ### tracks merge vs single parent
2913 ### tracks merge vs single parent
2860 nummerges = 0
2914 nummerges = 0
2861
2915
2862 ### tracks ways the "delta" are build
2916 ### tracks ways the "delta" are build
2863 # nodelta
2917 # nodelta
2864 numempty = 0
2918 numempty = 0
2865 numemptytext = 0
2919 numemptytext = 0
2866 numemptydelta = 0
2920 numemptydelta = 0
2867 # full file content
2921 # full file content
2868 numfull = 0
2922 numfull = 0
2869 # intermediate snapshot against a prior snapshot
2923 # intermediate snapshot against a prior snapshot
2870 numsemi = 0
2924 numsemi = 0
2871 # snapshot count per depth
2925 # snapshot count per depth
2872 numsnapdepth = collections.defaultdict(lambda: 0)
2926 numsnapdepth = collections.defaultdict(lambda: 0)
2873 # delta against previous revision
2927 # delta against previous revision
2874 numprev = 0
2928 numprev = 0
2875 # delta against first or second parent (not prev)
2929 # delta against first or second parent (not prev)
2876 nump1 = 0
2930 nump1 = 0
2877 nump2 = 0
2931 nump2 = 0
2878 # delta against neither prev nor parents
2932 # delta against neither prev nor parents
2879 numother = 0
2933 numother = 0
2880 # delta against prev that are also first or second parent
2934 # delta against prev that are also first or second parent
2881 # (details of `numprev`)
2935 # (details of `numprev`)
2882 nump1prev = 0
2936 nump1prev = 0
2883 nump2prev = 0
2937 nump2prev = 0
2884
2938
2885 # data about delta chain of each revs
2939 # data about delta chain of each revs
2886 chainlengths = []
2940 chainlengths = []
2887 chainbases = []
2941 chainbases = []
2888 chainspans = []
2942 chainspans = []
2889
2943
2890 # data about each revision
2944 # data about each revision
2891 datasize = [None, 0, 0]
2945 datasize = [None, 0, 0]
2892 fullsize = [None, 0, 0]
2946 fullsize = [None, 0, 0]
2893 semisize = [None, 0, 0]
2947 semisize = [None, 0, 0]
2894 # snapshot count per depth
2948 # snapshot count per depth
2895 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2949 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2896 deltasize = [None, 0, 0]
2950 deltasize = [None, 0, 0]
2897 chunktypecounts = {}
2951 chunktypecounts = {}
2898 chunktypesizes = {}
2952 chunktypesizes = {}
2899
2953
2900 def addsize(size, l):
2954 def addsize(size, l):
2901 if l[0] is None or size < l[0]:
2955 if l[0] is None or size < l[0]:
2902 l[0] = size
2956 l[0] = size
2903 if size > l[1]:
2957 if size > l[1]:
2904 l[1] = size
2958 l[1] = size
2905 l[2] += size
2959 l[2] += size
2906
2960
2907 numrevs = len(r)
2961 numrevs = len(r)
2908 for rev in pycompat.xrange(numrevs):
2962 for rev in pycompat.xrange(numrevs):
2909 p1, p2 = r.parentrevs(rev)
2963 p1, p2 = r.parentrevs(rev)
2910 delta = r.deltaparent(rev)
2964 delta = r.deltaparent(rev)
2911 if format > 0:
2965 if format > 0:
2912 addsize(r.rawsize(rev), datasize)
2966 addsize(r.rawsize(rev), datasize)
2913 if p2 != nullrev:
2967 if p2 != nullrev:
2914 nummerges += 1
2968 nummerges += 1
2915 size = r.length(rev)
2969 size = r.length(rev)
2916 if delta == nullrev:
2970 if delta == nullrev:
2917 chainlengths.append(0)
2971 chainlengths.append(0)
2918 chainbases.append(r.start(rev))
2972 chainbases.append(r.start(rev))
2919 chainspans.append(size)
2973 chainspans.append(size)
2920 if size == 0:
2974 if size == 0:
2921 numempty += 1
2975 numempty += 1
2922 numemptytext += 1
2976 numemptytext += 1
2923 else:
2977 else:
2924 numfull += 1
2978 numfull += 1
2925 numsnapdepth[0] += 1
2979 numsnapdepth[0] += 1
2926 addsize(size, fullsize)
2980 addsize(size, fullsize)
2927 addsize(size, snapsizedepth[0])
2981 addsize(size, snapsizedepth[0])
2928 else:
2982 else:
2929 chainlengths.append(chainlengths[delta] + 1)
2983 chainlengths.append(chainlengths[delta] + 1)
2930 baseaddr = chainbases[delta]
2984 baseaddr = chainbases[delta]
2931 revaddr = r.start(rev)
2985 revaddr = r.start(rev)
2932 chainbases.append(baseaddr)
2986 chainbases.append(baseaddr)
2933 chainspans.append((revaddr - baseaddr) + size)
2987 chainspans.append((revaddr - baseaddr) + size)
2934 if size == 0:
2988 if size == 0:
2935 numempty += 1
2989 numempty += 1
2936 numemptydelta += 1
2990 numemptydelta += 1
2937 elif r.issnapshot(rev):
2991 elif r.issnapshot(rev):
2938 addsize(size, semisize)
2992 addsize(size, semisize)
2939 numsemi += 1
2993 numsemi += 1
2940 depth = r.snapshotdepth(rev)
2994 depth = r.snapshotdepth(rev)
2941 numsnapdepth[depth] += 1
2995 numsnapdepth[depth] += 1
2942 addsize(size, snapsizedepth[depth])
2996 addsize(size, snapsizedepth[depth])
2943 else:
2997 else:
2944 addsize(size, deltasize)
2998 addsize(size, deltasize)
2945 if delta == rev - 1:
2999 if delta == rev - 1:
2946 numprev += 1
3000 numprev += 1
2947 if delta == p1:
3001 if delta == p1:
2948 nump1prev += 1
3002 nump1prev += 1
2949 elif delta == p2:
3003 elif delta == p2:
2950 nump2prev += 1
3004 nump2prev += 1
2951 elif delta == p1:
3005 elif delta == p1:
2952 nump1 += 1
3006 nump1 += 1
2953 elif delta == p2:
3007 elif delta == p2:
2954 nump2 += 1
3008 nump2 += 1
2955 elif delta != nullrev:
3009 elif delta != nullrev:
2956 numother += 1
3010 numother += 1
2957
3011
2958 # Obtain data on the raw chunks in the revlog.
3012 # Obtain data on the raw chunks in the revlog.
2959 if util.safehasattr(r, b'_getsegmentforrevs'):
3013 if util.safehasattr(r, b'_getsegmentforrevs'):
2960 segment = r._getsegmentforrevs(rev, rev)[1]
3014 segment = r._getsegmentforrevs(rev, rev)[1]
2961 else:
3015 else:
2962 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
3016 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
2963 if segment:
3017 if segment:
2964 chunktype = bytes(segment[0:1])
3018 chunktype = bytes(segment[0:1])
2965 else:
3019 else:
2966 chunktype = b'empty'
3020 chunktype = b'empty'
2967
3021
2968 if chunktype not in chunktypecounts:
3022 if chunktype not in chunktypecounts:
2969 chunktypecounts[chunktype] = 0
3023 chunktypecounts[chunktype] = 0
2970 chunktypesizes[chunktype] = 0
3024 chunktypesizes[chunktype] = 0
2971
3025
2972 chunktypecounts[chunktype] += 1
3026 chunktypecounts[chunktype] += 1
2973 chunktypesizes[chunktype] += size
3027 chunktypesizes[chunktype] += size
2974
3028
2975 # Adjust size min value for empty cases
3029 # Adjust size min value for empty cases
2976 for size in (datasize, fullsize, semisize, deltasize):
3030 for size in (datasize, fullsize, semisize, deltasize):
2977 if size[0] is None:
3031 if size[0] is None:
2978 size[0] = 0
3032 size[0] = 0
2979
3033
2980 numdeltas = numrevs - numfull - numempty - numsemi
3034 numdeltas = numrevs - numfull - numempty - numsemi
2981 numoprev = numprev - nump1prev - nump2prev
3035 numoprev = numprev - nump1prev - nump2prev
2982 totalrawsize = datasize[2]
3036 totalrawsize = datasize[2]
2983 datasize[2] /= numrevs
3037 datasize[2] /= numrevs
2984 fulltotal = fullsize[2]
3038 fulltotal = fullsize[2]
2985 if numfull == 0:
3039 if numfull == 0:
2986 fullsize[2] = 0
3040 fullsize[2] = 0
2987 else:
3041 else:
2988 fullsize[2] /= numfull
3042 fullsize[2] /= numfull
2989 semitotal = semisize[2]
3043 semitotal = semisize[2]
2990 snaptotal = {}
3044 snaptotal = {}
2991 if numsemi > 0:
3045 if numsemi > 0:
2992 semisize[2] /= numsemi
3046 semisize[2] /= numsemi
2993 for depth in snapsizedepth:
3047 for depth in snapsizedepth:
2994 snaptotal[depth] = snapsizedepth[depth][2]
3048 snaptotal[depth] = snapsizedepth[depth][2]
2995 snapsizedepth[depth][2] /= numsnapdepth[depth]
3049 snapsizedepth[depth][2] /= numsnapdepth[depth]
2996
3050
2997 deltatotal = deltasize[2]
3051 deltatotal = deltasize[2]
2998 if numdeltas > 0:
3052 if numdeltas > 0:
2999 deltasize[2] /= numdeltas
3053 deltasize[2] /= numdeltas
3000 totalsize = fulltotal + semitotal + deltatotal
3054 totalsize = fulltotal + semitotal + deltatotal
3001 avgchainlen = sum(chainlengths) / numrevs
3055 avgchainlen = sum(chainlengths) / numrevs
3002 maxchainlen = max(chainlengths)
3056 maxchainlen = max(chainlengths)
3003 maxchainspan = max(chainspans)
3057 maxchainspan = max(chainspans)
3004 compratio = 1
3058 compratio = 1
3005 if totalsize:
3059 if totalsize:
3006 compratio = totalrawsize / totalsize
3060 compratio = totalrawsize / totalsize
3007
3061
3008 basedfmtstr = b'%%%dd\n'
3062 basedfmtstr = b'%%%dd\n'
3009 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
3063 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
3010
3064
3011 def dfmtstr(max):
3065 def dfmtstr(max):
3012 return basedfmtstr % len(str(max))
3066 return basedfmtstr % len(str(max))
3013
3067
3014 def pcfmtstr(max, padding=0):
3068 def pcfmtstr(max, padding=0):
3015 return basepcfmtstr % (len(str(max)), b' ' * padding)
3069 return basepcfmtstr % (len(str(max)), b' ' * padding)
3016
3070
3017 def pcfmt(value, total):
3071 def pcfmt(value, total):
3018 if total:
3072 if total:
3019 return (value, 100 * float(value) / total)
3073 return (value, 100 * float(value) / total)
3020 else:
3074 else:
3021 return value, 100.0
3075 return value, 100.0
3022
3076
3023 ui.writenoi18n(b'format : %d\n' % format)
3077 ui.writenoi18n(b'format : %d\n' % format)
3024 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
3078 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
3025
3079
3026 ui.write(b'\n')
3080 ui.write(b'\n')
3027 fmt = pcfmtstr(totalsize)
3081 fmt = pcfmtstr(totalsize)
3028 fmt2 = dfmtstr(totalsize)
3082 fmt2 = dfmtstr(totalsize)
3029 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3083 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3030 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
3084 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
3031 ui.writenoi18n(
3085 ui.writenoi18n(
3032 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
3086 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
3033 )
3087 )
3034 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3088 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3035 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
3089 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
3036 ui.writenoi18n(
3090 ui.writenoi18n(
3037 b' text : '
3091 b' text : '
3038 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
3092 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
3039 )
3093 )
3040 ui.writenoi18n(
3094 ui.writenoi18n(
3041 b' delta : '
3095 b' delta : '
3042 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
3096 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
3043 )
3097 )
3044 ui.writenoi18n(
3098 ui.writenoi18n(
3045 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
3099 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
3046 )
3100 )
3047 for depth in sorted(numsnapdepth):
3101 for depth in sorted(numsnapdepth):
3048 ui.write(
3102 ui.write(
3049 (b' lvl-%-3d : ' % depth)
3103 (b' lvl-%-3d : ' % depth)
3050 + fmt % pcfmt(numsnapdepth[depth], numrevs)
3104 + fmt % pcfmt(numsnapdepth[depth], numrevs)
3051 )
3105 )
3052 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
3106 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
3053 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
3107 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
3054 ui.writenoi18n(
3108 ui.writenoi18n(
3055 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
3109 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
3056 )
3110 )
3057 for depth in sorted(numsnapdepth):
3111 for depth in sorted(numsnapdepth):
3058 ui.write(
3112 ui.write(
3059 (b' lvl-%-3d : ' % depth)
3113 (b' lvl-%-3d : ' % depth)
3060 + fmt % pcfmt(snaptotal[depth], totalsize)
3114 + fmt % pcfmt(snaptotal[depth], totalsize)
3061 )
3115 )
3062 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
3116 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
3063
3117
3064 def fmtchunktype(chunktype):
3118 def fmtchunktype(chunktype):
3065 if chunktype == b'empty':
3119 if chunktype == b'empty':
3066 return b' %s : ' % chunktype
3120 return b' %s : ' % chunktype
3067 elif chunktype in pycompat.bytestr(string.ascii_letters):
3121 elif chunktype in pycompat.bytestr(string.ascii_letters):
3068 return b' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3122 return b' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3069 else:
3123 else:
3070 return b' 0x%s : ' % hex(chunktype)
3124 return b' 0x%s : ' % hex(chunktype)
3071
3125
3072 ui.write(b'\n')
3126 ui.write(b'\n')
3073 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
3127 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
3074 for chunktype in sorted(chunktypecounts):
3128 for chunktype in sorted(chunktypecounts):
3075 ui.write(fmtchunktype(chunktype))
3129 ui.write(fmtchunktype(chunktype))
3076 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3130 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3077 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
3131 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
3078 for chunktype in sorted(chunktypecounts):
3132 for chunktype in sorted(chunktypecounts):
3079 ui.write(fmtchunktype(chunktype))
3133 ui.write(fmtchunktype(chunktype))
3080 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3134 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3081
3135
3082 ui.write(b'\n')
3136 ui.write(b'\n')
3083 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
3137 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
3084 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
3138 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
3085 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
3139 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
3086 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
3140 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
3087 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
3141 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
3088
3142
3089 if format > 0:
3143 if format > 0:
3090 ui.write(b'\n')
3144 ui.write(b'\n')
3091 ui.writenoi18n(
3145 ui.writenoi18n(
3092 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
3146 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
3093 % tuple(datasize)
3147 % tuple(datasize)
3094 )
3148 )
3095 ui.writenoi18n(
3149 ui.writenoi18n(
3096 b'full revision size (min/max/avg) : %d / %d / %d\n'
3150 b'full revision size (min/max/avg) : %d / %d / %d\n'
3097 % tuple(fullsize)
3151 % tuple(fullsize)
3098 )
3152 )
3099 ui.writenoi18n(
3153 ui.writenoi18n(
3100 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
3154 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
3101 % tuple(semisize)
3155 % tuple(semisize)
3102 )
3156 )
3103 for depth in sorted(snapsizedepth):
3157 for depth in sorted(snapsizedepth):
3104 if depth == 0:
3158 if depth == 0:
3105 continue
3159 continue
3106 ui.writenoi18n(
3160 ui.writenoi18n(
3107 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
3161 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
3108 % ((depth,) + tuple(snapsizedepth[depth]))
3162 % ((depth,) + tuple(snapsizedepth[depth]))
3109 )
3163 )
3110 ui.writenoi18n(
3164 ui.writenoi18n(
3111 b'delta size (min/max/avg) : %d / %d / %d\n'
3165 b'delta size (min/max/avg) : %d / %d / %d\n'
3112 % tuple(deltasize)
3166 % tuple(deltasize)
3113 )
3167 )
3114
3168
3115 if numdeltas > 0:
3169 if numdeltas > 0:
3116 ui.write(b'\n')
3170 ui.write(b'\n')
3117 fmt = pcfmtstr(numdeltas)
3171 fmt = pcfmtstr(numdeltas)
3118 fmt2 = pcfmtstr(numdeltas, 4)
3172 fmt2 = pcfmtstr(numdeltas, 4)
3119 ui.writenoi18n(
3173 ui.writenoi18n(
3120 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
3174 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
3121 )
3175 )
3122 if numprev > 0:
3176 if numprev > 0:
3123 ui.writenoi18n(
3177 ui.writenoi18n(
3124 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
3178 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
3125 )
3179 )
3126 ui.writenoi18n(
3180 ui.writenoi18n(
3127 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
3181 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
3128 )
3182 )
3129 ui.writenoi18n(
3183 ui.writenoi18n(
3130 b' other : ' + fmt2 % pcfmt(numoprev, numprev)
3184 b' other : ' + fmt2 % pcfmt(numoprev, numprev)
3131 )
3185 )
3132 if gdelta:
3186 if gdelta:
3133 ui.writenoi18n(
3187 ui.writenoi18n(
3134 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
3188 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
3135 )
3189 )
3136 ui.writenoi18n(
3190 ui.writenoi18n(
3137 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
3191 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
3138 )
3192 )
3139 ui.writenoi18n(
3193 ui.writenoi18n(
3140 b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
3194 b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
3141 )
3195 )
3142
3196
3143
3197
3144 @command(
3198 @command(
3145 b'debugrevlogindex',
3199 b'debugrevlogindex',
3146 cmdutil.debugrevlogopts
3200 cmdutil.debugrevlogopts
3147 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3201 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3148 _(b'[-f FORMAT] -c|-m|FILE'),
3202 _(b'[-f FORMAT] -c|-m|FILE'),
3149 optionalrepo=True,
3203 optionalrepo=True,
3150 )
3204 )
3151 def debugrevlogindex(ui, repo, file_=None, **opts):
3205 def debugrevlogindex(ui, repo, file_=None, **opts):
3152 """dump the contents of a revlog index"""
3206 """dump the contents of a revlog index"""
3153 opts = pycompat.byteskwargs(opts)
3207 opts = pycompat.byteskwargs(opts)
3154 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3208 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3155 format = opts.get(b'format', 0)
3209 format = opts.get(b'format', 0)
3156 if format not in (0, 1):
3210 if format not in (0, 1):
3157 raise error.Abort(_(b"unknown format %d") % format)
3211 raise error.Abort(_(b"unknown format %d") % format)
3158
3212
3159 if ui.debugflag:
3213 if ui.debugflag:
3160 shortfn = hex
3214 shortfn = hex
3161 else:
3215 else:
3162 shortfn = short
3216 shortfn = short
3163
3217
3164 # There might not be anything in r, so have a sane default
3218 # There might not be anything in r, so have a sane default
3165 idlen = 12
3219 idlen = 12
3166 for i in r:
3220 for i in r:
3167 idlen = len(shortfn(r.node(i)))
3221 idlen = len(shortfn(r.node(i)))
3168 break
3222 break
3169
3223
3170 if format == 0:
3224 if format == 0:
3171 if ui.verbose:
3225 if ui.verbose:
3172 ui.writenoi18n(
3226 ui.writenoi18n(
3173 b" rev offset length linkrev %s %s p2\n"
3227 b" rev offset length linkrev %s %s p2\n"
3174 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3228 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3175 )
3229 )
3176 else:
3230 else:
3177 ui.writenoi18n(
3231 ui.writenoi18n(
3178 b" rev linkrev %s %s p2\n"
3232 b" rev linkrev %s %s p2\n"
3179 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3233 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3180 )
3234 )
3181 elif format == 1:
3235 elif format == 1:
3182 if ui.verbose:
3236 if ui.verbose:
3183 ui.writenoi18n(
3237 ui.writenoi18n(
3184 (
3238 (
3185 b" rev flag offset length size link p1"
3239 b" rev flag offset length size link p1"
3186 b" p2 %s\n"
3240 b" p2 %s\n"
3187 )
3241 )
3188 % b"nodeid".rjust(idlen)
3242 % b"nodeid".rjust(idlen)
3189 )
3243 )
3190 else:
3244 else:
3191 ui.writenoi18n(
3245 ui.writenoi18n(
3192 b" rev flag size link p1 p2 %s\n"
3246 b" rev flag size link p1 p2 %s\n"
3193 % b"nodeid".rjust(idlen)
3247 % b"nodeid".rjust(idlen)
3194 )
3248 )
3195
3249
3196 for i in r:
3250 for i in r:
3197 node = r.node(i)
3251 node = r.node(i)
3198 if format == 0:
3252 if format == 0:
3199 try:
3253 try:
3200 pp = r.parents(node)
3254 pp = r.parents(node)
3201 except Exception:
3255 except Exception:
3202 pp = [nullid, nullid]
3256 pp = [nullid, nullid]
3203 if ui.verbose:
3257 if ui.verbose:
3204 ui.write(
3258 ui.write(
3205 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3259 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3206 % (
3260 % (
3207 i,
3261 i,
3208 r.start(i),
3262 r.start(i),
3209 r.length(i),
3263 r.length(i),
3210 r.linkrev(i),
3264 r.linkrev(i),
3211 shortfn(node),
3265 shortfn(node),
3212 shortfn(pp[0]),
3266 shortfn(pp[0]),
3213 shortfn(pp[1]),
3267 shortfn(pp[1]),
3214 )
3268 )
3215 )
3269 )
3216 else:
3270 else:
3217 ui.write(
3271 ui.write(
3218 b"% 6d % 7d %s %s %s\n"
3272 b"% 6d % 7d %s %s %s\n"
3219 % (
3273 % (
3220 i,
3274 i,
3221 r.linkrev(i),
3275 r.linkrev(i),
3222 shortfn(node),
3276 shortfn(node),
3223 shortfn(pp[0]),
3277 shortfn(pp[0]),
3224 shortfn(pp[1]),
3278 shortfn(pp[1]),
3225 )
3279 )
3226 )
3280 )
3227 elif format == 1:
3281 elif format == 1:
3228 pr = r.parentrevs(i)
3282 pr = r.parentrevs(i)
3229 if ui.verbose:
3283 if ui.verbose:
3230 ui.write(
3284 ui.write(
3231 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3285 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3232 % (
3286 % (
3233 i,
3287 i,
3234 r.flags(i),
3288 r.flags(i),
3235 r.start(i),
3289 r.start(i),
3236 r.length(i),
3290 r.length(i),
3237 r.rawsize(i),
3291 r.rawsize(i),
3238 r.linkrev(i),
3292 r.linkrev(i),
3239 pr[0],
3293 pr[0],
3240 pr[1],
3294 pr[1],
3241 shortfn(node),
3295 shortfn(node),
3242 )
3296 )
3243 )
3297 )
3244 else:
3298 else:
3245 ui.write(
3299 ui.write(
3246 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3300 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3247 % (
3301 % (
3248 i,
3302 i,
3249 r.flags(i),
3303 r.flags(i),
3250 r.rawsize(i),
3304 r.rawsize(i),
3251 r.linkrev(i),
3305 r.linkrev(i),
3252 pr[0],
3306 pr[0],
3253 pr[1],
3307 pr[1],
3254 shortfn(node),
3308 shortfn(node),
3255 )
3309 )
3256 )
3310 )
3257
3311
3258
3312
3259 @command(
3313 @command(
3260 b'debugrevspec',
3314 b'debugrevspec',
3261 [
3315 [
3262 (
3316 (
3263 b'',
3317 b'',
3264 b'optimize',
3318 b'optimize',
3265 None,
3319 None,
3266 _(b'print parsed tree after optimizing (DEPRECATED)'),
3320 _(b'print parsed tree after optimizing (DEPRECATED)'),
3267 ),
3321 ),
3268 (
3322 (
3269 b'',
3323 b'',
3270 b'show-revs',
3324 b'show-revs',
3271 True,
3325 True,
3272 _(b'print list of result revisions (default)'),
3326 _(b'print list of result revisions (default)'),
3273 ),
3327 ),
3274 (
3328 (
3275 b's',
3329 b's',
3276 b'show-set',
3330 b'show-set',
3277 None,
3331 None,
3278 _(b'print internal representation of result set'),
3332 _(b'print internal representation of result set'),
3279 ),
3333 ),
3280 (
3334 (
3281 b'p',
3335 b'p',
3282 b'show-stage',
3336 b'show-stage',
3283 [],
3337 [],
3284 _(b'print parsed tree at the given stage'),
3338 _(b'print parsed tree at the given stage'),
3285 _(b'NAME'),
3339 _(b'NAME'),
3286 ),
3340 ),
3287 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3341 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3288 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3342 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3289 ],
3343 ],
3290 b'REVSPEC',
3344 b'REVSPEC',
3291 )
3345 )
3292 def debugrevspec(ui, repo, expr, **opts):
3346 def debugrevspec(ui, repo, expr, **opts):
3293 """parse and apply a revision specification
3347 """parse and apply a revision specification
3294
3348
3295 Use -p/--show-stage option to print the parsed tree at the given stages.
3349 Use -p/--show-stage option to print the parsed tree at the given stages.
3296 Use -p all to print tree at every stage.
3350 Use -p all to print tree at every stage.
3297
3351
3298 Use --no-show-revs option with -s or -p to print only the set
3352 Use --no-show-revs option with -s or -p to print only the set
3299 representation or the parsed tree respectively.
3353 representation or the parsed tree respectively.
3300
3354
3301 Use --verify-optimized to compare the optimized result with the unoptimized
3355 Use --verify-optimized to compare the optimized result with the unoptimized
3302 one. Returns 1 if the optimized result differs.
3356 one. Returns 1 if the optimized result differs.
3303 """
3357 """
3304 opts = pycompat.byteskwargs(opts)
3358 opts = pycompat.byteskwargs(opts)
3305 aliases = ui.configitems(b'revsetalias')
3359 aliases = ui.configitems(b'revsetalias')
3306 stages = [
3360 stages = [
3307 (b'parsed', lambda tree: tree),
3361 (b'parsed', lambda tree: tree),
3308 (
3362 (
3309 b'expanded',
3363 b'expanded',
3310 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3364 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3311 ),
3365 ),
3312 (b'concatenated', revsetlang.foldconcat),
3366 (b'concatenated', revsetlang.foldconcat),
3313 (b'analyzed', revsetlang.analyze),
3367 (b'analyzed', revsetlang.analyze),
3314 (b'optimized', revsetlang.optimize),
3368 (b'optimized', revsetlang.optimize),
3315 ]
3369 ]
3316 if opts[b'no_optimized']:
3370 if opts[b'no_optimized']:
3317 stages = stages[:-1]
3371 stages = stages[:-1]
3318 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3372 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3319 raise error.Abort(
3373 raise error.Abort(
3320 _(b'cannot use --verify-optimized with --no-optimized')
3374 _(b'cannot use --verify-optimized with --no-optimized')
3321 )
3375 )
3322 stagenames = {n for n, f in stages}
3376 stagenames = {n for n, f in stages}
3323
3377
3324 showalways = set()
3378 showalways = set()
3325 showchanged = set()
3379 showchanged = set()
3326 if ui.verbose and not opts[b'show_stage']:
3380 if ui.verbose and not opts[b'show_stage']:
3327 # show parsed tree by --verbose (deprecated)
3381 # show parsed tree by --verbose (deprecated)
3328 showalways.add(b'parsed')
3382 showalways.add(b'parsed')
3329 showchanged.update([b'expanded', b'concatenated'])
3383 showchanged.update([b'expanded', b'concatenated'])
3330 if opts[b'optimize']:
3384 if opts[b'optimize']:
3331 showalways.add(b'optimized')
3385 showalways.add(b'optimized')
3332 if opts[b'show_stage'] and opts[b'optimize']:
3386 if opts[b'show_stage'] and opts[b'optimize']:
3333 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3387 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3334 if opts[b'show_stage'] == [b'all']:
3388 if opts[b'show_stage'] == [b'all']:
3335 showalways.update(stagenames)
3389 showalways.update(stagenames)
3336 else:
3390 else:
3337 for n in opts[b'show_stage']:
3391 for n in opts[b'show_stage']:
3338 if n not in stagenames:
3392 if n not in stagenames:
3339 raise error.Abort(_(b'invalid stage name: %s') % n)
3393 raise error.Abort(_(b'invalid stage name: %s') % n)
3340 showalways.update(opts[b'show_stage'])
3394 showalways.update(opts[b'show_stage'])
3341
3395
3342 treebystage = {}
3396 treebystage = {}
3343 printedtree = None
3397 printedtree = None
3344 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3398 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3345 for n, f in stages:
3399 for n, f in stages:
3346 treebystage[n] = tree = f(tree)
3400 treebystage[n] = tree = f(tree)
3347 if n in showalways or (n in showchanged and tree != printedtree):
3401 if n in showalways or (n in showchanged and tree != printedtree):
3348 if opts[b'show_stage'] or n != b'parsed':
3402 if opts[b'show_stage'] or n != b'parsed':
3349 ui.write(b"* %s:\n" % n)
3403 ui.write(b"* %s:\n" % n)
3350 ui.write(revsetlang.prettyformat(tree), b"\n")
3404 ui.write(revsetlang.prettyformat(tree), b"\n")
3351 printedtree = tree
3405 printedtree = tree
3352
3406
3353 if opts[b'verify_optimized']:
3407 if opts[b'verify_optimized']:
3354 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3408 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3355 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3409 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3356 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3410 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3357 ui.writenoi18n(
3411 ui.writenoi18n(
3358 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3412 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3359 )
3413 )
3360 ui.writenoi18n(
3414 ui.writenoi18n(
3361 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3415 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3362 )
3416 )
3363 arevs = list(arevs)
3417 arevs = list(arevs)
3364 brevs = list(brevs)
3418 brevs = list(brevs)
3365 if arevs == brevs:
3419 if arevs == brevs:
3366 return 0
3420 return 0
3367 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3421 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3368 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3422 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3369 sm = difflib.SequenceMatcher(None, arevs, brevs)
3423 sm = difflib.SequenceMatcher(None, arevs, brevs)
3370 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3424 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3371 if tag in ('delete', 'replace'):
3425 if tag in ('delete', 'replace'):
3372 for c in arevs[alo:ahi]:
3426 for c in arevs[alo:ahi]:
3373 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3427 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3374 if tag in ('insert', 'replace'):
3428 if tag in ('insert', 'replace'):
3375 for c in brevs[blo:bhi]:
3429 for c in brevs[blo:bhi]:
3376 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3430 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3377 if tag == 'equal':
3431 if tag == 'equal':
3378 for c in arevs[alo:ahi]:
3432 for c in arevs[alo:ahi]:
3379 ui.write(b' %d\n' % c)
3433 ui.write(b' %d\n' % c)
3380 return 1
3434 return 1
3381
3435
3382 func = revset.makematcher(tree)
3436 func = revset.makematcher(tree)
3383 revs = func(repo)
3437 revs = func(repo)
3384 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3438 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3385 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3439 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3386 if not opts[b'show_revs']:
3440 if not opts[b'show_revs']:
3387 return
3441 return
3388 for c in revs:
3442 for c in revs:
3389 ui.write(b"%d\n" % c)
3443 ui.write(b"%d\n" % c)
3390
3444
3391
3445
3392 @command(
3446 @command(
3393 b'debugserve',
3447 b'debugserve',
3394 [
3448 [
3395 (
3449 (
3396 b'',
3450 b'',
3397 b'sshstdio',
3451 b'sshstdio',
3398 False,
3452 False,
3399 _(b'run an SSH server bound to process handles'),
3453 _(b'run an SSH server bound to process handles'),
3400 ),
3454 ),
3401 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3455 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3402 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3456 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3403 ],
3457 ],
3404 b'',
3458 b'',
3405 )
3459 )
3406 def debugserve(ui, repo, **opts):
3460 def debugserve(ui, repo, **opts):
3407 """run a server with advanced settings
3461 """run a server with advanced settings
3408
3462
3409 This command is similar to :hg:`serve`. It exists partially as a
3463 This command is similar to :hg:`serve`. It exists partially as a
3410 workaround to the fact that ``hg serve --stdio`` must have specific
3464 workaround to the fact that ``hg serve --stdio`` must have specific
3411 arguments for security reasons.
3465 arguments for security reasons.
3412 """
3466 """
3413 opts = pycompat.byteskwargs(opts)
3467 opts = pycompat.byteskwargs(opts)
3414
3468
3415 if not opts[b'sshstdio']:
3469 if not opts[b'sshstdio']:
3416 raise error.Abort(_(b'only --sshstdio is currently supported'))
3470 raise error.Abort(_(b'only --sshstdio is currently supported'))
3417
3471
3418 logfh = None
3472 logfh = None
3419
3473
3420 if opts[b'logiofd'] and opts[b'logiofile']:
3474 if opts[b'logiofd'] and opts[b'logiofile']:
3421 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3475 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3422
3476
3423 if opts[b'logiofd']:
3477 if opts[b'logiofd']:
3424 # Ideally we would be line buffered. But line buffering in binary
3478 # Ideally we would be line buffered. But line buffering in binary
3425 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3479 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3426 # buffering could have performance impacts. But since this isn't
3480 # buffering could have performance impacts. But since this isn't
3427 # performance critical code, it should be fine.
3481 # performance critical code, it should be fine.
3428 try:
3482 try:
3429 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3483 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3430 except OSError as e:
3484 except OSError as e:
3431 if e.errno != errno.ESPIPE:
3485 if e.errno != errno.ESPIPE:
3432 raise
3486 raise
3433 # can't seek a pipe, so `ab` mode fails on py3
3487 # can't seek a pipe, so `ab` mode fails on py3
3434 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3488 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3435 elif opts[b'logiofile']:
3489 elif opts[b'logiofile']:
3436 logfh = open(opts[b'logiofile'], b'ab', 0)
3490 logfh = open(opts[b'logiofile'], b'ab', 0)
3437
3491
3438 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3492 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3439 s.serve_forever()
3493 s.serve_forever()
3440
3494
3441
3495
3442 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3496 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3443 def debugsetparents(ui, repo, rev1, rev2=None):
3497 def debugsetparents(ui, repo, rev1, rev2=None):
3444 """manually set the parents of the current working directory (DANGEROUS)
3498 """manually set the parents of the current working directory (DANGEROUS)
3445
3499
3446 This command is not what you are looking for and should not be used. Using
3500 This command is not what you are looking for and should not be used. Using
3447 this command will most certainly results in slight corruption of the file
3501 this command will most certainly results in slight corruption of the file
3448 level histories withing your repository. DO NOT USE THIS COMMAND.
3502 level histories withing your repository. DO NOT USE THIS COMMAND.
3449
3503
3450 The command update the p1 and p2 field in the dirstate, and not touching
3504 The command update the p1 and p2 field in the dirstate, and not touching
3451 anything else. This useful for writing repository conversion tools, but
3505 anything else. This useful for writing repository conversion tools, but
3452 should be used with extreme care. For example, neither the working
3506 should be used with extreme care. For example, neither the working
3453 directory nor the dirstate is updated, so file status may be incorrect
3507 directory nor the dirstate is updated, so file status may be incorrect
3454 after running this command. Only used if you are one of the few people that
3508 after running this command. Only used if you are one of the few people that
3455 deeply unstand both conversion tools and file level histories. If you are
3509 deeply unstand both conversion tools and file level histories. If you are
3456 reading this help, you are not one of this people (most of them sailed west
3510 reading this help, you are not one of this people (most of them sailed west
3457 from Mithlond anyway.
3511 from Mithlond anyway.
3458
3512
3459 So one last time DO NOT USE THIS COMMAND.
3513 So one last time DO NOT USE THIS COMMAND.
3460
3514
3461 Returns 0 on success.
3515 Returns 0 on success.
3462 """
3516 """
3463
3517
3464 node1 = scmutil.revsingle(repo, rev1).node()
3518 node1 = scmutil.revsingle(repo, rev1).node()
3465 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3519 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3466
3520
3467 with repo.wlock():
3521 with repo.wlock():
3468 repo.setparents(node1, node2)
3522 repo.setparents(node1, node2)
3469
3523
3470
3524
3471 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3525 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3472 def debugsidedata(ui, repo, file_, rev=None, **opts):
3526 def debugsidedata(ui, repo, file_, rev=None, **opts):
3473 """dump the side data for a cl/manifest/file revision
3527 """dump the side data for a cl/manifest/file revision
3474
3528
3475 Use --verbose to dump the sidedata content."""
3529 Use --verbose to dump the sidedata content."""
3476 opts = pycompat.byteskwargs(opts)
3530 opts = pycompat.byteskwargs(opts)
3477 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3531 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3478 if rev is not None:
3532 if rev is not None:
3479 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3533 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3480 file_, rev = None, file_
3534 file_, rev = None, file_
3481 elif rev is None:
3535 elif rev is None:
3482 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3536 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3483 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3537 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3484 r = getattr(r, '_revlog', r)
3538 r = getattr(r, '_revlog', r)
3485 try:
3539 try:
3486 sidedata = r.sidedata(r.lookup(rev))
3540 sidedata = r.sidedata(r.lookup(rev))
3487 except KeyError:
3541 except KeyError:
3488 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3542 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3489 if sidedata:
3543 if sidedata:
3490 sidedata = list(sidedata.items())
3544 sidedata = list(sidedata.items())
3491 sidedata.sort()
3545 sidedata.sort()
3492 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3546 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3493 for key, value in sidedata:
3547 for key, value in sidedata:
3494 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3548 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3495 if ui.verbose:
3549 if ui.verbose:
3496 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3550 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3497
3551
3498
3552
3499 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3553 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3500 def debugssl(ui, repo, source=None, **opts):
3554 def debugssl(ui, repo, source=None, **opts):
3501 """test a secure connection to a server
3555 """test a secure connection to a server
3502
3556
3503 This builds the certificate chain for the server on Windows, installing the
3557 This builds the certificate chain for the server on Windows, installing the
3504 missing intermediates and trusted root via Windows Update if necessary. It
3558 missing intermediates and trusted root via Windows Update if necessary. It
3505 does nothing on other platforms.
3559 does nothing on other platforms.
3506
3560
3507 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3561 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3508 that server is used. See :hg:`help urls` for more information.
3562 that server is used. See :hg:`help urls` for more information.
3509
3563
3510 If the update succeeds, retry the original operation. Otherwise, the cause
3564 If the update succeeds, retry the original operation. Otherwise, the cause
3511 of the SSL error is likely another issue.
3565 of the SSL error is likely another issue.
3512 """
3566 """
3513 if not pycompat.iswindows:
3567 if not pycompat.iswindows:
3514 raise error.Abort(
3568 raise error.Abort(
3515 _(b'certificate chain building is only possible on Windows')
3569 _(b'certificate chain building is only possible on Windows')
3516 )
3570 )
3517
3571
3518 if not source:
3572 if not source:
3519 if not repo:
3573 if not repo:
3520 raise error.Abort(
3574 raise error.Abort(
3521 _(
3575 _(
3522 b"there is no Mercurial repository here, and no "
3576 b"there is no Mercurial repository here, and no "
3523 b"server specified"
3577 b"server specified"
3524 )
3578 )
3525 )
3579 )
3526 source = b"default"
3580 source = b"default"
3527
3581
3528 source, branches = hg.parseurl(ui.expandpath(source))
3582 source, branches = hg.parseurl(ui.expandpath(source))
3529 url = util.url(source)
3583 url = util.url(source)
3530
3584
3531 defaultport = {b'https': 443, b'ssh': 22}
3585 defaultport = {b'https': 443, b'ssh': 22}
3532 if url.scheme in defaultport:
3586 if url.scheme in defaultport:
3533 try:
3587 try:
3534 addr = (url.host, int(url.port or defaultport[url.scheme]))
3588 addr = (url.host, int(url.port or defaultport[url.scheme]))
3535 except ValueError:
3589 except ValueError:
3536 raise error.Abort(_(b"malformed port number in URL"))
3590 raise error.Abort(_(b"malformed port number in URL"))
3537 else:
3591 else:
3538 raise error.Abort(_(b"only https and ssh connections are supported"))
3592 raise error.Abort(_(b"only https and ssh connections are supported"))
3539
3593
3540 from . import win32
3594 from . import win32
3541
3595
3542 s = ssl.wrap_socket(
3596 s = ssl.wrap_socket(
3543 socket.socket(),
3597 socket.socket(),
3544 ssl_version=ssl.PROTOCOL_TLS,
3598 ssl_version=ssl.PROTOCOL_TLS,
3545 cert_reqs=ssl.CERT_NONE,
3599 cert_reqs=ssl.CERT_NONE,
3546 ca_certs=None,
3600 ca_certs=None,
3547 )
3601 )
3548
3602
3549 try:
3603 try:
3550 s.connect(addr)
3604 s.connect(addr)
3551 cert = s.getpeercert(True)
3605 cert = s.getpeercert(True)
3552
3606
3553 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3607 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3554
3608
3555 complete = win32.checkcertificatechain(cert, build=False)
3609 complete = win32.checkcertificatechain(cert, build=False)
3556
3610
3557 if not complete:
3611 if not complete:
3558 ui.status(_(b'certificate chain is incomplete, updating... '))
3612 ui.status(_(b'certificate chain is incomplete, updating... '))
3559
3613
3560 if not win32.checkcertificatechain(cert):
3614 if not win32.checkcertificatechain(cert):
3561 ui.status(_(b'failed.\n'))
3615 ui.status(_(b'failed.\n'))
3562 else:
3616 else:
3563 ui.status(_(b'done.\n'))
3617 ui.status(_(b'done.\n'))
3564 else:
3618 else:
3565 ui.status(_(b'full certificate chain is available\n'))
3619 ui.status(_(b'full certificate chain is available\n'))
3566 finally:
3620 finally:
3567 s.close()
3621 s.close()
3568
3622
3569
3623
3570 @command(
3624 @command(
3571 b"debugbackupbundle",
3625 b"debugbackupbundle",
3572 [
3626 [
3573 (
3627 (
3574 b"",
3628 b"",
3575 b"recover",
3629 b"recover",
3576 b"",
3630 b"",
3577 b"brings the specified changeset back into the repository",
3631 b"brings the specified changeset back into the repository",
3578 )
3632 )
3579 ]
3633 ]
3580 + cmdutil.logopts,
3634 + cmdutil.logopts,
3581 _(b"hg debugbackupbundle [--recover HASH]"),
3635 _(b"hg debugbackupbundle [--recover HASH]"),
3582 )
3636 )
3583 def debugbackupbundle(ui, repo, *pats, **opts):
3637 def debugbackupbundle(ui, repo, *pats, **opts):
3584 """lists the changesets available in backup bundles
3638 """lists the changesets available in backup bundles
3585
3639
3586 Without any arguments, this command prints a list of the changesets in each
3640 Without any arguments, this command prints a list of the changesets in each
3587 backup bundle.
3641 backup bundle.
3588
3642
3589 --recover takes a changeset hash and unbundles the first bundle that
3643 --recover takes a changeset hash and unbundles the first bundle that
3590 contains that hash, which puts that changeset back in your repository.
3644 contains that hash, which puts that changeset back in your repository.
3591
3645
3592 --verbose will print the entire commit message and the bundle path for that
3646 --verbose will print the entire commit message and the bundle path for that
3593 backup.
3647 backup.
3594 """
3648 """
3595 backups = list(
3649 backups = list(
3596 filter(
3650 filter(
3597 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3651 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3598 )
3652 )
3599 )
3653 )
3600 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3654 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3601
3655
3602 opts = pycompat.byteskwargs(opts)
3656 opts = pycompat.byteskwargs(opts)
3603 opts[b"bundle"] = b""
3657 opts[b"bundle"] = b""
3604 opts[b"force"] = None
3658 opts[b"force"] = None
3605 limit = logcmdutil.getlimit(opts)
3659 limit = logcmdutil.getlimit(opts)
3606
3660
3607 def display(other, chlist, displayer):
3661 def display(other, chlist, displayer):
3608 if opts.get(b"newest_first"):
3662 if opts.get(b"newest_first"):
3609 chlist.reverse()
3663 chlist.reverse()
3610 count = 0
3664 count = 0
3611 for n in chlist:
3665 for n in chlist:
3612 if limit is not None and count >= limit:
3666 if limit is not None and count >= limit:
3613 break
3667 break
3614 parents = [True for p in other.changelog.parents(n) if p != nullid]
3668 parents = [True for p in other.changelog.parents(n) if p != nullid]
3615 if opts.get(b"no_merges") and len(parents) == 2:
3669 if opts.get(b"no_merges") and len(parents) == 2:
3616 continue
3670 continue
3617 count += 1
3671 count += 1
3618 displayer.show(other[n])
3672 displayer.show(other[n])
3619
3673
3620 recovernode = opts.get(b"recover")
3674 recovernode = opts.get(b"recover")
3621 if recovernode:
3675 if recovernode:
3622 if scmutil.isrevsymbol(repo, recovernode):
3676 if scmutil.isrevsymbol(repo, recovernode):
3623 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3677 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3624 return
3678 return
3625 elif backups:
3679 elif backups:
3626 msg = _(
3680 msg = _(
3627 b"Recover changesets using: hg debugbackupbundle --recover "
3681 b"Recover changesets using: hg debugbackupbundle --recover "
3628 b"<changeset hash>\n\nAvailable backup changesets:"
3682 b"<changeset hash>\n\nAvailable backup changesets:"
3629 )
3683 )
3630 ui.status(msg, label=b"status.removed")
3684 ui.status(msg, label=b"status.removed")
3631 else:
3685 else:
3632 ui.status(_(b"no backup changesets found\n"))
3686 ui.status(_(b"no backup changesets found\n"))
3633 return
3687 return
3634
3688
3635 for backup in backups:
3689 for backup in backups:
3636 # Much of this is copied from the hg incoming logic
3690 # Much of this is copied from the hg incoming logic
3637 source = ui.expandpath(os.path.relpath(backup, encoding.getcwd()))
3691 source = ui.expandpath(os.path.relpath(backup, encoding.getcwd()))
3638 source, branches = hg.parseurl(source, opts.get(b"branch"))
3692 source, branches = hg.parseurl(source, opts.get(b"branch"))
3639 try:
3693 try:
3640 other = hg.peer(repo, opts, source)
3694 other = hg.peer(repo, opts, source)
3641 except error.LookupError as ex:
3695 except error.LookupError as ex:
3642 msg = _(b"\nwarning: unable to open bundle %s") % source
3696 msg = _(b"\nwarning: unable to open bundle %s") % source
3643 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3697 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3644 ui.warn(msg, hint=hint)
3698 ui.warn(msg, hint=hint)
3645 continue
3699 continue
3646 revs, checkout = hg.addbranchrevs(
3700 revs, checkout = hg.addbranchrevs(
3647 repo, other, branches, opts.get(b"rev")
3701 repo, other, branches, opts.get(b"rev")
3648 )
3702 )
3649
3703
3650 if revs:
3704 if revs:
3651 revs = [other.lookup(rev) for rev in revs]
3705 revs = [other.lookup(rev) for rev in revs]
3652
3706
3653 quiet = ui.quiet
3707 quiet = ui.quiet
3654 try:
3708 try:
3655 ui.quiet = True
3709 ui.quiet = True
3656 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3710 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3657 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3711 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3658 )
3712 )
3659 except error.LookupError:
3713 except error.LookupError:
3660 continue
3714 continue
3661 finally:
3715 finally:
3662 ui.quiet = quiet
3716 ui.quiet = quiet
3663
3717
3664 try:
3718 try:
3665 if not chlist:
3719 if not chlist:
3666 continue
3720 continue
3667 if recovernode:
3721 if recovernode:
3668 with repo.lock(), repo.transaction(b"unbundle") as tr:
3722 with repo.lock(), repo.transaction(b"unbundle") as tr:
3669 if scmutil.isrevsymbol(other, recovernode):
3723 if scmutil.isrevsymbol(other, recovernode):
3670 ui.status(_(b"Unbundling %s\n") % (recovernode))
3724 ui.status(_(b"Unbundling %s\n") % (recovernode))
3671 f = hg.openpath(ui, source)
3725 f = hg.openpath(ui, source)
3672 gen = exchange.readbundle(ui, f, source)
3726 gen = exchange.readbundle(ui, f, source)
3673 if isinstance(gen, bundle2.unbundle20):
3727 if isinstance(gen, bundle2.unbundle20):
3674 bundle2.applybundle(
3728 bundle2.applybundle(
3675 repo,
3729 repo,
3676 gen,
3730 gen,
3677 tr,
3731 tr,
3678 source=b"unbundle",
3732 source=b"unbundle",
3679 url=b"bundle:" + source,
3733 url=b"bundle:" + source,
3680 )
3734 )
3681 else:
3735 else:
3682 gen.apply(repo, b"unbundle", b"bundle:" + source)
3736 gen.apply(repo, b"unbundle", b"bundle:" + source)
3683 break
3737 break
3684 else:
3738 else:
3685 backupdate = encoding.strtolocal(
3739 backupdate = encoding.strtolocal(
3686 time.strftime(
3740 time.strftime(
3687 "%a %H:%M, %Y-%m-%d",
3741 "%a %H:%M, %Y-%m-%d",
3688 time.localtime(os.path.getmtime(source)),
3742 time.localtime(os.path.getmtime(source)),
3689 )
3743 )
3690 )
3744 )
3691 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3745 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3692 if ui.verbose:
3746 if ui.verbose:
3693 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), source))
3747 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), source))
3694 else:
3748 else:
3695 opts[
3749 opts[
3696 b"template"
3750 b"template"
3697 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3751 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3698 displayer = logcmdutil.changesetdisplayer(
3752 displayer = logcmdutil.changesetdisplayer(
3699 ui, other, opts, False
3753 ui, other, opts, False
3700 )
3754 )
3701 display(other, chlist, displayer)
3755 display(other, chlist, displayer)
3702 displayer.close()
3756 displayer.close()
3703 finally:
3757 finally:
3704 cleanupfn()
3758 cleanupfn()
3705
3759
3706
3760
3707 @command(
3761 @command(
3708 b'debugsub',
3762 b'debugsub',
3709 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3763 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3710 _(b'[-r REV] [REV]'),
3764 _(b'[-r REV] [REV]'),
3711 )
3765 )
3712 def debugsub(ui, repo, rev=None):
3766 def debugsub(ui, repo, rev=None):
3713 ctx = scmutil.revsingle(repo, rev, None)
3767 ctx = scmutil.revsingle(repo, rev, None)
3714 for k, v in sorted(ctx.substate.items()):
3768 for k, v in sorted(ctx.substate.items()):
3715 ui.writenoi18n(b'path %s\n' % k)
3769 ui.writenoi18n(b'path %s\n' % k)
3716 ui.writenoi18n(b' source %s\n' % v[0])
3770 ui.writenoi18n(b' source %s\n' % v[0])
3717 ui.writenoi18n(b' revision %s\n' % v[1])
3771 ui.writenoi18n(b' revision %s\n' % v[1])
3718
3772
3719
3773
3720 @command(b'debugshell', optionalrepo=True)
3774 @command(b'debugshell', optionalrepo=True)
3721 def debugshell(ui, repo):
3775 def debugshell(ui, repo):
3722 """run an interactive Python interpreter
3776 """run an interactive Python interpreter
3723
3777
3724 The local namespace is provided with a reference to the ui and
3778 The local namespace is provided with a reference to the ui and
3725 the repo instance (if available).
3779 the repo instance (if available).
3726 """
3780 """
3727 import code
3781 import code
3728
3782
3729 imported_objects = {
3783 imported_objects = {
3730 'ui': ui,
3784 'ui': ui,
3731 'repo': repo,
3785 'repo': repo,
3732 }
3786 }
3733
3787
3734 code.interact(local=imported_objects)
3788 code.interact(local=imported_objects)
3735
3789
3736
3790
3737 @command(
3791 @command(
3738 b'debugsuccessorssets',
3792 b'debugsuccessorssets',
3739 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3793 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3740 _(b'[REV]'),
3794 _(b'[REV]'),
3741 )
3795 )
3742 def debugsuccessorssets(ui, repo, *revs, **opts):
3796 def debugsuccessorssets(ui, repo, *revs, **opts):
3743 """show set of successors for revision
3797 """show set of successors for revision
3744
3798
3745 A successors set of changeset A is a consistent group of revisions that
3799 A successors set of changeset A is a consistent group of revisions that
3746 succeed A. It contains non-obsolete changesets only unless closests
3800 succeed A. It contains non-obsolete changesets only unless closests
3747 successors set is set.
3801 successors set is set.
3748
3802
3749 In most cases a changeset A has a single successors set containing a single
3803 In most cases a changeset A has a single successors set containing a single
3750 successor (changeset A replaced by A').
3804 successor (changeset A replaced by A').
3751
3805
3752 A changeset that is made obsolete with no successors are called "pruned".
3806 A changeset that is made obsolete with no successors are called "pruned".
3753 Such changesets have no successors sets at all.
3807 Such changesets have no successors sets at all.
3754
3808
3755 A changeset that has been "split" will have a successors set containing
3809 A changeset that has been "split" will have a successors set containing
3756 more than one successor.
3810 more than one successor.
3757
3811
3758 A changeset that has been rewritten in multiple different ways is called
3812 A changeset that has been rewritten in multiple different ways is called
3759 "divergent". Such changesets have multiple successor sets (each of which
3813 "divergent". Such changesets have multiple successor sets (each of which
3760 may also be split, i.e. have multiple successors).
3814 may also be split, i.e. have multiple successors).
3761
3815
3762 Results are displayed as follows::
3816 Results are displayed as follows::
3763
3817
3764 <rev1>
3818 <rev1>
3765 <successors-1A>
3819 <successors-1A>
3766 <rev2>
3820 <rev2>
3767 <successors-2A>
3821 <successors-2A>
3768 <successors-2B1> <successors-2B2> <successors-2B3>
3822 <successors-2B1> <successors-2B2> <successors-2B3>
3769
3823
3770 Here rev2 has two possible (i.e. divergent) successors sets. The first
3824 Here rev2 has two possible (i.e. divergent) successors sets. The first
3771 holds one element, whereas the second holds three (i.e. the changeset has
3825 holds one element, whereas the second holds three (i.e. the changeset has
3772 been split).
3826 been split).
3773 """
3827 """
3774 # passed to successorssets caching computation from one call to another
3828 # passed to successorssets caching computation from one call to another
3775 cache = {}
3829 cache = {}
3776 ctx2str = bytes
3830 ctx2str = bytes
3777 node2str = short
3831 node2str = short
3778 for rev in scmutil.revrange(repo, revs):
3832 for rev in scmutil.revrange(repo, revs):
3779 ctx = repo[rev]
3833 ctx = repo[rev]
3780 ui.write(b'%s\n' % ctx2str(ctx))
3834 ui.write(b'%s\n' % ctx2str(ctx))
3781 for succsset in obsutil.successorssets(
3835 for succsset in obsutil.successorssets(
3782 repo, ctx.node(), closest=opts['closest'], cache=cache
3836 repo, ctx.node(), closest=opts['closest'], cache=cache
3783 ):
3837 ):
3784 if succsset:
3838 if succsset:
3785 ui.write(b' ')
3839 ui.write(b' ')
3786 ui.write(node2str(succsset[0]))
3840 ui.write(node2str(succsset[0]))
3787 for node in succsset[1:]:
3841 for node in succsset[1:]:
3788 ui.write(b' ')
3842 ui.write(b' ')
3789 ui.write(node2str(node))
3843 ui.write(node2str(node))
3790 ui.write(b'\n')
3844 ui.write(b'\n')
3791
3845
3792
3846
3793 @command(b'debugtagscache', [])
3847 @command(b'debugtagscache', [])
3794 def debugtagscache(ui, repo):
3848 def debugtagscache(ui, repo):
3795 """display the contents of .hg/cache/hgtagsfnodes1"""
3849 """display the contents of .hg/cache/hgtagsfnodes1"""
3796 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3850 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3797 for r in repo:
3851 for r in repo:
3798 node = repo[r].node()
3852 node = repo[r].node()
3799 tagsnode = cache.getfnode(node, computemissing=False)
3853 tagsnode = cache.getfnode(node, computemissing=False)
3800 tagsnodedisplay = hex(tagsnode) if tagsnode else b'missing/invalid'
3854 tagsnodedisplay = hex(tagsnode) if tagsnode else b'missing/invalid'
3801 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3855 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3802
3856
3803
3857
3804 @command(
3858 @command(
3805 b'debugtemplate',
3859 b'debugtemplate',
3806 [
3860 [
3807 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3861 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3808 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3862 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3809 ],
3863 ],
3810 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3864 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3811 optionalrepo=True,
3865 optionalrepo=True,
3812 )
3866 )
3813 def debugtemplate(ui, repo, tmpl, **opts):
3867 def debugtemplate(ui, repo, tmpl, **opts):
3814 """parse and apply a template
3868 """parse and apply a template
3815
3869
3816 If -r/--rev is given, the template is processed as a log template and
3870 If -r/--rev is given, the template is processed as a log template and
3817 applied to the given changesets. Otherwise, it is processed as a generic
3871 applied to the given changesets. Otherwise, it is processed as a generic
3818 template.
3872 template.
3819
3873
3820 Use --verbose to print the parsed tree.
3874 Use --verbose to print the parsed tree.
3821 """
3875 """
3822 revs = None
3876 revs = None
3823 if opts['rev']:
3877 if opts['rev']:
3824 if repo is None:
3878 if repo is None:
3825 raise error.RepoError(
3879 raise error.RepoError(
3826 _(b'there is no Mercurial repository here (.hg not found)')
3880 _(b'there is no Mercurial repository here (.hg not found)')
3827 )
3881 )
3828 revs = scmutil.revrange(repo, opts['rev'])
3882 revs = scmutil.revrange(repo, opts['rev'])
3829
3883
3830 props = {}
3884 props = {}
3831 for d in opts['define']:
3885 for d in opts['define']:
3832 try:
3886 try:
3833 k, v = (e.strip() for e in d.split(b'=', 1))
3887 k, v = (e.strip() for e in d.split(b'=', 1))
3834 if not k or k == b'ui':
3888 if not k or k == b'ui':
3835 raise ValueError
3889 raise ValueError
3836 props[k] = v
3890 props[k] = v
3837 except ValueError:
3891 except ValueError:
3838 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3892 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3839
3893
3840 if ui.verbose:
3894 if ui.verbose:
3841 aliases = ui.configitems(b'templatealias')
3895 aliases = ui.configitems(b'templatealias')
3842 tree = templater.parse(tmpl)
3896 tree = templater.parse(tmpl)
3843 ui.note(templater.prettyformat(tree), b'\n')
3897 ui.note(templater.prettyformat(tree), b'\n')
3844 newtree = templater.expandaliases(tree, aliases)
3898 newtree = templater.expandaliases(tree, aliases)
3845 if newtree != tree:
3899 if newtree != tree:
3846 ui.notenoi18n(
3900 ui.notenoi18n(
3847 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3901 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3848 )
3902 )
3849
3903
3850 if revs is None:
3904 if revs is None:
3851 tres = formatter.templateresources(ui, repo)
3905 tres = formatter.templateresources(ui, repo)
3852 t = formatter.maketemplater(ui, tmpl, resources=tres)
3906 t = formatter.maketemplater(ui, tmpl, resources=tres)
3853 if ui.verbose:
3907 if ui.verbose:
3854 kwds, funcs = t.symbolsuseddefault()
3908 kwds, funcs = t.symbolsuseddefault()
3855 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3909 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3856 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3910 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3857 ui.write(t.renderdefault(props))
3911 ui.write(t.renderdefault(props))
3858 else:
3912 else:
3859 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3913 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3860 if ui.verbose:
3914 if ui.verbose:
3861 kwds, funcs = displayer.t.symbolsuseddefault()
3915 kwds, funcs = displayer.t.symbolsuseddefault()
3862 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3916 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3863 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3917 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3864 for r in revs:
3918 for r in revs:
3865 displayer.show(repo[r], **pycompat.strkwargs(props))
3919 displayer.show(repo[r], **pycompat.strkwargs(props))
3866 displayer.close()
3920 displayer.close()
3867
3921
3868
3922
3869 @command(
3923 @command(
3870 b'debuguigetpass',
3924 b'debuguigetpass',
3871 [
3925 [
3872 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3926 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3873 ],
3927 ],
3874 _(b'[-p TEXT]'),
3928 _(b'[-p TEXT]'),
3875 norepo=True,
3929 norepo=True,
3876 )
3930 )
3877 def debuguigetpass(ui, prompt=b''):
3931 def debuguigetpass(ui, prompt=b''):
3878 """show prompt to type password"""
3932 """show prompt to type password"""
3879 r = ui.getpass(prompt)
3933 r = ui.getpass(prompt)
3880 if r is None:
3934 if r is None:
3881 r = b"<default response>"
3935 r = b"<default response>"
3882 ui.writenoi18n(b'response: %s\n' % r)
3936 ui.writenoi18n(b'response: %s\n' % r)
3883
3937
3884
3938
3885 @command(
3939 @command(
3886 b'debuguiprompt',
3940 b'debuguiprompt',
3887 [
3941 [
3888 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3942 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3889 ],
3943 ],
3890 _(b'[-p TEXT]'),
3944 _(b'[-p TEXT]'),
3891 norepo=True,
3945 norepo=True,
3892 )
3946 )
3893 def debuguiprompt(ui, prompt=b''):
3947 def debuguiprompt(ui, prompt=b''):
3894 """show plain prompt"""
3948 """show plain prompt"""
3895 r = ui.prompt(prompt)
3949 r = ui.prompt(prompt)
3896 ui.writenoi18n(b'response: %s\n' % r)
3950 ui.writenoi18n(b'response: %s\n' % r)
3897
3951
3898
3952
3899 @command(b'debugupdatecaches', [])
3953 @command(b'debugupdatecaches', [])
3900 def debugupdatecaches(ui, repo, *pats, **opts):
3954 def debugupdatecaches(ui, repo, *pats, **opts):
3901 """warm all known caches in the repository"""
3955 """warm all known caches in the repository"""
3902 with repo.wlock(), repo.lock():
3956 with repo.wlock(), repo.lock():
3903 repo.updatecaches(full=True)
3957 repo.updatecaches(full=True)
3904
3958
3905
3959
3906 @command(
3960 @command(
3907 b'debugupgraderepo',
3961 b'debugupgraderepo',
3908 [
3962 [
3909 (
3963 (
3910 b'o',
3964 b'o',
3911 b'optimize',
3965 b'optimize',
3912 [],
3966 [],
3913 _(b'extra optimization to perform'),
3967 _(b'extra optimization to perform'),
3914 _(b'NAME'),
3968 _(b'NAME'),
3915 ),
3969 ),
3916 (b'', b'run', False, _(b'performs an upgrade')),
3970 (b'', b'run', False, _(b'performs an upgrade')),
3917 (b'', b'backup', True, _(b'keep the old repository content around')),
3971 (b'', b'backup', True, _(b'keep the old repository content around')),
3918 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
3972 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
3919 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
3973 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
3920 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
3974 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
3921 ],
3975 ],
3922 )
3976 )
3923 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
3977 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
3924 """upgrade a repository to use different features
3978 """upgrade a repository to use different features
3925
3979
3926 If no arguments are specified, the repository is evaluated for upgrade
3980 If no arguments are specified, the repository is evaluated for upgrade
3927 and a list of problems and potential optimizations is printed.
3981 and a list of problems and potential optimizations is printed.
3928
3982
3929 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
3983 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
3930 can be influenced via additional arguments. More details will be provided
3984 can be influenced via additional arguments. More details will be provided
3931 by the command output when run without ``--run``.
3985 by the command output when run without ``--run``.
3932
3986
3933 During the upgrade, the repository will be locked and no writes will be
3987 During the upgrade, the repository will be locked and no writes will be
3934 allowed.
3988 allowed.
3935
3989
3936 At the end of the upgrade, the repository may not be readable while new
3990 At the end of the upgrade, the repository may not be readable while new
3937 repository data is swapped in. This window will be as long as it takes to
3991 repository data is swapped in. This window will be as long as it takes to
3938 rename some directories inside the ``.hg`` directory. On most machines, this
3992 rename some directories inside the ``.hg`` directory. On most machines, this
3939 should complete almost instantaneously and the chances of a consumer being
3993 should complete almost instantaneously and the chances of a consumer being
3940 unable to access the repository should be low.
3994 unable to access the repository should be low.
3941
3995
3942 By default, all revlog will be upgraded. You can restrict this using flag
3996 By default, all revlog will be upgraded. You can restrict this using flag
3943 such as `--manifest`:
3997 such as `--manifest`:
3944
3998
3945 * `--manifest`: only optimize the manifest
3999 * `--manifest`: only optimize the manifest
3946 * `--no-manifest`: optimize all revlog but the manifest
4000 * `--no-manifest`: optimize all revlog but the manifest
3947 * `--changelog`: optimize the changelog only
4001 * `--changelog`: optimize the changelog only
3948 * `--no-changelog --no-manifest`: optimize filelogs only
4002 * `--no-changelog --no-manifest`: optimize filelogs only
3949 * `--filelogs`: optimize the filelogs only
4003 * `--filelogs`: optimize the filelogs only
3950 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4004 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
3951 """
4005 """
3952 return upgrade.upgraderepo(
4006 return upgrade.upgraderepo(
3953 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4007 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
3954 )
4008 )
3955
4009
3956
4010
3957 @command(
4011 @command(
3958 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4012 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
3959 )
4013 )
3960 def debugwalk(ui, repo, *pats, **opts):
4014 def debugwalk(ui, repo, *pats, **opts):
3961 """show how files match on given patterns"""
4015 """show how files match on given patterns"""
3962 opts = pycompat.byteskwargs(opts)
4016 opts = pycompat.byteskwargs(opts)
3963 m = scmutil.match(repo[None], pats, opts)
4017 m = scmutil.match(repo[None], pats, opts)
3964 if ui.verbose:
4018 if ui.verbose:
3965 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4019 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
3966 items = list(repo[None].walk(m))
4020 items = list(repo[None].walk(m))
3967 if not items:
4021 if not items:
3968 return
4022 return
3969 f = lambda fn: fn
4023 f = lambda fn: fn
3970 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4024 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
3971 f = lambda fn: util.normpath(fn)
4025 f = lambda fn: util.normpath(fn)
3972 fmt = b'f %%-%ds %%-%ds %%s' % (
4026 fmt = b'f %%-%ds %%-%ds %%s' % (
3973 max([len(abs) for abs in items]),
4027 max([len(abs) for abs in items]),
3974 max([len(repo.pathto(abs)) for abs in items]),
4028 max([len(repo.pathto(abs)) for abs in items]),
3975 )
4029 )
3976 for abs in items:
4030 for abs in items:
3977 line = fmt % (
4031 line = fmt % (
3978 abs,
4032 abs,
3979 f(repo.pathto(abs)),
4033 f(repo.pathto(abs)),
3980 m.exact(abs) and b'exact' or b'',
4034 m.exact(abs) and b'exact' or b'',
3981 )
4035 )
3982 ui.write(b"%s\n" % line.rstrip())
4036 ui.write(b"%s\n" % line.rstrip())
3983
4037
3984
4038
3985 @command(b'debugwhyunstable', [], _(b'REV'))
4039 @command(b'debugwhyunstable', [], _(b'REV'))
3986 def debugwhyunstable(ui, repo, rev):
4040 def debugwhyunstable(ui, repo, rev):
3987 """explain instabilities of a changeset"""
4041 """explain instabilities of a changeset"""
3988 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4042 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
3989 dnodes = b''
4043 dnodes = b''
3990 if entry.get(b'divergentnodes'):
4044 if entry.get(b'divergentnodes'):
3991 dnodes = (
4045 dnodes = (
3992 b' '.join(
4046 b' '.join(
3993 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4047 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
3994 for ctx in entry[b'divergentnodes']
4048 for ctx in entry[b'divergentnodes']
3995 )
4049 )
3996 + b' '
4050 + b' '
3997 )
4051 )
3998 ui.write(
4052 ui.write(
3999 b'%s: %s%s %s\n'
4053 b'%s: %s%s %s\n'
4000 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4054 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4001 )
4055 )
4002
4056
4003
4057
4004 @command(
4058 @command(
4005 b'debugwireargs',
4059 b'debugwireargs',
4006 [
4060 [
4007 (b'', b'three', b'', b'three'),
4061 (b'', b'three', b'', b'three'),
4008 (b'', b'four', b'', b'four'),
4062 (b'', b'four', b'', b'four'),
4009 (b'', b'five', b'', b'five'),
4063 (b'', b'five', b'', b'five'),
4010 ]
4064 ]
4011 + cmdutil.remoteopts,
4065 + cmdutil.remoteopts,
4012 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4066 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4013 norepo=True,
4067 norepo=True,
4014 )
4068 )
4015 def debugwireargs(ui, repopath, *vals, **opts):
4069 def debugwireargs(ui, repopath, *vals, **opts):
4016 opts = pycompat.byteskwargs(opts)
4070 opts = pycompat.byteskwargs(opts)
4017 repo = hg.peer(ui, opts, repopath)
4071 repo = hg.peer(ui, opts, repopath)
4018 for opt in cmdutil.remoteopts:
4072 for opt in cmdutil.remoteopts:
4019 del opts[opt[1]]
4073 del opts[opt[1]]
4020 args = {}
4074 args = {}
4021 for k, v in pycompat.iteritems(opts):
4075 for k, v in pycompat.iteritems(opts):
4022 if v:
4076 if v:
4023 args[k] = v
4077 args[k] = v
4024 args = pycompat.strkwargs(args)
4078 args = pycompat.strkwargs(args)
4025 # run twice to check that we don't mess up the stream for the next command
4079 # run twice to check that we don't mess up the stream for the next command
4026 res1 = repo.debugwireargs(*vals, **args)
4080 res1 = repo.debugwireargs(*vals, **args)
4027 res2 = repo.debugwireargs(*vals, **args)
4081 res2 = repo.debugwireargs(*vals, **args)
4028 ui.write(b"%s\n" % res1)
4082 ui.write(b"%s\n" % res1)
4029 if res1 != res2:
4083 if res1 != res2:
4030 ui.warn(b"%s\n" % res2)
4084 ui.warn(b"%s\n" % res2)
4031
4085
4032
4086
4033 def _parsewirelangblocks(fh):
4087 def _parsewirelangblocks(fh):
4034 activeaction = None
4088 activeaction = None
4035 blocklines = []
4089 blocklines = []
4036 lastindent = 0
4090 lastindent = 0
4037
4091
4038 for line in fh:
4092 for line in fh:
4039 line = line.rstrip()
4093 line = line.rstrip()
4040 if not line:
4094 if not line:
4041 continue
4095 continue
4042
4096
4043 if line.startswith(b'#'):
4097 if line.startswith(b'#'):
4044 continue
4098 continue
4045
4099
4046 if not line.startswith(b' '):
4100 if not line.startswith(b' '):
4047 # New block. Flush previous one.
4101 # New block. Flush previous one.
4048 if activeaction:
4102 if activeaction:
4049 yield activeaction, blocklines
4103 yield activeaction, blocklines
4050
4104
4051 activeaction = line
4105 activeaction = line
4052 blocklines = []
4106 blocklines = []
4053 lastindent = 0
4107 lastindent = 0
4054 continue
4108 continue
4055
4109
4056 # Else we start with an indent.
4110 # Else we start with an indent.
4057
4111
4058 if not activeaction:
4112 if not activeaction:
4059 raise error.Abort(_(b'indented line outside of block'))
4113 raise error.Abort(_(b'indented line outside of block'))
4060
4114
4061 indent = len(line) - len(line.lstrip())
4115 indent = len(line) - len(line.lstrip())
4062
4116
4063 # If this line is indented more than the last line, concatenate it.
4117 # If this line is indented more than the last line, concatenate it.
4064 if indent > lastindent and blocklines:
4118 if indent > lastindent and blocklines:
4065 blocklines[-1] += line.lstrip()
4119 blocklines[-1] += line.lstrip()
4066 else:
4120 else:
4067 blocklines.append(line)
4121 blocklines.append(line)
4068 lastindent = indent
4122 lastindent = indent
4069
4123
4070 # Flush last block.
4124 # Flush last block.
4071 if activeaction:
4125 if activeaction:
4072 yield activeaction, blocklines
4126 yield activeaction, blocklines
4073
4127
4074
4128
4075 @command(
4129 @command(
4076 b'debugwireproto',
4130 b'debugwireproto',
4077 [
4131 [
4078 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4132 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4079 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4133 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4080 (
4134 (
4081 b'',
4135 b'',
4082 b'noreadstderr',
4136 b'noreadstderr',
4083 False,
4137 False,
4084 _(b'do not read from stderr of the remote'),
4138 _(b'do not read from stderr of the remote'),
4085 ),
4139 ),
4086 (
4140 (
4087 b'',
4141 b'',
4088 b'nologhandshake',
4142 b'nologhandshake',
4089 False,
4143 False,
4090 _(b'do not log I/O related to the peer handshake'),
4144 _(b'do not log I/O related to the peer handshake'),
4091 ),
4145 ),
4092 ]
4146 ]
4093 + cmdutil.remoteopts,
4147 + cmdutil.remoteopts,
4094 _(b'[PATH]'),
4148 _(b'[PATH]'),
4095 optionalrepo=True,
4149 optionalrepo=True,
4096 )
4150 )
4097 def debugwireproto(ui, repo, path=None, **opts):
4151 def debugwireproto(ui, repo, path=None, **opts):
4098 """send wire protocol commands to a server
4152 """send wire protocol commands to a server
4099
4153
4100 This command can be used to issue wire protocol commands to remote
4154 This command can be used to issue wire protocol commands to remote
4101 peers and to debug the raw data being exchanged.
4155 peers and to debug the raw data being exchanged.
4102
4156
4103 ``--localssh`` will start an SSH server against the current repository
4157 ``--localssh`` will start an SSH server against the current repository
4104 and connect to that. By default, the connection will perform a handshake
4158 and connect to that. By default, the connection will perform a handshake
4105 and establish an appropriate peer instance.
4159 and establish an appropriate peer instance.
4106
4160
4107 ``--peer`` can be used to bypass the handshake protocol and construct a
4161 ``--peer`` can be used to bypass the handshake protocol and construct a
4108 peer instance using the specified class type. Valid values are ``raw``,
4162 peer instance using the specified class type. Valid values are ``raw``,
4109 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
4163 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
4110 raw data payloads and don't support higher-level command actions.
4164 raw data payloads and don't support higher-level command actions.
4111
4165
4112 ``--noreadstderr`` can be used to disable automatic reading from stderr
4166 ``--noreadstderr`` can be used to disable automatic reading from stderr
4113 of the peer (for SSH connections only). Disabling automatic reading of
4167 of the peer (for SSH connections only). Disabling automatic reading of
4114 stderr is useful for making output more deterministic.
4168 stderr is useful for making output more deterministic.
4115
4169
4116 Commands are issued via a mini language which is specified via stdin.
4170 Commands are issued via a mini language which is specified via stdin.
4117 The language consists of individual actions to perform. An action is
4171 The language consists of individual actions to perform. An action is
4118 defined by a block. A block is defined as a line with no leading
4172 defined by a block. A block is defined as a line with no leading
4119 space followed by 0 or more lines with leading space. Blocks are
4173 space followed by 0 or more lines with leading space. Blocks are
4120 effectively a high-level command with additional metadata.
4174 effectively a high-level command with additional metadata.
4121
4175
4122 Lines beginning with ``#`` are ignored.
4176 Lines beginning with ``#`` are ignored.
4123
4177
4124 The following sections denote available actions.
4178 The following sections denote available actions.
4125
4179
4126 raw
4180 raw
4127 ---
4181 ---
4128
4182
4129 Send raw data to the server.
4183 Send raw data to the server.
4130
4184
4131 The block payload contains the raw data to send as one atomic send
4185 The block payload contains the raw data to send as one atomic send
4132 operation. The data may not actually be delivered in a single system
4186 operation. The data may not actually be delivered in a single system
4133 call: it depends on the abilities of the transport being used.
4187 call: it depends on the abilities of the transport being used.
4134
4188
4135 Each line in the block is de-indented and concatenated. Then, that
4189 Each line in the block is de-indented and concatenated. Then, that
4136 value is evaluated as a Python b'' literal. This allows the use of
4190 value is evaluated as a Python b'' literal. This allows the use of
4137 backslash escaping, etc.
4191 backslash escaping, etc.
4138
4192
4139 raw+
4193 raw+
4140 ----
4194 ----
4141
4195
4142 Behaves like ``raw`` except flushes output afterwards.
4196 Behaves like ``raw`` except flushes output afterwards.
4143
4197
4144 command <X>
4198 command <X>
4145 -----------
4199 -----------
4146
4200
4147 Send a request to run a named command, whose name follows the ``command``
4201 Send a request to run a named command, whose name follows the ``command``
4148 string.
4202 string.
4149
4203
4150 Arguments to the command are defined as lines in this block. The format of
4204 Arguments to the command are defined as lines in this block. The format of
4151 each line is ``<key> <value>``. e.g.::
4205 each line is ``<key> <value>``. e.g.::
4152
4206
4153 command listkeys
4207 command listkeys
4154 namespace bookmarks
4208 namespace bookmarks
4155
4209
4156 If the value begins with ``eval:``, it will be interpreted as a Python
4210 If the value begins with ``eval:``, it will be interpreted as a Python
4157 literal expression. Otherwise values are interpreted as Python b'' literals.
4211 literal expression. Otherwise values are interpreted as Python b'' literals.
4158 This allows sending complex types and encoding special byte sequences via
4212 This allows sending complex types and encoding special byte sequences via
4159 backslash escaping.
4213 backslash escaping.
4160
4214
4161 The following arguments have special meaning:
4215 The following arguments have special meaning:
4162
4216
4163 ``PUSHFILE``
4217 ``PUSHFILE``
4164 When defined, the *push* mechanism of the peer will be used instead
4218 When defined, the *push* mechanism of the peer will be used instead
4165 of the static request-response mechanism and the content of the
4219 of the static request-response mechanism and the content of the
4166 file specified in the value of this argument will be sent as the
4220 file specified in the value of this argument will be sent as the
4167 command payload.
4221 command payload.
4168
4222
4169 This can be used to submit a local bundle file to the remote.
4223 This can be used to submit a local bundle file to the remote.
4170
4224
4171 batchbegin
4225 batchbegin
4172 ----------
4226 ----------
4173
4227
4174 Instruct the peer to begin a batched send.
4228 Instruct the peer to begin a batched send.
4175
4229
4176 All ``command`` blocks are queued for execution until the next
4230 All ``command`` blocks are queued for execution until the next
4177 ``batchsubmit`` block.
4231 ``batchsubmit`` block.
4178
4232
4179 batchsubmit
4233 batchsubmit
4180 -----------
4234 -----------
4181
4235
4182 Submit previously queued ``command`` blocks as a batch request.
4236 Submit previously queued ``command`` blocks as a batch request.
4183
4237
4184 This action MUST be paired with a ``batchbegin`` action.
4238 This action MUST be paired with a ``batchbegin`` action.
4185
4239
4186 httprequest <method> <path>
4240 httprequest <method> <path>
4187 ---------------------------
4241 ---------------------------
4188
4242
4189 (HTTP peer only)
4243 (HTTP peer only)
4190
4244
4191 Send an HTTP request to the peer.
4245 Send an HTTP request to the peer.
4192
4246
4193 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4247 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4194
4248
4195 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4249 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4196 headers to add to the request. e.g. ``Accept: foo``.
4250 headers to add to the request. e.g. ``Accept: foo``.
4197
4251
4198 The following arguments are special:
4252 The following arguments are special:
4199
4253
4200 ``BODYFILE``
4254 ``BODYFILE``
4201 The content of the file defined as the value to this argument will be
4255 The content of the file defined as the value to this argument will be
4202 transferred verbatim as the HTTP request body.
4256 transferred verbatim as the HTTP request body.
4203
4257
4204 ``frame <type> <flags> <payload>``
4258 ``frame <type> <flags> <payload>``
4205 Send a unified protocol frame as part of the request body.
4259 Send a unified protocol frame as part of the request body.
4206
4260
4207 All frames will be collected and sent as the body to the HTTP
4261 All frames will be collected and sent as the body to the HTTP
4208 request.
4262 request.
4209
4263
4210 close
4264 close
4211 -----
4265 -----
4212
4266
4213 Close the connection to the server.
4267 Close the connection to the server.
4214
4268
4215 flush
4269 flush
4216 -----
4270 -----
4217
4271
4218 Flush data written to the server.
4272 Flush data written to the server.
4219
4273
4220 readavailable
4274 readavailable
4221 -------------
4275 -------------
4222
4276
4223 Close the write end of the connection and read all available data from
4277 Close the write end of the connection and read all available data from
4224 the server.
4278 the server.
4225
4279
4226 If the connection to the server encompasses multiple pipes, we poll both
4280 If the connection to the server encompasses multiple pipes, we poll both
4227 pipes and read available data.
4281 pipes and read available data.
4228
4282
4229 readline
4283 readline
4230 --------
4284 --------
4231
4285
4232 Read a line of output from the server. If there are multiple output
4286 Read a line of output from the server. If there are multiple output
4233 pipes, reads only the main pipe.
4287 pipes, reads only the main pipe.
4234
4288
4235 ereadline
4289 ereadline
4236 ---------
4290 ---------
4237
4291
4238 Like ``readline``, but read from the stderr pipe, if available.
4292 Like ``readline``, but read from the stderr pipe, if available.
4239
4293
4240 read <X>
4294 read <X>
4241 --------
4295 --------
4242
4296
4243 ``read()`` N bytes from the server's main output pipe.
4297 ``read()`` N bytes from the server's main output pipe.
4244
4298
4245 eread <X>
4299 eread <X>
4246 ---------
4300 ---------
4247
4301
4248 ``read()`` N bytes from the server's stderr pipe, if available.
4302 ``read()`` N bytes from the server's stderr pipe, if available.
4249
4303
4250 Specifying Unified Frame-Based Protocol Frames
4304 Specifying Unified Frame-Based Protocol Frames
4251 ----------------------------------------------
4305 ----------------------------------------------
4252
4306
4253 It is possible to emit a *Unified Frame-Based Protocol* by using special
4307 It is possible to emit a *Unified Frame-Based Protocol* by using special
4254 syntax.
4308 syntax.
4255
4309
4256 A frame is composed as a type, flags, and payload. These can be parsed
4310 A frame is composed as a type, flags, and payload. These can be parsed
4257 from a string of the form:
4311 from a string of the form:
4258
4312
4259 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4313 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4260
4314
4261 ``request-id`` and ``stream-id`` are integers defining the request and
4315 ``request-id`` and ``stream-id`` are integers defining the request and
4262 stream identifiers.
4316 stream identifiers.
4263
4317
4264 ``type`` can be an integer value for the frame type or the string name
4318 ``type`` can be an integer value for the frame type or the string name
4265 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4319 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4266 ``command-name``.
4320 ``command-name``.
4267
4321
4268 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4322 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4269 components. Each component (and there can be just one) can be an integer
4323 components. Each component (and there can be just one) can be an integer
4270 or a flag name for stream flags or frame flags, respectively. Values are
4324 or a flag name for stream flags or frame flags, respectively. Values are
4271 resolved to integers and then bitwise OR'd together.
4325 resolved to integers and then bitwise OR'd together.
4272
4326
4273 ``payload`` represents the raw frame payload. If it begins with
4327 ``payload`` represents the raw frame payload. If it begins with
4274 ``cbor:``, the following string is evaluated as Python code and the
4328 ``cbor:``, the following string is evaluated as Python code and the
4275 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4329 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4276 as a Python byte string literal.
4330 as a Python byte string literal.
4277 """
4331 """
4278 opts = pycompat.byteskwargs(opts)
4332 opts = pycompat.byteskwargs(opts)
4279
4333
4280 if opts[b'localssh'] and not repo:
4334 if opts[b'localssh'] and not repo:
4281 raise error.Abort(_(b'--localssh requires a repository'))
4335 raise error.Abort(_(b'--localssh requires a repository'))
4282
4336
4283 if opts[b'peer'] and opts[b'peer'] not in (
4337 if opts[b'peer'] and opts[b'peer'] not in (
4284 b'raw',
4338 b'raw',
4285 b'http2',
4339 b'http2',
4286 b'ssh1',
4340 b'ssh1',
4287 b'ssh2',
4341 b'ssh2',
4288 ):
4342 ):
4289 raise error.Abort(
4343 raise error.Abort(
4290 _(b'invalid value for --peer'),
4344 _(b'invalid value for --peer'),
4291 hint=_(b'valid values are "raw", "ssh1", and "ssh2"'),
4345 hint=_(b'valid values are "raw", "ssh1", and "ssh2"'),
4292 )
4346 )
4293
4347
4294 if path and opts[b'localssh']:
4348 if path and opts[b'localssh']:
4295 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4349 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4296
4350
4297 if ui.interactive():
4351 if ui.interactive():
4298 ui.write(_(b'(waiting for commands on stdin)\n'))
4352 ui.write(_(b'(waiting for commands on stdin)\n'))
4299
4353
4300 blocks = list(_parsewirelangblocks(ui.fin))
4354 blocks = list(_parsewirelangblocks(ui.fin))
4301
4355
4302 proc = None
4356 proc = None
4303 stdin = None
4357 stdin = None
4304 stdout = None
4358 stdout = None
4305 stderr = None
4359 stderr = None
4306 opener = None
4360 opener = None
4307
4361
4308 if opts[b'localssh']:
4362 if opts[b'localssh']:
4309 # We start the SSH server in its own process so there is process
4363 # We start the SSH server in its own process so there is process
4310 # separation. This prevents a whole class of potential bugs around
4364 # separation. This prevents a whole class of potential bugs around
4311 # shared state from interfering with server operation.
4365 # shared state from interfering with server operation.
4312 args = procutil.hgcmd() + [
4366 args = procutil.hgcmd() + [
4313 b'-R',
4367 b'-R',
4314 repo.root,
4368 repo.root,
4315 b'debugserve',
4369 b'debugserve',
4316 b'--sshstdio',
4370 b'--sshstdio',
4317 ]
4371 ]
4318 proc = subprocess.Popen(
4372 proc = subprocess.Popen(
4319 pycompat.rapply(procutil.tonativestr, args),
4373 pycompat.rapply(procutil.tonativestr, args),
4320 stdin=subprocess.PIPE,
4374 stdin=subprocess.PIPE,
4321 stdout=subprocess.PIPE,
4375 stdout=subprocess.PIPE,
4322 stderr=subprocess.PIPE,
4376 stderr=subprocess.PIPE,
4323 bufsize=0,
4377 bufsize=0,
4324 )
4378 )
4325
4379
4326 stdin = proc.stdin
4380 stdin = proc.stdin
4327 stdout = proc.stdout
4381 stdout = proc.stdout
4328 stderr = proc.stderr
4382 stderr = proc.stderr
4329
4383
4330 # We turn the pipes into observers so we can log I/O.
4384 # We turn the pipes into observers so we can log I/O.
4331 if ui.verbose or opts[b'peer'] == b'raw':
4385 if ui.verbose or opts[b'peer'] == b'raw':
4332 stdin = util.makeloggingfileobject(
4386 stdin = util.makeloggingfileobject(
4333 ui, proc.stdin, b'i', logdata=True
4387 ui, proc.stdin, b'i', logdata=True
4334 )
4388 )
4335 stdout = util.makeloggingfileobject(
4389 stdout = util.makeloggingfileobject(
4336 ui, proc.stdout, b'o', logdata=True
4390 ui, proc.stdout, b'o', logdata=True
4337 )
4391 )
4338 stderr = util.makeloggingfileobject(
4392 stderr = util.makeloggingfileobject(
4339 ui, proc.stderr, b'e', logdata=True
4393 ui, proc.stderr, b'e', logdata=True
4340 )
4394 )
4341
4395
4342 # --localssh also implies the peer connection settings.
4396 # --localssh also implies the peer connection settings.
4343
4397
4344 url = b'ssh://localserver'
4398 url = b'ssh://localserver'
4345 autoreadstderr = not opts[b'noreadstderr']
4399 autoreadstderr = not opts[b'noreadstderr']
4346
4400
4347 if opts[b'peer'] == b'ssh1':
4401 if opts[b'peer'] == b'ssh1':
4348 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4402 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4349 peer = sshpeer.sshv1peer(
4403 peer = sshpeer.sshv1peer(
4350 ui,
4404 ui,
4351 url,
4405 url,
4352 proc,
4406 proc,
4353 stdin,
4407 stdin,
4354 stdout,
4408 stdout,
4355 stderr,
4409 stderr,
4356 None,
4410 None,
4357 autoreadstderr=autoreadstderr,
4411 autoreadstderr=autoreadstderr,
4358 )
4412 )
4359 elif opts[b'peer'] == b'ssh2':
4413 elif opts[b'peer'] == b'ssh2':
4360 ui.write(_(b'creating ssh peer for wire protocol version 2\n'))
4414 ui.write(_(b'creating ssh peer for wire protocol version 2\n'))
4361 peer = sshpeer.sshv2peer(
4415 peer = sshpeer.sshv2peer(
4362 ui,
4416 ui,
4363 url,
4417 url,
4364 proc,
4418 proc,
4365 stdin,
4419 stdin,
4366 stdout,
4420 stdout,
4367 stderr,
4421 stderr,
4368 None,
4422 None,
4369 autoreadstderr=autoreadstderr,
4423 autoreadstderr=autoreadstderr,
4370 )
4424 )
4371 elif opts[b'peer'] == b'raw':
4425 elif opts[b'peer'] == b'raw':
4372 ui.write(_(b'using raw connection to peer\n'))
4426 ui.write(_(b'using raw connection to peer\n'))
4373 peer = None
4427 peer = None
4374 else:
4428 else:
4375 ui.write(_(b'creating ssh peer from handshake results\n'))
4429 ui.write(_(b'creating ssh peer from handshake results\n'))
4376 peer = sshpeer.makepeer(
4430 peer = sshpeer.makepeer(
4377 ui,
4431 ui,
4378 url,
4432 url,
4379 proc,
4433 proc,
4380 stdin,
4434 stdin,
4381 stdout,
4435 stdout,
4382 stderr,
4436 stderr,
4383 autoreadstderr=autoreadstderr,
4437 autoreadstderr=autoreadstderr,
4384 )
4438 )
4385
4439
4386 elif path:
4440 elif path:
4387 # We bypass hg.peer() so we can proxy the sockets.
4441 # We bypass hg.peer() so we can proxy the sockets.
4388 # TODO consider not doing this because we skip
4442 # TODO consider not doing this because we skip
4389 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4443 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4390 u = util.url(path)
4444 u = util.url(path)
4391 if u.scheme != b'http':
4445 if u.scheme != b'http':
4392 raise error.Abort(_(b'only http:// paths are currently supported'))
4446 raise error.Abort(_(b'only http:// paths are currently supported'))
4393
4447
4394 url, authinfo = u.authinfo()
4448 url, authinfo = u.authinfo()
4395 openerargs = {
4449 openerargs = {
4396 'useragent': b'Mercurial debugwireproto',
4450 'useragent': b'Mercurial debugwireproto',
4397 }
4451 }
4398
4452
4399 # Turn pipes/sockets into observers so we can log I/O.
4453 # Turn pipes/sockets into observers so we can log I/O.
4400 if ui.verbose:
4454 if ui.verbose:
4401 openerargs.update(
4455 openerargs.update(
4402 {
4456 {
4403 'loggingfh': ui,
4457 'loggingfh': ui,
4404 'loggingname': b's',
4458 'loggingname': b's',
4405 'loggingopts': {
4459 'loggingopts': {
4406 'logdata': True,
4460 'logdata': True,
4407 'logdataapis': False,
4461 'logdataapis': False,
4408 },
4462 },
4409 }
4463 }
4410 )
4464 )
4411
4465
4412 if ui.debugflag:
4466 if ui.debugflag:
4413 openerargs['loggingopts']['logdataapis'] = True
4467 openerargs['loggingopts']['logdataapis'] = True
4414
4468
4415 # Don't send default headers when in raw mode. This allows us to
4469 # Don't send default headers when in raw mode. This allows us to
4416 # bypass most of the behavior of our URL handling code so we can
4470 # bypass most of the behavior of our URL handling code so we can
4417 # have near complete control over what's sent on the wire.
4471 # have near complete control over what's sent on the wire.
4418 if opts[b'peer'] == b'raw':
4472 if opts[b'peer'] == b'raw':
4419 openerargs['sendaccept'] = False
4473 openerargs['sendaccept'] = False
4420
4474
4421 opener = urlmod.opener(ui, authinfo, **openerargs)
4475 opener = urlmod.opener(ui, authinfo, **openerargs)
4422
4476
4423 if opts[b'peer'] == b'http2':
4477 if opts[b'peer'] == b'http2':
4424 ui.write(_(b'creating http peer for wire protocol version 2\n'))
4478 ui.write(_(b'creating http peer for wire protocol version 2\n'))
4425 # We go through makepeer() because we need an API descriptor for
4479 # We go through makepeer() because we need an API descriptor for
4426 # the peer instance to be useful.
4480 # the peer instance to be useful.
4427 with ui.configoverride(
4481 with ui.configoverride(
4428 {(b'experimental', b'httppeer.advertise-v2'): True}
4482 {(b'experimental', b'httppeer.advertise-v2'): True}
4429 ):
4483 ):
4430 if opts[b'nologhandshake']:
4484 if opts[b'nologhandshake']:
4431 ui.pushbuffer()
4485 ui.pushbuffer()
4432
4486
4433 peer = httppeer.makepeer(ui, path, opener=opener)
4487 peer = httppeer.makepeer(ui, path, opener=opener)
4434
4488
4435 if opts[b'nologhandshake']:
4489 if opts[b'nologhandshake']:
4436 ui.popbuffer()
4490 ui.popbuffer()
4437
4491
4438 if not isinstance(peer, httppeer.httpv2peer):
4492 if not isinstance(peer, httppeer.httpv2peer):
4439 raise error.Abort(
4493 raise error.Abort(
4440 _(
4494 _(
4441 b'could not instantiate HTTP peer for '
4495 b'could not instantiate HTTP peer for '
4442 b'wire protocol version 2'
4496 b'wire protocol version 2'
4443 ),
4497 ),
4444 hint=_(
4498 hint=_(
4445 b'the server may not have the feature '
4499 b'the server may not have the feature '
4446 b'enabled or is not allowing this '
4500 b'enabled or is not allowing this '
4447 b'client version'
4501 b'client version'
4448 ),
4502 ),
4449 )
4503 )
4450
4504
4451 elif opts[b'peer'] == b'raw':
4505 elif opts[b'peer'] == b'raw':
4452 ui.write(_(b'using raw connection to peer\n'))
4506 ui.write(_(b'using raw connection to peer\n'))
4453 peer = None
4507 peer = None
4454 elif opts[b'peer']:
4508 elif opts[b'peer']:
4455 raise error.Abort(
4509 raise error.Abort(
4456 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4510 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4457 )
4511 )
4458 else:
4512 else:
4459 peer = httppeer.makepeer(ui, path, opener=opener)
4513 peer = httppeer.makepeer(ui, path, opener=opener)
4460
4514
4461 # We /could/ populate stdin/stdout with sock.makefile()...
4515 # We /could/ populate stdin/stdout with sock.makefile()...
4462 else:
4516 else:
4463 raise error.Abort(_(b'unsupported connection configuration'))
4517 raise error.Abort(_(b'unsupported connection configuration'))
4464
4518
4465 batchedcommands = None
4519 batchedcommands = None
4466
4520
4467 # Now perform actions based on the parsed wire language instructions.
4521 # Now perform actions based on the parsed wire language instructions.
4468 for action, lines in blocks:
4522 for action, lines in blocks:
4469 if action in (b'raw', b'raw+'):
4523 if action in (b'raw', b'raw+'):
4470 if not stdin:
4524 if not stdin:
4471 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4525 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4472
4526
4473 # Concatenate the data together.
4527 # Concatenate the data together.
4474 data = b''.join(l.lstrip() for l in lines)
4528 data = b''.join(l.lstrip() for l in lines)
4475 data = stringutil.unescapestr(data)
4529 data = stringutil.unescapestr(data)
4476 stdin.write(data)
4530 stdin.write(data)
4477
4531
4478 if action == b'raw+':
4532 if action == b'raw+':
4479 stdin.flush()
4533 stdin.flush()
4480 elif action == b'flush':
4534 elif action == b'flush':
4481 if not stdin:
4535 if not stdin:
4482 raise error.Abort(_(b'cannot call flush on this peer'))
4536 raise error.Abort(_(b'cannot call flush on this peer'))
4483 stdin.flush()
4537 stdin.flush()
4484 elif action.startswith(b'command'):
4538 elif action.startswith(b'command'):
4485 if not peer:
4539 if not peer:
4486 raise error.Abort(
4540 raise error.Abort(
4487 _(
4541 _(
4488 b'cannot send commands unless peer instance '
4542 b'cannot send commands unless peer instance '
4489 b'is available'
4543 b'is available'
4490 )
4544 )
4491 )
4545 )
4492
4546
4493 command = action.split(b' ', 1)[1]
4547 command = action.split(b' ', 1)[1]
4494
4548
4495 args = {}
4549 args = {}
4496 for line in lines:
4550 for line in lines:
4497 # We need to allow empty values.
4551 # We need to allow empty values.
4498 fields = line.lstrip().split(b' ', 1)
4552 fields = line.lstrip().split(b' ', 1)
4499 if len(fields) == 1:
4553 if len(fields) == 1:
4500 key = fields[0]
4554 key = fields[0]
4501 value = b''
4555 value = b''
4502 else:
4556 else:
4503 key, value = fields
4557 key, value = fields
4504
4558
4505 if value.startswith(b'eval:'):
4559 if value.startswith(b'eval:'):
4506 value = stringutil.evalpythonliteral(value[5:])
4560 value = stringutil.evalpythonliteral(value[5:])
4507 else:
4561 else:
4508 value = stringutil.unescapestr(value)
4562 value = stringutil.unescapestr(value)
4509
4563
4510 args[key] = value
4564 args[key] = value
4511
4565
4512 if batchedcommands is not None:
4566 if batchedcommands is not None:
4513 batchedcommands.append((command, args))
4567 batchedcommands.append((command, args))
4514 continue
4568 continue
4515
4569
4516 ui.status(_(b'sending %s command\n') % command)
4570 ui.status(_(b'sending %s command\n') % command)
4517
4571
4518 if b'PUSHFILE' in args:
4572 if b'PUSHFILE' in args:
4519 with open(args[b'PUSHFILE'], 'rb') as fh:
4573 with open(args[b'PUSHFILE'], 'rb') as fh:
4520 del args[b'PUSHFILE']
4574 del args[b'PUSHFILE']
4521 res, output = peer._callpush(
4575 res, output = peer._callpush(
4522 command, fh, **pycompat.strkwargs(args)
4576 command, fh, **pycompat.strkwargs(args)
4523 )
4577 )
4524 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4578 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4525 ui.status(
4579 ui.status(
4526 _(b'remote output: %s\n') % stringutil.escapestr(output)
4580 _(b'remote output: %s\n') % stringutil.escapestr(output)
4527 )
4581 )
4528 else:
4582 else:
4529 with peer.commandexecutor() as e:
4583 with peer.commandexecutor() as e:
4530 res = e.callcommand(command, args).result()
4584 res = e.callcommand(command, args).result()
4531
4585
4532 if isinstance(res, wireprotov2peer.commandresponse):
4586 if isinstance(res, wireprotov2peer.commandresponse):
4533 val = res.objects()
4587 val = res.objects()
4534 ui.status(
4588 ui.status(
4535 _(b'response: %s\n')
4589 _(b'response: %s\n')
4536 % stringutil.pprint(val, bprefix=True, indent=2)
4590 % stringutil.pprint(val, bprefix=True, indent=2)
4537 )
4591 )
4538 else:
4592 else:
4539 ui.status(
4593 ui.status(
4540 _(b'response: %s\n')
4594 _(b'response: %s\n')
4541 % stringutil.pprint(res, bprefix=True, indent=2)
4595 % stringutil.pprint(res, bprefix=True, indent=2)
4542 )
4596 )
4543
4597
4544 elif action == b'batchbegin':
4598 elif action == b'batchbegin':
4545 if batchedcommands is not None:
4599 if batchedcommands is not None:
4546 raise error.Abort(_(b'nested batchbegin not allowed'))
4600 raise error.Abort(_(b'nested batchbegin not allowed'))
4547
4601
4548 batchedcommands = []
4602 batchedcommands = []
4549 elif action == b'batchsubmit':
4603 elif action == b'batchsubmit':
4550 # There is a batching API we could go through. But it would be
4604 # There is a batching API we could go through. But it would be
4551 # difficult to normalize requests into function calls. It is easier
4605 # difficult to normalize requests into function calls. It is easier
4552 # to bypass this layer and normalize to commands + args.
4606 # to bypass this layer and normalize to commands + args.
4553 ui.status(
4607 ui.status(
4554 _(b'sending batch with %d sub-commands\n')
4608 _(b'sending batch with %d sub-commands\n')
4555 % len(batchedcommands)
4609 % len(batchedcommands)
4556 )
4610 )
4557 assert peer is not None
4611 assert peer is not None
4558 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4612 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4559 ui.status(
4613 ui.status(
4560 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4614 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4561 )
4615 )
4562
4616
4563 batchedcommands = None
4617 batchedcommands = None
4564
4618
4565 elif action.startswith(b'httprequest '):
4619 elif action.startswith(b'httprequest '):
4566 if not opener:
4620 if not opener:
4567 raise error.Abort(
4621 raise error.Abort(
4568 _(b'cannot use httprequest without an HTTP peer')
4622 _(b'cannot use httprequest without an HTTP peer')
4569 )
4623 )
4570
4624
4571 request = action.split(b' ', 2)
4625 request = action.split(b' ', 2)
4572 if len(request) != 3:
4626 if len(request) != 3:
4573 raise error.Abort(
4627 raise error.Abort(
4574 _(
4628 _(
4575 b'invalid httprequest: expected format is '
4629 b'invalid httprequest: expected format is '
4576 b'"httprequest <method> <path>'
4630 b'"httprequest <method> <path>'
4577 )
4631 )
4578 )
4632 )
4579
4633
4580 method, httppath = request[1:]
4634 method, httppath = request[1:]
4581 headers = {}
4635 headers = {}
4582 body = None
4636 body = None
4583 frames = []
4637 frames = []
4584 for line in lines:
4638 for line in lines:
4585 line = line.lstrip()
4639 line = line.lstrip()
4586 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4640 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4587 if m:
4641 if m:
4588 # Headers need to use native strings.
4642 # Headers need to use native strings.
4589 key = pycompat.strurl(m.group(1))
4643 key = pycompat.strurl(m.group(1))
4590 value = pycompat.strurl(m.group(2))
4644 value = pycompat.strurl(m.group(2))
4591 headers[key] = value
4645 headers[key] = value
4592 continue
4646 continue
4593
4647
4594 if line.startswith(b'BODYFILE '):
4648 if line.startswith(b'BODYFILE '):
4595 with open(line.split(b' ', 1), b'rb') as fh:
4649 with open(line.split(b' ', 1), b'rb') as fh:
4596 body = fh.read()
4650 body = fh.read()
4597 elif line.startswith(b'frame '):
4651 elif line.startswith(b'frame '):
4598 frame = wireprotoframing.makeframefromhumanstring(
4652 frame = wireprotoframing.makeframefromhumanstring(
4599 line[len(b'frame ') :]
4653 line[len(b'frame ') :]
4600 )
4654 )
4601
4655
4602 frames.append(frame)
4656 frames.append(frame)
4603 else:
4657 else:
4604 raise error.Abort(
4658 raise error.Abort(
4605 _(b'unknown argument to httprequest: %s') % line
4659 _(b'unknown argument to httprequest: %s') % line
4606 )
4660 )
4607
4661
4608 url = path + httppath
4662 url = path + httppath
4609
4663
4610 if frames:
4664 if frames:
4611 body = b''.join(bytes(f) for f in frames)
4665 body = b''.join(bytes(f) for f in frames)
4612
4666
4613 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4667 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4614
4668
4615 # urllib.Request insists on using has_data() as a proxy for
4669 # urllib.Request insists on using has_data() as a proxy for
4616 # determining the request method. Override that to use our
4670 # determining the request method. Override that to use our
4617 # explicitly requested method.
4671 # explicitly requested method.
4618 req.get_method = lambda: pycompat.sysstr(method)
4672 req.get_method = lambda: pycompat.sysstr(method)
4619
4673
4620 try:
4674 try:
4621 res = opener.open(req)
4675 res = opener.open(req)
4622 body = res.read()
4676 body = res.read()
4623 except util.urlerr.urlerror as e:
4677 except util.urlerr.urlerror as e:
4624 # read() method must be called, but only exists in Python 2
4678 # read() method must be called, but only exists in Python 2
4625 getattr(e, 'read', lambda: None)()
4679 getattr(e, 'read', lambda: None)()
4626 continue
4680 continue
4627
4681
4628 ct = res.headers.get('Content-Type')
4682 ct = res.headers.get('Content-Type')
4629 if ct == 'application/mercurial-cbor':
4683 if ct == 'application/mercurial-cbor':
4630 ui.write(
4684 ui.write(
4631 _(b'cbor> %s\n')
4685 _(b'cbor> %s\n')
4632 % stringutil.pprint(
4686 % stringutil.pprint(
4633 cborutil.decodeall(body), bprefix=True, indent=2
4687 cborutil.decodeall(body), bprefix=True, indent=2
4634 )
4688 )
4635 )
4689 )
4636
4690
4637 elif action == b'close':
4691 elif action == b'close':
4638 assert peer is not None
4692 assert peer is not None
4639 peer.close()
4693 peer.close()
4640 elif action == b'readavailable':
4694 elif action == b'readavailable':
4641 if not stdout or not stderr:
4695 if not stdout or not stderr:
4642 raise error.Abort(
4696 raise error.Abort(
4643 _(b'readavailable not available on this peer')
4697 _(b'readavailable not available on this peer')
4644 )
4698 )
4645
4699
4646 stdin.close()
4700 stdin.close()
4647 stdout.read()
4701 stdout.read()
4648 stderr.read()
4702 stderr.read()
4649
4703
4650 elif action == b'readline':
4704 elif action == b'readline':
4651 if not stdout:
4705 if not stdout:
4652 raise error.Abort(_(b'readline not available on this peer'))
4706 raise error.Abort(_(b'readline not available on this peer'))
4653 stdout.readline()
4707 stdout.readline()
4654 elif action == b'ereadline':
4708 elif action == b'ereadline':
4655 if not stderr:
4709 if not stderr:
4656 raise error.Abort(_(b'ereadline not available on this peer'))
4710 raise error.Abort(_(b'ereadline not available on this peer'))
4657 stderr.readline()
4711 stderr.readline()
4658 elif action.startswith(b'read '):
4712 elif action.startswith(b'read '):
4659 count = int(action.split(b' ', 1)[1])
4713 count = int(action.split(b' ', 1)[1])
4660 if not stdout:
4714 if not stdout:
4661 raise error.Abort(_(b'read not available on this peer'))
4715 raise error.Abort(_(b'read not available on this peer'))
4662 stdout.read(count)
4716 stdout.read(count)
4663 elif action.startswith(b'eread '):
4717 elif action.startswith(b'eread '):
4664 count = int(action.split(b' ', 1)[1])
4718 count = int(action.split(b' ', 1)[1])
4665 if not stderr:
4719 if not stderr:
4666 raise error.Abort(_(b'eread not available on this peer'))
4720 raise error.Abort(_(b'eread not available on this peer'))
4667 stderr.read(count)
4721 stderr.read(count)
4668 else:
4722 else:
4669 raise error.Abort(_(b'unknown action: %s') % action)
4723 raise error.Abort(_(b'unknown action: %s') % action)
4670
4724
4671 if batchedcommands is not None:
4725 if batchedcommands is not None:
4672 raise error.Abort(_(b'unclosed "batchbegin" request'))
4726 raise error.Abort(_(b'unclosed "batchbegin" request'))
4673
4727
4674 if peer:
4728 if peer:
4675 peer.close()
4729 peer.close()
4676
4730
4677 if proc:
4731 if proc:
4678 proc.kill()
4732 proc.kill()
@@ -1,443 +1,443 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 abort
3 abort
4 add
4 add
5 addremove
5 addremove
6 annotate
6 annotate
7 archive
7 archive
8 backout
8 backout
9 bisect
9 bisect
10 bookmarks
10 bookmarks
11 branch
11 branch
12 branches
12 branches
13 bundle
13 bundle
14 cat
14 cat
15 clone
15 clone
16 commit
16 commit
17 config
17 config
18 continue
18 continue
19 copy
19 copy
20 diff
20 diff
21 export
21 export
22 files
22 files
23 forget
23 forget
24 graft
24 graft
25 grep
25 grep
26 heads
26 heads
27 help
27 help
28 identify
28 identify
29 import
29 import
30 incoming
30 incoming
31 init
31 init
32 locate
32 locate
33 log
33 log
34 manifest
34 manifest
35 merge
35 merge
36 outgoing
36 outgoing
37 parents
37 parents
38 paths
38 paths
39 phase
39 phase
40 pull
40 pull
41 purge
41 purge
42 push
42 push
43 recover
43 recover
44 remove
44 remove
45 rename
45 rename
46 resolve
46 resolve
47 revert
47 revert
48 rollback
48 rollback
49 root
49 root
50 serve
50 serve
51 shelve
51 shelve
52 status
52 status
53 summary
53 summary
54 tag
54 tag
55 tags
55 tags
56 tip
56 tip
57 unbundle
57 unbundle
58 unshelve
58 unshelve
59 update
59 update
60 verify
60 verify
61 version
61 version
62
62
63 Show all commands that start with "a"
63 Show all commands that start with "a"
64 $ hg debugcomplete a
64 $ hg debugcomplete a
65 abort
65 abort
66 add
66 add
67 addremove
67 addremove
68 annotate
68 annotate
69 archive
69 archive
70
70
71 Do not show debug commands if there are other candidates
71 Do not show debug commands if there are other candidates
72 $ hg debugcomplete d
72 $ hg debugcomplete d
73 diff
73 diff
74
74
75 Show debug commands if there are no other candidates
75 Show debug commands if there are no other candidates
76 $ hg debugcomplete debug
76 $ hg debugcomplete debug
77 debugancestor
77 debugancestor
78 debugantivirusrunning
78 debugantivirusrunning
79 debugapplystreamclonebundle
79 debugapplystreamclonebundle
80 debugbackupbundle
80 debugbackupbundle
81 debugbuilddag
81 debugbuilddag
82 debugbundle
82 debugbundle
83 debugcapabilities
83 debugcapabilities
84 debugchangedfiles
84 debugchangedfiles
85 debugcheckstate
85 debugcheckstate
86 debugcolor
86 debugcolor
87 debugcommands
87 debugcommands
88 debugcomplete
88 debugcomplete
89 debugconfig
89 debugconfig
90 debugcreatestreamclonebundle
90 debugcreatestreamclonebundle
91 debugdag
91 debugdag
92 debugdata
92 debugdata
93 debugdate
93 debugdate
94 debugdeltachain
94 debugdeltachain
95 debugdirstate
95 debugdirstate
96 debugdiscovery
96 debugdiscovery
97 debugdownload
97 debugdownload
98 debugextensions
98 debugextensions
99 debugfileset
99 debugfileset
100 debugformat
100 debugformat
101 debugfsinfo
101 debugfsinfo
102 debuggetbundle
102 debuggetbundle
103 debugignore
103 debugignore
104 debugindex
104 debugindex
105 debugindexdot
105 debugindexdot
106 debugindexstats
106 debugindexstats
107 debuginstall
107 debuginstall
108 debugknown
108 debugknown
109 debuglabelcomplete
109 debuglabelcomplete
110 debuglocks
110 debuglocks
111 debugmanifestfulltextcache
111 debugmanifestfulltextcache
112 debugmergestate
112 debugmergestate
113 debugnamecomplete
113 debugnamecomplete
114 debugnodemap
114 debugnodemap
115 debugobsolete
115 debugobsolete
116 debugp1copies
116 debugp1copies
117 debugp2copies
117 debugp2copies
118 debugpathcomplete
118 debugpathcomplete
119 debugpathcopies
119 debugpathcopies
120 debugpeer
120 debugpeer
121 debugpickmergetool
121 debugpickmergetool
122 debugpushkey
122 debugpushkey
123 debugpvec
123 debugpvec
124 debugrebuilddirstate
124 debugrebuilddirstate
125 debugrebuildfncache
125 debugrebuildfncache
126 debugrename
126 debugrename
127 debugrequires
127 debugrequires
128 debugrevlog
128 debugrevlog
129 debugrevlogindex
129 debugrevlogindex
130 debugrevspec
130 debugrevspec
131 debugserve
131 debugserve
132 debugsetparents
132 debugsetparents
133 debugshell
133 debugshell
134 debugsidedata
134 debugsidedata
135 debugssl
135 debugssl
136 debugstrip
136 debugstrip
137 debugsub
137 debugsub
138 debugsuccessorssets
138 debugsuccessorssets
139 debugtagscache
139 debugtagscache
140 debugtemplate
140 debugtemplate
141 debuguigetpass
141 debuguigetpass
142 debuguiprompt
142 debuguiprompt
143 debugupdatecaches
143 debugupdatecaches
144 debugupgraderepo
144 debugupgraderepo
145 debugwalk
145 debugwalk
146 debugwhyunstable
146 debugwhyunstable
147 debugwireargs
147 debugwireargs
148 debugwireproto
148 debugwireproto
149
149
150 Do not show the alias of a debug command if there are other candidates
150 Do not show the alias of a debug command if there are other candidates
151 (this should hide rawcommit)
151 (this should hide rawcommit)
152 $ hg debugcomplete r
152 $ hg debugcomplete r
153 recover
153 recover
154 remove
154 remove
155 rename
155 rename
156 resolve
156 resolve
157 revert
157 revert
158 rollback
158 rollback
159 root
159 root
160 Show the alias of a debug command if there are no other candidates
160 Show the alias of a debug command if there are no other candidates
161 $ hg debugcomplete rawc
161 $ hg debugcomplete rawc
162
162
163
163
164 Show the global options
164 Show the global options
165 $ hg debugcomplete --options | sort
165 $ hg debugcomplete --options | sort
166 --color
166 --color
167 --config
167 --config
168 --cwd
168 --cwd
169 --debug
169 --debug
170 --debugger
170 --debugger
171 --encoding
171 --encoding
172 --encodingmode
172 --encodingmode
173 --help
173 --help
174 --hidden
174 --hidden
175 --noninteractive
175 --noninteractive
176 --pager
176 --pager
177 --profile
177 --profile
178 --quiet
178 --quiet
179 --repository
179 --repository
180 --time
180 --time
181 --traceback
181 --traceback
182 --verbose
182 --verbose
183 --version
183 --version
184 -R
184 -R
185 -h
185 -h
186 -q
186 -q
187 -v
187 -v
188 -y
188 -y
189
189
190 Show the options for the "serve" command
190 Show the options for the "serve" command
191 $ hg debugcomplete --options serve | sort
191 $ hg debugcomplete --options serve | sort
192 --accesslog
192 --accesslog
193 --address
193 --address
194 --certificate
194 --certificate
195 --cmdserver
195 --cmdserver
196 --color
196 --color
197 --config
197 --config
198 --cwd
198 --cwd
199 --daemon
199 --daemon
200 --daemon-postexec
200 --daemon-postexec
201 --debug
201 --debug
202 --debugger
202 --debugger
203 --encoding
203 --encoding
204 --encodingmode
204 --encodingmode
205 --errorlog
205 --errorlog
206 --help
206 --help
207 --hidden
207 --hidden
208 --ipv6
208 --ipv6
209 --name
209 --name
210 --noninteractive
210 --noninteractive
211 --pager
211 --pager
212 --pid-file
212 --pid-file
213 --port
213 --port
214 --prefix
214 --prefix
215 --print-url
215 --print-url
216 --profile
216 --profile
217 --quiet
217 --quiet
218 --repository
218 --repository
219 --stdio
219 --stdio
220 --style
220 --style
221 --subrepos
221 --subrepos
222 --templates
222 --templates
223 --time
223 --time
224 --traceback
224 --traceback
225 --verbose
225 --verbose
226 --version
226 --version
227 --web-conf
227 --web-conf
228 -6
228 -6
229 -A
229 -A
230 -E
230 -E
231 -R
231 -R
232 -S
232 -S
233 -a
233 -a
234 -d
234 -d
235 -h
235 -h
236 -n
236 -n
237 -p
237 -p
238 -q
238 -q
239 -t
239 -t
240 -v
240 -v
241 -y
241 -y
242
242
243 Show an error if we use --options with an ambiguous abbreviation
243 Show an error if we use --options with an ambiguous abbreviation
244 $ hg debugcomplete --options s
244 $ hg debugcomplete --options s
245 hg: command 's' is ambiguous:
245 hg: command 's' is ambiguous:
246 serve shelve showconfig status summary
246 serve shelve showconfig status summary
247 [10]
247 [10]
248
248
249 Show all commands + options
249 Show all commands + options
250 $ hg debugcommands
250 $ hg debugcommands
251 abort: dry-run
251 abort: dry-run
252 add: include, exclude, subrepos, dry-run
252 add: include, exclude, subrepos, dry-run
253 addremove: similarity, subrepos, include, exclude, dry-run
253 addremove: similarity, subrepos, include, exclude, dry-run
254 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
254 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
255 archive: no-decode, prefix, rev, type, subrepos, include, exclude
255 archive: no-decode, prefix, rev, type, subrepos, include, exclude
256 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
256 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
257 bisect: reset, good, bad, skip, extend, command, noupdate
257 bisect: reset, good, bad, skip, extend, command, noupdate
258 bookmarks: force, rev, delete, rename, inactive, list, template
258 bookmarks: force, rev, delete, rename, inactive, list, template
259 branch: force, clean, rev
259 branch: force, clean, rev
260 branches: active, closed, rev, template
260 branches: active, closed, rev, template
261 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
261 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
262 cat: output, rev, decode, include, exclude, template
262 cat: output, rev, decode, include, exclude, template
263 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
263 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
264 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
264 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
265 config: untrusted, edit, local, shared, non-shared, global, template
265 config: untrusted, edit, local, shared, non-shared, global, template
266 continue: dry-run
266 continue: dry-run
267 copy: forget, after, at-rev, force, include, exclude, dry-run
267 copy: forget, after, at-rev, force, include, exclude, dry-run
268 debugancestor:
268 debugancestor:
269 debugantivirusrunning:
269 debugantivirusrunning:
270 debugapplystreamclonebundle:
270 debugapplystreamclonebundle:
271 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
271 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
272 debugbuilddag: mergeable-file, overwritten-file, new-file
272 debugbuilddag: mergeable-file, overwritten-file, new-file
273 debugbundle: all, part-type, spec
273 debugbundle: all, part-type, spec
274 debugcapabilities:
274 debugcapabilities:
275 debugchangedfiles:
275 debugchangedfiles:
276 debugcheckstate:
276 debugcheckstate:
277 debugcolor: style
277 debugcolor: style
278 debugcommands:
278 debugcommands:
279 debugcomplete: options
279 debugcomplete: options
280 debugcreatestreamclonebundle:
280 debugcreatestreamclonebundle:
281 debugdag: tags, branches, dots, spaces
281 debugdag: tags, branches, dots, spaces
282 debugdata: changelog, manifest, dir
282 debugdata: changelog, manifest, dir
283 debugdate: extended
283 debugdate: extended
284 debugdeltachain: changelog, manifest, dir, template
284 debugdeltachain: changelog, manifest, dir, template
285 debugdirstate: nodates, dates, datesort
285 debugdirstate: nodates, dates, datesort
286 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
286 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure
287 debugdownload: output
287 debugdownload: output
288 debugextensions: template
288 debugextensions: template
289 debugfileset: rev, all-files, show-matcher, show-stage
289 debugfileset: rev, all-files, show-matcher, show-stage
290 debugformat: template
290 debugformat: template
291 debugfsinfo:
291 debugfsinfo:
292 debuggetbundle: head, common, type
292 debuggetbundle: head, common, type
293 debugignore:
293 debugignore:
294 debugindex: changelog, manifest, dir, template
294 debugindex: changelog, manifest, dir, template
295 debugindexdot: changelog, manifest, dir
295 debugindexdot: changelog, manifest, dir
296 debugindexstats:
296 debugindexstats:
297 debuginstall: template
297 debuginstall: template
298 debugknown:
298 debugknown:
299 debuglabelcomplete:
299 debuglabelcomplete:
300 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
300 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
301 debugmanifestfulltextcache: clear, add
301 debugmanifestfulltextcache: clear, add
302 debugmergestate: style, template
302 debugmergestate: style, template
303 debugnamecomplete:
303 debugnamecomplete:
304 debugnodemap: dump-new, dump-disk, check, metadata
304 debugnodemap: dump-new, dump-disk, check, metadata
305 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
305 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
306 debugp1copies: rev
306 debugp1copies: rev
307 debugp2copies: rev
307 debugp2copies: rev
308 debugpathcomplete: full, normal, added, removed
308 debugpathcomplete: full, normal, added, removed
309 debugpathcopies: include, exclude
309 debugpathcopies: include, exclude
310 debugpeer:
310 debugpeer:
311 debugpickmergetool: rev, changedelete, include, exclude, tool
311 debugpickmergetool: rev, changedelete, include, exclude, tool
312 debugpushkey:
312 debugpushkey:
313 debugpvec:
313 debugpvec:
314 debugrebuilddirstate: rev, minimal
314 debugrebuilddirstate: rev, minimal
315 debugrebuildfncache:
315 debugrebuildfncache:
316 debugrename: rev
316 debugrename: rev
317 debugrequires:
317 debugrequires:
318 debugrevlog: changelog, manifest, dir, dump
318 debugrevlog: changelog, manifest, dir, dump
319 debugrevlogindex: changelog, manifest, dir, format
319 debugrevlogindex: changelog, manifest, dir, format
320 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
320 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
321 debugserve: sshstdio, logiofd, logiofile
321 debugserve: sshstdio, logiofd, logiofile
322 debugsetparents:
322 debugsetparents:
323 debugshell:
323 debugshell:
324 debugsidedata: changelog, manifest, dir
324 debugsidedata: changelog, manifest, dir
325 debugssl:
325 debugssl:
326 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
326 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
327 debugsub: rev
327 debugsub: rev
328 debugsuccessorssets: closest
328 debugsuccessorssets: closest
329 debugtagscache:
329 debugtagscache:
330 debugtemplate: rev, define
330 debugtemplate: rev, define
331 debuguigetpass: prompt
331 debuguigetpass: prompt
332 debuguiprompt: prompt
332 debuguiprompt: prompt
333 debugupdatecaches:
333 debugupdatecaches:
334 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
334 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
335 debugwalk: include, exclude
335 debugwalk: include, exclude
336 debugwhyunstable:
336 debugwhyunstable:
337 debugwireargs: three, four, five, ssh, remotecmd, insecure
337 debugwireargs: three, four, five, ssh, remotecmd, insecure
338 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
338 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
339 diff: rev, from, to, change, merge, 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
339 diff: rev, from, to, change, merge, 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
340 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
340 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
341 files: rev, print0, include, exclude, template, subrepos
341 files: rev, print0, include, exclude, template, subrepos
342 forget: interactive, include, exclude, dry-run
342 forget: interactive, include, exclude, dry-run
343 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
343 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
344 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
344 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
345 heads: rev, topo, active, closed, style, template
345 heads: rev, topo, active, closed, style, template
346 help: extension, command, keyword, system
346 help: extension, command, keyword, system
347 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
347 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
348 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
348 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
349 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
349 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
350 init: ssh, remotecmd, insecure
350 init: ssh, remotecmd, insecure
351 locate: rev, print0, fullpath, include, exclude
351 locate: rev, print0, fullpath, include, exclude
352 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
352 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
353 manifest: rev, all, template
353 manifest: rev, all, template
354 merge: force, rev, preview, abort, tool
354 merge: force, rev, preview, abort, tool
355 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
355 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
356 parents: rev, style, template
356 parents: rev, style, template
357 paths: template
357 paths: template
358 phase: public, draft, secret, force, rev
358 phase: public, draft, secret, force, rev
359 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
359 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
360 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
360 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
361 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
361 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
362 recover: verify
362 recover: verify
363 remove: after, force, subrepos, include, exclude, dry-run
363 remove: after, force, subrepos, include, exclude, dry-run
364 rename: after, at-rev, force, include, exclude, dry-run
364 rename: after, at-rev, force, include, exclude, dry-run
365 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
365 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
366 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
366 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
367 rollback: dry-run, force
367 rollback: dry-run, force
368 root: template
368 root: template
369 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
369 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
370 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
370 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
371 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
371 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
372 summary: remote
372 summary: remote
373 tag: force, local, rev, remove, edit, message, date, user
373 tag: force, local, rev, remove, edit, message, date, user
374 tags: template
374 tags: template
375 tip: patch, git, style, template
375 tip: patch, git, style, template
376 unbundle: update
376 unbundle: update
377 unshelve: abort, continue, interactive, keep, name, tool, date
377 unshelve: abort, continue, interactive, keep, name, tool, date
378 update: clean, check, merge, date, rev, tool
378 update: clean, check, merge, date, rev, tool
379 verify: full
379 verify: full
380 version: template
380 version: template
381
381
382 $ hg init a
382 $ hg init a
383 $ cd a
383 $ cd a
384 $ echo fee > fee
384 $ echo fee > fee
385 $ hg ci -q -Amfee
385 $ hg ci -q -Amfee
386 $ hg tag fee
386 $ hg tag fee
387 $ mkdir fie
387 $ mkdir fie
388 $ echo dead > fie/dead
388 $ echo dead > fie/dead
389 $ echo live > fie/live
389 $ echo live > fie/live
390 $ hg bookmark fo
390 $ hg bookmark fo
391 $ hg branch -q fie
391 $ hg branch -q fie
392 $ hg ci -q -Amfie
392 $ hg ci -q -Amfie
393 $ echo fo > fo
393 $ echo fo > fo
394 $ hg branch -qf default
394 $ hg branch -qf default
395 $ hg ci -q -Amfo
395 $ hg ci -q -Amfo
396 $ echo Fum > Fum
396 $ echo Fum > Fum
397 $ hg ci -q -AmFum
397 $ hg ci -q -AmFum
398 $ hg bookmark Fum
398 $ hg bookmark Fum
399
399
400 Test debugpathcomplete
400 Test debugpathcomplete
401
401
402 $ hg debugpathcomplete f
402 $ hg debugpathcomplete f
403 fee
403 fee
404 fie
404 fie
405 fo
405 fo
406 $ hg debugpathcomplete -f f
406 $ hg debugpathcomplete -f f
407 fee
407 fee
408 fie/dead
408 fie/dead
409 fie/live
409 fie/live
410 fo
410 fo
411
411
412 $ hg rm Fum
412 $ hg rm Fum
413 $ hg debugpathcomplete -r F
413 $ hg debugpathcomplete -r F
414 Fum
414 Fum
415
415
416 Test debugnamecomplete
416 Test debugnamecomplete
417
417
418 $ hg debugnamecomplete
418 $ hg debugnamecomplete
419 Fum
419 Fum
420 default
420 default
421 fee
421 fee
422 fie
422 fie
423 fo
423 fo
424 tip
424 tip
425 $ hg debugnamecomplete f
425 $ hg debugnamecomplete f
426 fee
426 fee
427 fie
427 fie
428 fo
428 fo
429
429
430 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
430 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
431 used for completions in some shells.
431 used for completions in some shells.
432
432
433 $ hg debuglabelcomplete
433 $ hg debuglabelcomplete
434 Fum
434 Fum
435 default
435 default
436 fee
436 fee
437 fie
437 fie
438 fo
438 fo
439 tip
439 tip
440 $ hg debuglabelcomplete f
440 $ hg debuglabelcomplete f
441 fee
441 fee
442 fie
442 fie
443 fo
443 fo
@@ -1,1590 +1,1726 b''
1
1
2 Function to test discovery between two repos in both directions, using both the local shortcut
2 Function to test discovery between two repos in both directions, using both the local shortcut
3 (which is currently not activated by default) and the full remotable protocol:
3 (which is currently not activated by default) and the full remotable protocol:
4
4
5 $ testdesc() { # revs_a, revs_b, dagdesc
5 $ testdesc() { # revs_a, revs_b, dagdesc
6 > if [ -d foo ]; then rm -rf foo; fi
6 > if [ -d foo ]; then rm -rf foo; fi
7 > hg init foo
7 > hg init foo
8 > cd foo
8 > cd foo
9 > hg debugbuilddag "$3"
9 > hg debugbuilddag "$3"
10 > hg clone . a $1 --quiet
10 > hg clone . a $1 --quiet
11 > hg clone . b $2 --quiet
11 > hg clone . b $2 --quiet
12 > echo
12 > echo
13 > echo "% -- a -> b tree"
13 > echo "% -- a -> b tree"
14 > hg -R a debugdiscovery b --verbose --old
14 > hg -R a debugdiscovery b --verbose --old
15 > echo
15 > echo
16 > echo "% -- a -> b set"
16 > echo "% -- a -> b set"
17 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true
17 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true
18 > echo
18 > echo
19 > echo "% -- a -> b set (tip only)"
19 > echo "% -- a -> b set (tip only)"
20 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true --rev tip
20 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true --rev tip
21 > echo
21 > echo
22 > echo "% -- b -> a tree"
22 > echo "% -- b -> a tree"
23 > hg -R b debugdiscovery a --verbose --old
23 > hg -R b debugdiscovery a --verbose --old
24 > echo
24 > echo
25 > echo "% -- b -> a set"
25 > echo "% -- b -> a set"
26 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true
26 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true
27 > echo
27 > echo
28 > echo "% -- b -> a set (tip only)"
28 > echo "% -- b -> a set (tip only)"
29 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true --rev tip
29 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true --rev tip
30 > cd ..
30 > cd ..
31 > }
31 > }
32
32
33
33
34 Small superset:
34 Small superset:
35
35
36 $ testdesc '-ra1 -ra2' '-rb1 -rb2 -rb3' '
36 $ testdesc '-ra1 -ra2' '-rb1 -rb2 -rb3' '
37 > +2:f +1:a1:b1
37 > +2:f +1:a1:b1
38 > <f +4 :a2
38 > <f +4 :a2
39 > +5 :b2
39 > +5 :b2
40 > <f +3 :b3'
40 > <f +3 :b3'
41
41
42 % -- a -> b tree
42 % -- a -> b tree
43 comparing with b
43 comparing with b
44 searching for changes
44 searching for changes
45 unpruned common: 01241442b3c2 66f7d451a68b b5714e113bc0
45 unpruned common: 01241442b3c2 66f7d451a68b b5714e113bc0
46 elapsed time: * seconds (glob)
46 elapsed time: * seconds (glob)
47 round-trips: 2
47 round-trips: 2
48 heads summary:
48 heads summary:
49 total common heads: 2
49 total common heads: 2
50 also local heads: 2
50 also local heads: 2
51 also remote heads: 1
51 also remote heads: 1
52 both: 1
52 both: 1
53 local heads: 2
53 local heads: 2
54 common: 2
54 common: 2
55 missing: 0
55 missing: 0
56 remote heads: 3
56 remote heads: 3
57 common: 1
57 common: 1
58 unknown: 2
58 unknown: 2
59 local changesets: 7
59 local changesets: 7
60 common: 7
60 common: 7
61 heads: 2
61 heads: 2
62 roots: 1
62 roots: 1
63 missing: 0
63 missing: 0
64 heads: 0
64 heads: 0
65 roots: 0
65 roots: 0
66 first undecided set: 3
66 first undecided set: 3
67 heads: 1
67 heads: 1
68 roots: 1
68 roots: 1
69 common: 3
69 common: 3
70 missing: 0
70 missing: 0
71 common heads: 01241442b3c2 b5714e113bc0
71 common heads: 01241442b3c2 b5714e113bc0
72
72
73 % -- a -> b set
73 % -- a -> b set
74 comparing with b
74 comparing with b
75 query 1; heads
75 query 1; heads
76 searching for changes
76 searching for changes
77 all local changesets known remotely
77 all local changesets known remotely
78 elapsed time: * seconds (glob)
78 elapsed time: * seconds (glob)
79 round-trips: 1
79 round-trips: 1
80 heads summary:
80 heads summary:
81 total common heads: 2
81 total common heads: 2
82 also local heads: 2
82 also local heads: 2
83 also remote heads: 1
83 also remote heads: 1
84 both: 1
84 both: 1
85 local heads: 2
85 local heads: 2
86 common: 2
86 common: 2
87 missing: 0
87 missing: 0
88 remote heads: 3
88 remote heads: 3
89 common: 1
89 common: 1
90 unknown: 2
90 unknown: 2
91 local changesets: 7
91 local changesets: 7
92 common: 7
92 common: 7
93 heads: 2
93 heads: 2
94 roots: 1
94 roots: 1
95 missing: 0
95 missing: 0
96 heads: 0
96 heads: 0
97 roots: 0
97 roots: 0
98 first undecided set: 3
98 first undecided set: 3
99 heads: 1
99 heads: 1
100 roots: 1
100 roots: 1
101 common: 3
101 common: 3
102 missing: 0
102 missing: 0
103 common heads: 01241442b3c2 b5714e113bc0
103 common heads: 01241442b3c2 b5714e113bc0
104
104
105 % -- a -> b set (tip only)
105 % -- a -> b set (tip only)
106 comparing with b
106 comparing with b
107 query 1; heads
107 query 1; heads
108 searching for changes
108 searching for changes
109 all local changesets known remotely
109 all local changesets known remotely
110 elapsed time: * seconds (glob)
110 elapsed time: * seconds (glob)
111 round-trips: 1
111 round-trips: 1
112 heads summary:
112 heads summary:
113 total common heads: 1
113 total common heads: 1
114 also local heads: 1
114 also local heads: 1
115 also remote heads: 0
115 also remote heads: 0
116 both: 0
116 both: 0
117 local heads: 2
117 local heads: 2
118 common: 1
118 common: 1
119 missing: 1
119 missing: 1
120 remote heads: 3
120 remote heads: 3
121 common: 0
121 common: 0
122 unknown: 3
122 unknown: 3
123 local changesets: 7
123 local changesets: 7
124 common: 6
124 common: 6
125 heads: 1
125 heads: 1
126 roots: 1
126 roots: 1
127 missing: 1
127 missing: 1
128 heads: 1
128 heads: 1
129 roots: 1
129 roots: 1
130 first undecided set: 6
130 first undecided set: 6
131 heads: 2
131 heads: 2
132 roots: 1
132 roots: 1
133 common: 5
133 common: 5
134 missing: 1
134 missing: 1
135 common heads: b5714e113bc0
135 common heads: b5714e113bc0
136
136
137 % -- b -> a tree
137 % -- b -> a tree
138 comparing with a
138 comparing with a
139 searching for changes
139 searching for changes
140 unpruned common: 01241442b3c2 b5714e113bc0
140 unpruned common: 01241442b3c2 b5714e113bc0
141 elapsed time: * seconds (glob)
141 elapsed time: * seconds (glob)
142 round-trips: 1
142 round-trips: 1
143 heads summary:
143 heads summary:
144 total common heads: 2
144 total common heads: 2
145 also local heads: 1
145 also local heads: 1
146 also remote heads: 2
146 also remote heads: 2
147 both: 1
147 both: 1
148 local heads: 3
148 local heads: 3
149 common: 1
149 common: 1
150 missing: 2
150 missing: 2
151 remote heads: 2
151 remote heads: 2
152 common: 2
152 common: 2
153 unknown: 0
153 unknown: 0
154 local changesets: 15
154 local changesets: 15
155 common: 7
155 common: 7
156 heads: 2
156 heads: 2
157 roots: 1
157 roots: 1
158 missing: 8
158 missing: 8
159 heads: 2
159 heads: 2
160 roots: 2
160 roots: 2
161 first undecided set: 8
161 first undecided set: 8
162 heads: 2
162 heads: 2
163 roots: 2
163 roots: 2
164 common: 0
164 common: 0
165 missing: 8
165 missing: 8
166 common heads: 01241442b3c2 b5714e113bc0
166 common heads: 01241442b3c2 b5714e113bc0
167
167
168 % -- b -> a set
168 % -- b -> a set
169 comparing with a
169 comparing with a
170 query 1; heads
170 query 1; heads
171 searching for changes
171 searching for changes
172 all remote heads known locally
172 all remote heads known locally
173 elapsed time: * seconds (glob)
173 elapsed time: * seconds (glob)
174 round-trips: 1
174 round-trips: 1
175 heads summary:
175 heads summary:
176 total common heads: 2
176 total common heads: 2
177 also local heads: 1
177 also local heads: 1
178 also remote heads: 2
178 also remote heads: 2
179 both: 1
179 both: 1
180 local heads: 3
180 local heads: 3
181 common: 1
181 common: 1
182 missing: 2
182 missing: 2
183 remote heads: 2
183 remote heads: 2
184 common: 2
184 common: 2
185 unknown: 0
185 unknown: 0
186 local changesets: 15
186 local changesets: 15
187 common: 7
187 common: 7
188 heads: 2
188 heads: 2
189 roots: 1
189 roots: 1
190 missing: 8
190 missing: 8
191 heads: 2
191 heads: 2
192 roots: 2
192 roots: 2
193 first undecided set: 8
193 first undecided set: 8
194 heads: 2
194 heads: 2
195 roots: 2
195 roots: 2
196 common: 0
196 common: 0
197 missing: 8
197 missing: 8
198 common heads: 01241442b3c2 b5714e113bc0
198 common heads: 01241442b3c2 b5714e113bc0
199
199
200 % -- b -> a set (tip only)
200 % -- b -> a set (tip only)
201 comparing with a
201 comparing with a
202 query 1; heads
202 query 1; heads
203 searching for changes
203 searching for changes
204 all remote heads known locally
204 all remote heads known locally
205 elapsed time: * seconds (glob)
205 elapsed time: * seconds (glob)
206 round-trips: 1
206 round-trips: 1
207 heads summary:
207 heads summary:
208 total common heads: 2
208 total common heads: 2
209 also local heads: 1
209 also local heads: 1
210 also remote heads: 2
210 also remote heads: 2
211 both: 1
211 both: 1
212 local heads: 3
212 local heads: 3
213 common: 1
213 common: 1
214 missing: 2
214 missing: 2
215 remote heads: 2
215 remote heads: 2
216 common: 2
216 common: 2
217 unknown: 0
217 unknown: 0
218 local changesets: 15
218 local changesets: 15
219 common: 7
219 common: 7
220 heads: 2
220 heads: 2
221 roots: 1
221 roots: 1
222 missing: 8
222 missing: 8
223 heads: 2
223 heads: 2
224 roots: 2
224 roots: 2
225 first undecided set: 8
225 first undecided set: 8
226 heads: 2
226 heads: 2
227 roots: 2
227 roots: 2
228 common: 0
228 common: 0
229 missing: 8
229 missing: 8
230 common heads: 01241442b3c2 b5714e113bc0
230 common heads: 01241442b3c2 b5714e113bc0
231
231
232
232
233 Many new:
233 Many new:
234
234
235 $ testdesc '-ra1 -ra2' '-rb' '
235 $ testdesc '-ra1 -ra2' '-rb' '
236 > +2:f +3:a1 +3:b
236 > +2:f +3:a1 +3:b
237 > <f +30 :a2'
237 > <f +30 :a2'
238
238
239 % -- a -> b tree
239 % -- a -> b tree
240 comparing with b
240 comparing with b
241 searching for changes
241 searching for changes
242 unpruned common: bebd167eb94d
242 unpruned common: bebd167eb94d
243 elapsed time: * seconds (glob)
243 elapsed time: * seconds (glob)
244 round-trips: 2
244 round-trips: 2
245 heads summary:
245 heads summary:
246 total common heads: 1
246 total common heads: 1
247 also local heads: 1
247 also local heads: 1
248 also remote heads: 0
248 also remote heads: 0
249 both: 0
249 both: 0
250 local heads: 2
250 local heads: 2
251 common: 1
251 common: 1
252 missing: 1
252 missing: 1
253 remote heads: 1
253 remote heads: 1
254 common: 0
254 common: 0
255 unknown: 1
255 unknown: 1
256 local changesets: 35
256 local changesets: 35
257 common: 5
257 common: 5
258 heads: 1
258 heads: 1
259 roots: 1
259 roots: 1
260 missing: 30
260 missing: 30
261 heads: 1
261 heads: 1
262 roots: 1
262 roots: 1
263 first undecided set: 34
263 first undecided set: 34
264 heads: 2
264 heads: 2
265 roots: 1
265 roots: 1
266 common: 4
266 common: 4
267 missing: 30
267 missing: 30
268 common heads: bebd167eb94d
268 common heads: bebd167eb94d
269
269
270 % -- a -> b set
270 % -- a -> b set
271 comparing with b
271 comparing with b
272 query 1; heads
272 query 1; heads
273 searching for changes
273 searching for changes
274 taking initial sample
274 taking initial sample
275 searching: 2 queries
275 searching: 2 queries
276 query 2; still undecided: 29, sample size is: 29
276 query 2; still undecided: 29, sample size is: 29
277 2 total queries in *.????s (glob)
277 2 total queries in *.????s (glob)
278 elapsed time: * seconds (glob)
278 elapsed time: * seconds (glob)
279 round-trips: 2
279 round-trips: 2
280 heads summary:
280 heads summary:
281 total common heads: 1
281 total common heads: 1
282 also local heads: 1
282 also local heads: 1
283 also remote heads: 0
283 also remote heads: 0
284 both: 0
284 both: 0
285 local heads: 2
285 local heads: 2
286 common: 1
286 common: 1
287 missing: 1
287 missing: 1
288 remote heads: 1
288 remote heads: 1
289 common: 0
289 common: 0
290 unknown: 1
290 unknown: 1
291 local changesets: 35
291 local changesets: 35
292 common: 5
292 common: 5
293 heads: 1
293 heads: 1
294 roots: 1
294 roots: 1
295 missing: 30
295 missing: 30
296 heads: 1
296 heads: 1
297 roots: 1
297 roots: 1
298 first undecided set: 34
298 first undecided set: 34
299 heads: 2
299 heads: 2
300 roots: 1
300 roots: 1
301 common: 4
301 common: 4
302 missing: 30
302 missing: 30
303 common heads: bebd167eb94d
303 common heads: bebd167eb94d
304
304
305 % -- a -> b set (tip only)
305 % -- a -> b set (tip only)
306 comparing with b
306 comparing with b
307 query 1; heads
307 query 1; heads
308 searching for changes
308 searching for changes
309 taking quick initial sample
309 taking quick initial sample
310 searching: 2 queries
310 searching: 2 queries
311 query 2; still undecided: 31, sample size is: 31
311 query 2; still undecided: 31, sample size is: 31
312 2 total queries in *.????s (glob)
312 2 total queries in *.????s (glob)
313 elapsed time: * seconds (glob)
313 elapsed time: * seconds (glob)
314 round-trips: 2
314 round-trips: 2
315 heads summary:
315 heads summary:
316 total common heads: 1
316 total common heads: 1
317 also local heads: 0
317 also local heads: 0
318 also remote heads: 0
318 also remote heads: 0
319 both: 0
319 both: 0
320 local heads: 2
320 local heads: 2
321 common: 0
321 common: 0
322 missing: 2
322 missing: 2
323 remote heads: 1
323 remote heads: 1
324 common: 0
324 common: 0
325 unknown: 1
325 unknown: 1
326 local changesets: 35
326 local changesets: 35
327 common: 2
327 common: 2
328 heads: 1
328 heads: 1
329 roots: 1
329 roots: 1
330 missing: 33
330 missing: 33
331 heads: 2
331 heads: 2
332 roots: 2
332 roots: 2
333 first undecided set: 35
333 first undecided set: 35
334 heads: 2
334 heads: 2
335 roots: 1
335 roots: 1
336 common: 2
336 common: 2
337 missing: 33
337 missing: 33
338 common heads: 66f7d451a68b
338 common heads: 66f7d451a68b
339
339
340 % -- b -> a tree
340 % -- b -> a tree
341 comparing with a
341 comparing with a
342 searching for changes
342 searching for changes
343 unpruned common: 66f7d451a68b bebd167eb94d
343 unpruned common: 66f7d451a68b bebd167eb94d
344 elapsed time: * seconds (glob)
344 elapsed time: * seconds (glob)
345 round-trips: 4
345 round-trips: 4
346 heads summary:
346 heads summary:
347 total common heads: 1
347 total common heads: 1
348 also local heads: 0
348 also local heads: 0
349 also remote heads: 1
349 also remote heads: 1
350 both: 0
350 both: 0
351 local heads: 1
351 local heads: 1
352 common: 0
352 common: 0
353 missing: 1
353 missing: 1
354 remote heads: 2
354 remote heads: 2
355 common: 1
355 common: 1
356 unknown: 1
356 unknown: 1
357 local changesets: 8
357 local changesets: 8
358 common: 5
358 common: 5
359 heads: 1
359 heads: 1
360 roots: 1
360 roots: 1
361 missing: 3
361 missing: 3
362 heads: 1
362 heads: 1
363 roots: 1
363 roots: 1
364 first undecided set: 3
364 first undecided set: 3
365 heads: 1
365 heads: 1
366 roots: 1
366 roots: 1
367 common: 0
367 common: 0
368 missing: 3
368 missing: 3
369 common heads: bebd167eb94d
369 common heads: bebd167eb94d
370
370
371 % -- b -> a set
371 % -- b -> a set
372 comparing with a
372 comparing with a
373 query 1; heads
373 query 1; heads
374 searching for changes
374 searching for changes
375 taking initial sample
375 taking initial sample
376 searching: 2 queries
376 searching: 2 queries
377 query 2; still undecided: 2, sample size is: 2
377 query 2; still undecided: 2, sample size is: 2
378 2 total queries in *.????s (glob)
378 2 total queries in *.????s (glob)
379 elapsed time: * seconds (glob)
379 elapsed time: * seconds (glob)
380 round-trips: 2
380 round-trips: 2
381 heads summary:
381 heads summary:
382 total common heads: 1
382 total common heads: 1
383 also local heads: 0
383 also local heads: 0
384 also remote heads: 1
384 also remote heads: 1
385 both: 0
385 both: 0
386 local heads: 1
386 local heads: 1
387 common: 0
387 common: 0
388 missing: 1
388 missing: 1
389 remote heads: 2
389 remote heads: 2
390 common: 1
390 common: 1
391 unknown: 1
391 unknown: 1
392 local changesets: 8
392 local changesets: 8
393 common: 5
393 common: 5
394 heads: 1
394 heads: 1
395 roots: 1
395 roots: 1
396 missing: 3
396 missing: 3
397 heads: 1
397 heads: 1
398 roots: 1
398 roots: 1
399 first undecided set: 3
399 first undecided set: 3
400 heads: 1
400 heads: 1
401 roots: 1
401 roots: 1
402 common: 0
402 common: 0
403 missing: 3
403 missing: 3
404 common heads: bebd167eb94d
404 common heads: bebd167eb94d
405
405
406 % -- b -> a set (tip only)
406 % -- b -> a set (tip only)
407 comparing with a
407 comparing with a
408 query 1; heads
408 query 1; heads
409 searching for changes
409 searching for changes
410 taking initial sample
410 taking initial sample
411 searching: 2 queries
411 searching: 2 queries
412 query 2; still undecided: 2, sample size is: 2
412 query 2; still undecided: 2, sample size is: 2
413 2 total queries in *.????s (glob)
413 2 total queries in *.????s (glob)
414 elapsed time: * seconds (glob)
414 elapsed time: * seconds (glob)
415 round-trips: 2
415 round-trips: 2
416 heads summary:
416 heads summary:
417 total common heads: 1
417 total common heads: 1
418 also local heads: 0
418 also local heads: 0
419 also remote heads: 1
419 also remote heads: 1
420 both: 0
420 both: 0
421 local heads: 1
421 local heads: 1
422 common: 0
422 common: 0
423 missing: 1
423 missing: 1
424 remote heads: 2
424 remote heads: 2
425 common: 1
425 common: 1
426 unknown: 1
426 unknown: 1
427 local changesets: 8
427 local changesets: 8
428 common: 5
428 common: 5
429 heads: 1
429 heads: 1
430 roots: 1
430 roots: 1
431 missing: 3
431 missing: 3
432 heads: 1
432 heads: 1
433 roots: 1
433 roots: 1
434 first undecided set: 3
434 first undecided set: 3
435 heads: 1
435 heads: 1
436 roots: 1
436 roots: 1
437 common: 0
437 common: 0
438 missing: 3
438 missing: 3
439 common heads: bebd167eb94d
439 common heads: bebd167eb94d
440
440
441 Both sides many new with stub:
441 Both sides many new with stub:
442
442
443 $ testdesc '-ra1 -ra2' '-rb' '
443 $ testdesc '-ra1 -ra2' '-rb' '
444 > +2:f +2:a1 +30 :b
444 > +2:f +2:a1 +30 :b
445 > <f +30 :a2'
445 > <f +30 :a2'
446
446
447 % -- a -> b tree
447 % -- a -> b tree
448 comparing with b
448 comparing with b
449 searching for changes
449 searching for changes
450 unpruned common: 2dc09a01254d
450 unpruned common: 2dc09a01254d
451 elapsed time: * seconds (glob)
451 elapsed time: * seconds (glob)
452 round-trips: 4
452 round-trips: 4
453 heads summary:
453 heads summary:
454 total common heads: 1
454 total common heads: 1
455 also local heads: 1
455 also local heads: 1
456 also remote heads: 0
456 also remote heads: 0
457 both: 0
457 both: 0
458 local heads: 2
458 local heads: 2
459 common: 1
459 common: 1
460 missing: 1
460 missing: 1
461 remote heads: 1
461 remote heads: 1
462 common: 0
462 common: 0
463 unknown: 1
463 unknown: 1
464 local changesets: 34
464 local changesets: 34
465 common: 4
465 common: 4
466 heads: 1
466 heads: 1
467 roots: 1
467 roots: 1
468 missing: 30
468 missing: 30
469 heads: 1
469 heads: 1
470 roots: 1
470 roots: 1
471 first undecided set: 33
471 first undecided set: 33
472 heads: 2
472 heads: 2
473 roots: 1
473 roots: 1
474 common: 3
474 common: 3
475 missing: 30
475 missing: 30
476 common heads: 2dc09a01254d
476 common heads: 2dc09a01254d
477
477
478 % -- a -> b set
478 % -- a -> b set
479 comparing with b
479 comparing with b
480 query 1; heads
480 query 1; heads
481 searching for changes
481 searching for changes
482 taking initial sample
482 taking initial sample
483 searching: 2 queries
483 searching: 2 queries
484 query 2; still undecided: 29, sample size is: 29
484 query 2; still undecided: 29, sample size is: 29
485 2 total queries in *.????s (glob)
485 2 total queries in *.????s (glob)
486 elapsed time: * seconds (glob)
486 elapsed time: * seconds (glob)
487 round-trips: 2
487 round-trips: 2
488 heads summary:
488 heads summary:
489 total common heads: 1
489 total common heads: 1
490 also local heads: 1
490 also local heads: 1
491 also remote heads: 0
491 also remote heads: 0
492 both: 0
492 both: 0
493 local heads: 2
493 local heads: 2
494 common: 1
494 common: 1
495 missing: 1
495 missing: 1
496 remote heads: 1
496 remote heads: 1
497 common: 0
497 common: 0
498 unknown: 1
498 unknown: 1
499 local changesets: 34
499 local changesets: 34
500 common: 4
500 common: 4
501 heads: 1
501 heads: 1
502 roots: 1
502 roots: 1
503 missing: 30
503 missing: 30
504 heads: 1
504 heads: 1
505 roots: 1
505 roots: 1
506 first undecided set: 33
506 first undecided set: 33
507 heads: 2
507 heads: 2
508 roots: 1
508 roots: 1
509 common: 3
509 common: 3
510 missing: 30
510 missing: 30
511 common heads: 2dc09a01254d
511 common heads: 2dc09a01254d
512
512
513 % -- a -> b set (tip only)
513 % -- a -> b set (tip only)
514 comparing with b
514 comparing with b
515 query 1; heads
515 query 1; heads
516 searching for changes
516 searching for changes
517 taking quick initial sample
517 taking quick initial sample
518 searching: 2 queries
518 searching: 2 queries
519 query 2; still undecided: 31, sample size is: 31
519 query 2; still undecided: 31, sample size is: 31
520 2 total queries in *.????s (glob)
520 2 total queries in *.????s (glob)
521 elapsed time: * seconds (glob)
521 elapsed time: * seconds (glob)
522 round-trips: 2
522 round-trips: 2
523 heads summary:
523 heads summary:
524 total common heads: 1
524 total common heads: 1
525 also local heads: 0
525 also local heads: 0
526 also remote heads: 0
526 also remote heads: 0
527 both: 0
527 both: 0
528 local heads: 2
528 local heads: 2
529 common: 0
529 common: 0
530 missing: 2
530 missing: 2
531 remote heads: 1
531 remote heads: 1
532 common: 0
532 common: 0
533 unknown: 1
533 unknown: 1
534 local changesets: 34
534 local changesets: 34
535 common: 2
535 common: 2
536 heads: 1
536 heads: 1
537 roots: 1
537 roots: 1
538 missing: 32
538 missing: 32
539 heads: 2
539 heads: 2
540 roots: 2
540 roots: 2
541 first undecided set: 34
541 first undecided set: 34
542 heads: 2
542 heads: 2
543 roots: 1
543 roots: 1
544 common: 2
544 common: 2
545 missing: 32
545 missing: 32
546 common heads: 66f7d451a68b
546 common heads: 66f7d451a68b
547
547
548 % -- b -> a tree
548 % -- b -> a tree
549 comparing with a
549 comparing with a
550 searching for changes
550 searching for changes
551 unpruned common: 2dc09a01254d 66f7d451a68b
551 unpruned common: 2dc09a01254d 66f7d451a68b
552 elapsed time: * seconds (glob)
552 elapsed time: * seconds (glob)
553 round-trips: 4
553 round-trips: 4
554 heads summary:
554 heads summary:
555 total common heads: 1
555 total common heads: 1
556 also local heads: 0
556 also local heads: 0
557 also remote heads: 1
557 also remote heads: 1
558 both: 0
558 both: 0
559 local heads: 1
559 local heads: 1
560 common: 0
560 common: 0
561 missing: 1
561 missing: 1
562 remote heads: 2
562 remote heads: 2
563 common: 1
563 common: 1
564 unknown: 1
564 unknown: 1
565 local changesets: 34
565 local changesets: 34
566 common: 4
566 common: 4
567 heads: 1
567 heads: 1
568 roots: 1
568 roots: 1
569 missing: 30
569 missing: 30
570 heads: 1
570 heads: 1
571 roots: 1
571 roots: 1
572 first undecided set: 30
572 first undecided set: 30
573 heads: 1
573 heads: 1
574 roots: 1
574 roots: 1
575 common: 0
575 common: 0
576 missing: 30
576 missing: 30
577 common heads: 2dc09a01254d
577 common heads: 2dc09a01254d
578
578
579 % -- b -> a set
579 % -- b -> a set
580 comparing with a
580 comparing with a
581 query 1; heads
581 query 1; heads
582 searching for changes
582 searching for changes
583 taking initial sample
583 taking initial sample
584 searching: 2 queries
584 searching: 2 queries
585 query 2; still undecided: 29, sample size is: 29
585 query 2; still undecided: 29, sample size is: 29
586 2 total queries in *.????s (glob)
586 2 total queries in *.????s (glob)
587 elapsed time: * seconds (glob)
587 elapsed time: * seconds (glob)
588 round-trips: 2
588 round-trips: 2
589 heads summary:
589 heads summary:
590 total common heads: 1
590 total common heads: 1
591 also local heads: 0
591 also local heads: 0
592 also remote heads: 1
592 also remote heads: 1
593 both: 0
593 both: 0
594 local heads: 1
594 local heads: 1
595 common: 0
595 common: 0
596 missing: 1
596 missing: 1
597 remote heads: 2
597 remote heads: 2
598 common: 1
598 common: 1
599 unknown: 1
599 unknown: 1
600 local changesets: 34
600 local changesets: 34
601 common: 4
601 common: 4
602 heads: 1
602 heads: 1
603 roots: 1
603 roots: 1
604 missing: 30
604 missing: 30
605 heads: 1
605 heads: 1
606 roots: 1
606 roots: 1
607 first undecided set: 30
607 first undecided set: 30
608 heads: 1
608 heads: 1
609 roots: 1
609 roots: 1
610 common: 0
610 common: 0
611 missing: 30
611 missing: 30
612 common heads: 2dc09a01254d
612 common heads: 2dc09a01254d
613
613
614 % -- b -> a set (tip only)
614 % -- b -> a set (tip only)
615 comparing with a
615 comparing with a
616 query 1; heads
616 query 1; heads
617 searching for changes
617 searching for changes
618 taking initial sample
618 taking initial sample
619 searching: 2 queries
619 searching: 2 queries
620 query 2; still undecided: 29, sample size is: 29
620 query 2; still undecided: 29, sample size is: 29
621 2 total queries in *.????s (glob)
621 2 total queries in *.????s (glob)
622 elapsed time: * seconds (glob)
622 elapsed time: * seconds (glob)
623 round-trips: 2
623 round-trips: 2
624 heads summary:
624 heads summary:
625 total common heads: 1
625 total common heads: 1
626 also local heads: 0
626 also local heads: 0
627 also remote heads: 1
627 also remote heads: 1
628 both: 0
628 both: 0
629 local heads: 1
629 local heads: 1
630 common: 0
630 common: 0
631 missing: 1
631 missing: 1
632 remote heads: 2
632 remote heads: 2
633 common: 1
633 common: 1
634 unknown: 1
634 unknown: 1
635 local changesets: 34
635 local changesets: 34
636 common: 4
636 common: 4
637 heads: 1
637 heads: 1
638 roots: 1
638 roots: 1
639 missing: 30
639 missing: 30
640 heads: 1
640 heads: 1
641 roots: 1
641 roots: 1
642 first undecided set: 30
642 first undecided set: 30
643 heads: 1
643 heads: 1
644 roots: 1
644 roots: 1
645 common: 0
645 common: 0
646 missing: 30
646 missing: 30
647 common heads: 2dc09a01254d
647 common heads: 2dc09a01254d
648
648
649
649
650 Both many new:
650 Both many new:
651
651
652 $ testdesc '-ra' '-rb' '
652 $ testdesc '-ra' '-rb' '
653 > +2:f +30 :b
653 > +2:f +30 :b
654 > <f +30 :a'
654 > <f +30 :a'
655
655
656 % -- a -> b tree
656 % -- a -> b tree
657 comparing with b
657 comparing with b
658 searching for changes
658 searching for changes
659 unpruned common: 66f7d451a68b
659 unpruned common: 66f7d451a68b
660 elapsed time: * seconds (glob)
660 elapsed time: * seconds (glob)
661 round-trips: 4
661 round-trips: 4
662 heads summary:
662 heads summary:
663 total common heads: 1
663 total common heads: 1
664 also local heads: 0
664 also local heads: 0
665 also remote heads: 0
665 also remote heads: 0
666 both: 0
666 both: 0
667 local heads: 1
667 local heads: 1
668 common: 0
668 common: 0
669 missing: 1
669 missing: 1
670 remote heads: 1
670 remote heads: 1
671 common: 0
671 common: 0
672 unknown: 1
672 unknown: 1
673 local changesets: 32
673 local changesets: 32
674 common: 2
674 common: 2
675 heads: 1
675 heads: 1
676 roots: 1
676 roots: 1
677 missing: 30
677 missing: 30
678 heads: 1
678 heads: 1
679 roots: 1
679 roots: 1
680 first undecided set: 32
680 first undecided set: 32
681 heads: 1
681 heads: 1
682 roots: 1
682 roots: 1
683 common: 2
683 common: 2
684 missing: 30
684 missing: 30
685 common heads: 66f7d451a68b
685 common heads: 66f7d451a68b
686
686
687 % -- a -> b set
687 % -- a -> b set
688 comparing with b
688 comparing with b
689 query 1; heads
689 query 1; heads
690 searching for changes
690 searching for changes
691 taking quick initial sample
691 taking quick initial sample
692 searching: 2 queries
692 searching: 2 queries
693 query 2; still undecided: 31, sample size is: 31
693 query 2; still undecided: 31, sample size is: 31
694 2 total queries in *.????s (glob)
694 2 total queries in *.????s (glob)
695 elapsed time: * seconds (glob)
695 elapsed time: * seconds (glob)
696 round-trips: 2
696 round-trips: 2
697 heads summary:
697 heads summary:
698 total common heads: 1
698 total common heads: 1
699 also local heads: 0
699 also local heads: 0
700 also remote heads: 0
700 also remote heads: 0
701 both: 0
701 both: 0
702 local heads: 1
702 local heads: 1
703 common: 0
703 common: 0
704 missing: 1
704 missing: 1
705 remote heads: 1
705 remote heads: 1
706 common: 0
706 common: 0
707 unknown: 1
707 unknown: 1
708 local changesets: 32
708 local changesets: 32
709 common: 2
709 common: 2
710 heads: 1
710 heads: 1
711 roots: 1
711 roots: 1
712 missing: 30
712 missing: 30
713 heads: 1
713 heads: 1
714 roots: 1
714 roots: 1
715 first undecided set: 32
715 first undecided set: 32
716 heads: 1
716 heads: 1
717 roots: 1
717 roots: 1
718 common: 2
718 common: 2
719 missing: 30
719 missing: 30
720 common heads: 66f7d451a68b
720 common heads: 66f7d451a68b
721
721
722 % -- a -> b set (tip only)
722 % -- a -> b set (tip only)
723 comparing with b
723 comparing with b
724 query 1; heads
724 query 1; heads
725 searching for changes
725 searching for changes
726 taking quick initial sample
726 taking quick initial sample
727 searching: 2 queries
727 searching: 2 queries
728 query 2; still undecided: 31, sample size is: 31
728 query 2; still undecided: 31, sample size is: 31
729 2 total queries in *.????s (glob)
729 2 total queries in *.????s (glob)
730 elapsed time: * seconds (glob)
730 elapsed time: * seconds (glob)
731 round-trips: 2
731 round-trips: 2
732 heads summary:
732 heads summary:
733 total common heads: 1
733 total common heads: 1
734 also local heads: 0
734 also local heads: 0
735 also remote heads: 0
735 also remote heads: 0
736 both: 0
736 both: 0
737 local heads: 1
737 local heads: 1
738 common: 0
738 common: 0
739 missing: 1
739 missing: 1
740 remote heads: 1
740 remote heads: 1
741 common: 0
741 common: 0
742 unknown: 1
742 unknown: 1
743 local changesets: 32
743 local changesets: 32
744 common: 2
744 common: 2
745 heads: 1
745 heads: 1
746 roots: 1
746 roots: 1
747 missing: 30
747 missing: 30
748 heads: 1
748 heads: 1
749 roots: 1
749 roots: 1
750 first undecided set: 32
750 first undecided set: 32
751 heads: 1
751 heads: 1
752 roots: 1
752 roots: 1
753 common: 2
753 common: 2
754 missing: 30
754 missing: 30
755 common heads: 66f7d451a68b
755 common heads: 66f7d451a68b
756
756
757 % -- b -> a tree
757 % -- b -> a tree
758 comparing with a
758 comparing with a
759 searching for changes
759 searching for changes
760 unpruned common: 66f7d451a68b
760 unpruned common: 66f7d451a68b
761 elapsed time: * seconds (glob)
761 elapsed time: * seconds (glob)
762 round-trips: 4
762 round-trips: 4
763 heads summary:
763 heads summary:
764 total common heads: 1
764 total common heads: 1
765 also local heads: 0
765 also local heads: 0
766 also remote heads: 0
766 also remote heads: 0
767 both: 0
767 both: 0
768 local heads: 1
768 local heads: 1
769 common: 0
769 common: 0
770 missing: 1
770 missing: 1
771 remote heads: 1
771 remote heads: 1
772 common: 0
772 common: 0
773 unknown: 1
773 unknown: 1
774 local changesets: 32
774 local changesets: 32
775 common: 2
775 common: 2
776 heads: 1
776 heads: 1
777 roots: 1
777 roots: 1
778 missing: 30
778 missing: 30
779 heads: 1
779 heads: 1
780 roots: 1
780 roots: 1
781 first undecided set: 32
781 first undecided set: 32
782 heads: 1
782 heads: 1
783 roots: 1
783 roots: 1
784 common: 2
784 common: 2
785 missing: 30
785 missing: 30
786 common heads: 66f7d451a68b
786 common heads: 66f7d451a68b
787
787
788 % -- b -> a set
788 % -- b -> a set
789 comparing with a
789 comparing with a
790 query 1; heads
790 query 1; heads
791 searching for changes
791 searching for changes
792 taking quick initial sample
792 taking quick initial sample
793 searching: 2 queries
793 searching: 2 queries
794 query 2; still undecided: 31, sample size is: 31
794 query 2; still undecided: 31, sample size is: 31
795 2 total queries in *.????s (glob)
795 2 total queries in *.????s (glob)
796 elapsed time: * seconds (glob)
796 elapsed time: * seconds (glob)
797 round-trips: 2
797 round-trips: 2
798 heads summary:
798 heads summary:
799 total common heads: 1
799 total common heads: 1
800 also local heads: 0
800 also local heads: 0
801 also remote heads: 0
801 also remote heads: 0
802 both: 0
802 both: 0
803 local heads: 1
803 local heads: 1
804 common: 0
804 common: 0
805 missing: 1
805 missing: 1
806 remote heads: 1
806 remote heads: 1
807 common: 0
807 common: 0
808 unknown: 1
808 unknown: 1
809 local changesets: 32
809 local changesets: 32
810 common: 2
810 common: 2
811 heads: 1
811 heads: 1
812 roots: 1
812 roots: 1
813 missing: 30
813 missing: 30
814 heads: 1
814 heads: 1
815 roots: 1
815 roots: 1
816 first undecided set: 32
816 first undecided set: 32
817 heads: 1
817 heads: 1
818 roots: 1
818 roots: 1
819 common: 2
819 common: 2
820 missing: 30
820 missing: 30
821 common heads: 66f7d451a68b
821 common heads: 66f7d451a68b
822
822
823 % -- b -> a set (tip only)
823 % -- b -> a set (tip only)
824 comparing with a
824 comparing with a
825 query 1; heads
825 query 1; heads
826 searching for changes
826 searching for changes
827 taking quick initial sample
827 taking quick initial sample
828 searching: 2 queries
828 searching: 2 queries
829 query 2; still undecided: 31, sample size is: 31
829 query 2; still undecided: 31, sample size is: 31
830 2 total queries in *.????s (glob)
830 2 total queries in *.????s (glob)
831 elapsed time: * seconds (glob)
831 elapsed time: * seconds (glob)
832 round-trips: 2
832 round-trips: 2
833 heads summary:
833 heads summary:
834 total common heads: 1
834 total common heads: 1
835 also local heads: 0
835 also local heads: 0
836 also remote heads: 0
836 also remote heads: 0
837 both: 0
837 both: 0
838 local heads: 1
838 local heads: 1
839 common: 0
839 common: 0
840 missing: 1
840 missing: 1
841 remote heads: 1
841 remote heads: 1
842 common: 0
842 common: 0
843 unknown: 1
843 unknown: 1
844 local changesets: 32
844 local changesets: 32
845 common: 2
845 common: 2
846 heads: 1
846 heads: 1
847 roots: 1
847 roots: 1
848 missing: 30
848 missing: 30
849 heads: 1
849 heads: 1
850 roots: 1
850 roots: 1
851 first undecided set: 32
851 first undecided set: 32
852 heads: 1
852 heads: 1
853 roots: 1
853 roots: 1
854 common: 2
854 common: 2
855 missing: 30
855 missing: 30
856 common heads: 66f7d451a68b
856 common heads: 66f7d451a68b
857
857
858
858
859 Both many new skewed:
859 Both many new skewed:
860
860
861 $ testdesc '-ra' '-rb' '
861 $ testdesc '-ra' '-rb' '
862 > +2:f +30 :b
862 > +2:f +30 :b
863 > <f +50 :a'
863 > <f +50 :a'
864
864
865 % -- a -> b tree
865 % -- a -> b tree
866 comparing with b
866 comparing with b
867 searching for changes
867 searching for changes
868 unpruned common: 66f7d451a68b
868 unpruned common: 66f7d451a68b
869 elapsed time: * seconds (glob)
869 elapsed time: * seconds (glob)
870 round-trips: 4
870 round-trips: 4
871 heads summary:
871 heads summary:
872 total common heads: 1
872 total common heads: 1
873 also local heads: 0
873 also local heads: 0
874 also remote heads: 0
874 also remote heads: 0
875 both: 0
875 both: 0
876 local heads: 1
876 local heads: 1
877 common: 0
877 common: 0
878 missing: 1
878 missing: 1
879 remote heads: 1
879 remote heads: 1
880 common: 0
880 common: 0
881 unknown: 1
881 unknown: 1
882 local changesets: 52
882 local changesets: 52
883 common: 2
883 common: 2
884 heads: 1
884 heads: 1
885 roots: 1
885 roots: 1
886 missing: 50
886 missing: 50
887 heads: 1
887 heads: 1
888 roots: 1
888 roots: 1
889 first undecided set: 52
889 first undecided set: 52
890 heads: 1
890 heads: 1
891 roots: 1
891 roots: 1
892 common: 2
892 common: 2
893 missing: 50
893 missing: 50
894 common heads: 66f7d451a68b
894 common heads: 66f7d451a68b
895
895
896 % -- a -> b set
896 % -- a -> b set
897 comparing with b
897 comparing with b
898 query 1; heads
898 query 1; heads
899 searching for changes
899 searching for changes
900 taking quick initial sample
900 taking quick initial sample
901 searching: 2 queries
901 searching: 2 queries
902 query 2; still undecided: 51, sample size is: 51
902 query 2; still undecided: 51, sample size is: 51
903 2 total queries in *.????s (glob)
903 2 total queries in *.????s (glob)
904 elapsed time: * seconds (glob)
904 elapsed time: * seconds (glob)
905 round-trips: 2
905 round-trips: 2
906 heads summary:
906 heads summary:
907 total common heads: 1
907 total common heads: 1
908 also local heads: 0
908 also local heads: 0
909 also remote heads: 0
909 also remote heads: 0
910 both: 0
910 both: 0
911 local heads: 1
911 local heads: 1
912 common: 0
912 common: 0
913 missing: 1
913 missing: 1
914 remote heads: 1
914 remote heads: 1
915 common: 0
915 common: 0
916 unknown: 1
916 unknown: 1
917 local changesets: 52
917 local changesets: 52
918 common: 2
918 common: 2
919 heads: 1
919 heads: 1
920 roots: 1
920 roots: 1
921 missing: 50
921 missing: 50
922 heads: 1
922 heads: 1
923 roots: 1
923 roots: 1
924 first undecided set: 52
924 first undecided set: 52
925 heads: 1
925 heads: 1
926 roots: 1
926 roots: 1
927 common: 2
927 common: 2
928 missing: 50
928 missing: 50
929 common heads: 66f7d451a68b
929 common heads: 66f7d451a68b
930
930
931 % -- a -> b set (tip only)
931 % -- a -> b set (tip only)
932 comparing with b
932 comparing with b
933 query 1; heads
933 query 1; heads
934 searching for changes
934 searching for changes
935 taking quick initial sample
935 taking quick initial sample
936 searching: 2 queries
936 searching: 2 queries
937 query 2; still undecided: 51, sample size is: 51
937 query 2; still undecided: 51, sample size is: 51
938 2 total queries in *.????s (glob)
938 2 total queries in *.????s (glob)
939 elapsed time: * seconds (glob)
939 elapsed time: * seconds (glob)
940 round-trips: 2
940 round-trips: 2
941 heads summary:
941 heads summary:
942 total common heads: 1
942 total common heads: 1
943 also local heads: 0
943 also local heads: 0
944 also remote heads: 0
944 also remote heads: 0
945 both: 0
945 both: 0
946 local heads: 1
946 local heads: 1
947 common: 0
947 common: 0
948 missing: 1
948 missing: 1
949 remote heads: 1
949 remote heads: 1
950 common: 0
950 common: 0
951 unknown: 1
951 unknown: 1
952 local changesets: 52
952 local changesets: 52
953 common: 2
953 common: 2
954 heads: 1
954 heads: 1
955 roots: 1
955 roots: 1
956 missing: 50
956 missing: 50
957 heads: 1
957 heads: 1
958 roots: 1
958 roots: 1
959 first undecided set: 52
959 first undecided set: 52
960 heads: 1
960 heads: 1
961 roots: 1
961 roots: 1
962 common: 2
962 common: 2
963 missing: 50
963 missing: 50
964 common heads: 66f7d451a68b
964 common heads: 66f7d451a68b
965
965
966 % -- b -> a tree
966 % -- b -> a tree
967 comparing with a
967 comparing with a
968 searching for changes
968 searching for changes
969 unpruned common: 66f7d451a68b
969 unpruned common: 66f7d451a68b
970 elapsed time: * seconds (glob)
970 elapsed time: * seconds (glob)
971 round-trips: 3
971 round-trips: 3
972 heads summary:
972 heads summary:
973 total common heads: 1
973 total common heads: 1
974 also local heads: 0
974 also local heads: 0
975 also remote heads: 0
975 also remote heads: 0
976 both: 0
976 both: 0
977 local heads: 1
977 local heads: 1
978 common: 0
978 common: 0
979 missing: 1
979 missing: 1
980 remote heads: 1
980 remote heads: 1
981 common: 0
981 common: 0
982 unknown: 1
982 unknown: 1
983 local changesets: 32
983 local changesets: 32
984 common: 2
984 common: 2
985 heads: 1
985 heads: 1
986 roots: 1
986 roots: 1
987 missing: 30
987 missing: 30
988 heads: 1
988 heads: 1
989 roots: 1
989 roots: 1
990 first undecided set: 32
990 first undecided set: 32
991 heads: 1
991 heads: 1
992 roots: 1
992 roots: 1
993 common: 2
993 common: 2
994 missing: 30
994 missing: 30
995 common heads: 66f7d451a68b
995 common heads: 66f7d451a68b
996
996
997 % -- b -> a set
997 % -- b -> a set
998 comparing with a
998 comparing with a
999 query 1; heads
999 query 1; heads
1000 searching for changes
1000 searching for changes
1001 taking quick initial sample
1001 taking quick initial sample
1002 searching: 2 queries
1002 searching: 2 queries
1003 query 2; still undecided: 31, sample size is: 31
1003 query 2; still undecided: 31, sample size is: 31
1004 2 total queries in *.????s (glob)
1004 2 total queries in *.????s (glob)
1005 elapsed time: * seconds (glob)
1005 elapsed time: * seconds (glob)
1006 round-trips: 2
1006 round-trips: 2
1007 heads summary:
1007 heads summary:
1008 total common heads: 1
1008 total common heads: 1
1009 also local heads: 0
1009 also local heads: 0
1010 also remote heads: 0
1010 also remote heads: 0
1011 both: 0
1011 both: 0
1012 local heads: 1
1012 local heads: 1
1013 common: 0
1013 common: 0
1014 missing: 1
1014 missing: 1
1015 remote heads: 1
1015 remote heads: 1
1016 common: 0
1016 common: 0
1017 unknown: 1
1017 unknown: 1
1018 local changesets: 32
1018 local changesets: 32
1019 common: 2
1019 common: 2
1020 heads: 1
1020 heads: 1
1021 roots: 1
1021 roots: 1
1022 missing: 30
1022 missing: 30
1023 heads: 1
1023 heads: 1
1024 roots: 1
1024 roots: 1
1025 first undecided set: 32
1025 first undecided set: 32
1026 heads: 1
1026 heads: 1
1027 roots: 1
1027 roots: 1
1028 common: 2
1028 common: 2
1029 missing: 30
1029 missing: 30
1030 common heads: 66f7d451a68b
1030 common heads: 66f7d451a68b
1031
1031
1032 % -- b -> a set (tip only)
1032 % -- b -> a set (tip only)
1033 comparing with a
1033 comparing with a
1034 query 1; heads
1034 query 1; heads
1035 searching for changes
1035 searching for changes
1036 taking quick initial sample
1036 taking quick initial sample
1037 searching: 2 queries
1037 searching: 2 queries
1038 query 2; still undecided: 31, sample size is: 31
1038 query 2; still undecided: 31, sample size is: 31
1039 2 total queries in *.????s (glob)
1039 2 total queries in *.????s (glob)
1040 elapsed time: * seconds (glob)
1040 elapsed time: * seconds (glob)
1041 round-trips: 2
1041 round-trips: 2
1042 heads summary:
1042 heads summary:
1043 total common heads: 1
1043 total common heads: 1
1044 also local heads: 0
1044 also local heads: 0
1045 also remote heads: 0
1045 also remote heads: 0
1046 both: 0
1046 both: 0
1047 local heads: 1
1047 local heads: 1
1048 common: 0
1048 common: 0
1049 missing: 1
1049 missing: 1
1050 remote heads: 1
1050 remote heads: 1
1051 common: 0
1051 common: 0
1052 unknown: 1
1052 unknown: 1
1053 local changesets: 32
1053 local changesets: 32
1054 common: 2
1054 common: 2
1055 heads: 1
1055 heads: 1
1056 roots: 1
1056 roots: 1
1057 missing: 30
1057 missing: 30
1058 heads: 1
1058 heads: 1
1059 roots: 1
1059 roots: 1
1060 first undecided set: 32
1060 first undecided set: 32
1061 heads: 1
1061 heads: 1
1062 roots: 1
1062 roots: 1
1063 common: 2
1063 common: 2
1064 missing: 30
1064 missing: 30
1065 common heads: 66f7d451a68b
1065 common heads: 66f7d451a68b
1066
1066
1067
1067
1068 Both many new on top of long history:
1068 Both many new on top of long history:
1069
1069
1070 $ testdesc '-ra' '-rb' '
1070 $ testdesc '-ra' '-rb' '
1071 > +1000:f +30 :b
1071 > +1000:f +30 :b
1072 > <f +50 :a'
1072 > <f +50 :a'
1073
1073
1074 % -- a -> b tree
1074 % -- a -> b tree
1075 comparing with b
1075 comparing with b
1076 searching for changes
1076 searching for changes
1077 unpruned common: 7ead0cba2838
1077 unpruned common: 7ead0cba2838
1078 elapsed time: * seconds (glob)
1078 elapsed time: * seconds (glob)
1079 round-trips: 4
1079 round-trips: 4
1080 heads summary:
1080 heads summary:
1081 total common heads: 1
1081 total common heads: 1
1082 also local heads: 0
1082 also local heads: 0
1083 also remote heads: 0
1083 also remote heads: 0
1084 both: 0
1084 both: 0
1085 local heads: 1
1085 local heads: 1
1086 common: 0
1086 common: 0
1087 missing: 1
1087 missing: 1
1088 remote heads: 1
1088 remote heads: 1
1089 common: 0
1089 common: 0
1090 unknown: 1
1090 unknown: 1
1091 local changesets: 1050
1091 local changesets: 1050
1092 common: 1000
1092 common: 1000
1093 heads: 1
1093 heads: 1
1094 roots: 1
1094 roots: 1
1095 missing: 50
1095 missing: 50
1096 heads: 1
1096 heads: 1
1097 roots: 1
1097 roots: 1
1098 first undecided set: 1050
1098 first undecided set: 1050
1099 heads: 1
1099 heads: 1
1100 roots: 1
1100 roots: 1
1101 common: 1000
1101 common: 1000
1102 missing: 50
1102 missing: 50
1103 common heads: 7ead0cba2838
1103 common heads: 7ead0cba2838
1104
1104
1105 % -- a -> b set
1105 % -- a -> b set
1106 comparing with b
1106 comparing with b
1107 query 1; heads
1107 query 1; heads
1108 searching for changes
1108 searching for changes
1109 taking quick initial sample
1109 taking quick initial sample
1110 searching: 2 queries
1110 searching: 2 queries
1111 query 2; still undecided: 1049, sample size is: 11
1111 query 2; still undecided: 1049, sample size is: 11
1112 sampling from both directions
1112 sampling from both directions
1113 searching: 3 queries
1113 searching: 3 queries
1114 query 3; still undecided: 31, sample size is: 31
1114 query 3; still undecided: 31, sample size is: 31
1115 3 total queries in *.????s (glob)
1115 3 total queries in *.????s (glob)
1116 elapsed time: * seconds (glob)
1116 elapsed time: * seconds (glob)
1117 round-trips: 3
1117 round-trips: 3
1118 heads summary:
1118 heads summary:
1119 total common heads: 1
1119 total common heads: 1
1120 also local heads: 0
1120 also local heads: 0
1121 also remote heads: 0
1121 also remote heads: 0
1122 both: 0
1122 both: 0
1123 local heads: 1
1123 local heads: 1
1124 common: 0
1124 common: 0
1125 missing: 1
1125 missing: 1
1126 remote heads: 1
1126 remote heads: 1
1127 common: 0
1127 common: 0
1128 unknown: 1
1128 unknown: 1
1129 local changesets: 1050
1129 local changesets: 1050
1130 common: 1000
1130 common: 1000
1131 heads: 1
1131 heads: 1
1132 roots: 1
1132 roots: 1
1133 missing: 50
1133 missing: 50
1134 heads: 1
1134 heads: 1
1135 roots: 1
1135 roots: 1
1136 first undecided set: 1050
1136 first undecided set: 1050
1137 heads: 1
1137 heads: 1
1138 roots: 1
1138 roots: 1
1139 common: 1000
1139 common: 1000
1140 missing: 50
1140 missing: 50
1141 common heads: 7ead0cba2838
1141 common heads: 7ead0cba2838
1142
1142
1143 % -- a -> b set (tip only)
1143 % -- a -> b set (tip only)
1144 comparing with b
1144 comparing with b
1145 query 1; heads
1145 query 1; heads
1146 searching for changes
1146 searching for changes
1147 taking quick initial sample
1147 taking quick initial sample
1148 searching: 2 queries
1148 searching: 2 queries
1149 query 2; still undecided: 1049, sample size is: 11
1149 query 2; still undecided: 1049, sample size is: 11
1150 sampling from both directions
1150 sampling from both directions
1151 searching: 3 queries
1151 searching: 3 queries
1152 query 3; still undecided: 31, sample size is: 31
1152 query 3; still undecided: 31, sample size is: 31
1153 3 total queries in *.????s (glob)
1153 3 total queries in *.????s (glob)
1154 elapsed time: * seconds (glob)
1154 elapsed time: * seconds (glob)
1155 round-trips: 3
1155 round-trips: 3
1156 heads summary:
1156 heads summary:
1157 total common heads: 1
1157 total common heads: 1
1158 also local heads: 0
1158 also local heads: 0
1159 also remote heads: 0
1159 also remote heads: 0
1160 both: 0
1160 both: 0
1161 local heads: 1
1161 local heads: 1
1162 common: 0
1162 common: 0
1163 missing: 1
1163 missing: 1
1164 remote heads: 1
1164 remote heads: 1
1165 common: 0
1165 common: 0
1166 unknown: 1
1166 unknown: 1
1167 local changesets: 1050
1167 local changesets: 1050
1168 common: 1000
1168 common: 1000
1169 heads: 1
1169 heads: 1
1170 roots: 1
1170 roots: 1
1171 missing: 50
1171 missing: 50
1172 heads: 1
1172 heads: 1
1173 roots: 1
1173 roots: 1
1174 first undecided set: 1050
1174 first undecided set: 1050
1175 heads: 1
1175 heads: 1
1176 roots: 1
1176 roots: 1
1177 common: 1000
1177 common: 1000
1178 missing: 50
1178 missing: 50
1179 common heads: 7ead0cba2838
1179 common heads: 7ead0cba2838
1180
1180
1181 % -- b -> a tree
1181 % -- b -> a tree
1182 comparing with a
1182 comparing with a
1183 searching for changes
1183 searching for changes
1184 unpruned common: 7ead0cba2838
1184 unpruned common: 7ead0cba2838
1185 elapsed time: * seconds (glob)
1185 elapsed time: * seconds (glob)
1186 round-trips: 3
1186 round-trips: 3
1187 heads summary:
1187 heads summary:
1188 total common heads: 1
1188 total common heads: 1
1189 also local heads: 0
1189 also local heads: 0
1190 also remote heads: 0
1190 also remote heads: 0
1191 both: 0
1191 both: 0
1192 local heads: 1
1192 local heads: 1
1193 common: 0
1193 common: 0
1194 missing: 1
1194 missing: 1
1195 remote heads: 1
1195 remote heads: 1
1196 common: 0
1196 common: 0
1197 unknown: 1
1197 unknown: 1
1198 local changesets: 1030
1198 local changesets: 1030
1199 common: 1000
1199 common: 1000
1200 heads: 1
1200 heads: 1
1201 roots: 1
1201 roots: 1
1202 missing: 30
1202 missing: 30
1203 heads: 1
1203 heads: 1
1204 roots: 1
1204 roots: 1
1205 first undecided set: 1030
1205 first undecided set: 1030
1206 heads: 1
1206 heads: 1
1207 roots: 1
1207 roots: 1
1208 common: 1000
1208 common: 1000
1209 missing: 30
1209 missing: 30
1210 common heads: 7ead0cba2838
1210 common heads: 7ead0cba2838
1211
1211
1212 % -- b -> a set
1212 % -- b -> a set
1213 comparing with a
1213 comparing with a
1214 query 1; heads
1214 query 1; heads
1215 searching for changes
1215 searching for changes
1216 taking quick initial sample
1216 taking quick initial sample
1217 searching: 2 queries
1217 searching: 2 queries
1218 query 2; still undecided: 1029, sample size is: 11
1218 query 2; still undecided: 1029, sample size is: 11
1219 sampling from both directions
1219 sampling from both directions
1220 searching: 3 queries
1220 searching: 3 queries
1221 query 3; still undecided: 15, sample size is: 15
1221 query 3; still undecided: 15, sample size is: 15
1222 3 total queries in *.????s (glob)
1222 3 total queries in *.????s (glob)
1223 elapsed time: * seconds (glob)
1223 elapsed time: * seconds (glob)
1224 round-trips: 3
1224 round-trips: 3
1225 heads summary:
1225 heads summary:
1226 total common heads: 1
1226 total common heads: 1
1227 also local heads: 0
1227 also local heads: 0
1228 also remote heads: 0
1228 also remote heads: 0
1229 both: 0
1229 both: 0
1230 local heads: 1
1230 local heads: 1
1231 common: 0
1231 common: 0
1232 missing: 1
1232 missing: 1
1233 remote heads: 1
1233 remote heads: 1
1234 common: 0
1234 common: 0
1235 unknown: 1
1235 unknown: 1
1236 local changesets: 1030
1236 local changesets: 1030
1237 common: 1000
1237 common: 1000
1238 heads: 1
1238 heads: 1
1239 roots: 1
1239 roots: 1
1240 missing: 30
1240 missing: 30
1241 heads: 1
1241 heads: 1
1242 roots: 1
1242 roots: 1
1243 first undecided set: 1030
1243 first undecided set: 1030
1244 heads: 1
1244 heads: 1
1245 roots: 1
1245 roots: 1
1246 common: 1000
1246 common: 1000
1247 missing: 30
1247 missing: 30
1248 common heads: 7ead0cba2838
1248 common heads: 7ead0cba2838
1249
1249
1250 % -- b -> a set (tip only)
1250 % -- b -> a set (tip only)
1251 comparing with a
1251 comparing with a
1252 query 1; heads
1252 query 1; heads
1253 searching for changes
1253 searching for changes
1254 taking quick initial sample
1254 taking quick initial sample
1255 searching: 2 queries
1255 searching: 2 queries
1256 query 2; still undecided: 1029, sample size is: 11
1256 query 2; still undecided: 1029, sample size is: 11
1257 sampling from both directions
1257 sampling from both directions
1258 searching: 3 queries
1258 searching: 3 queries
1259 query 3; still undecided: 15, sample size is: 15
1259 query 3; still undecided: 15, sample size is: 15
1260 3 total queries in *.????s (glob)
1260 3 total queries in *.????s (glob)
1261 elapsed time: * seconds (glob)
1261 elapsed time: * seconds (glob)
1262 round-trips: 3
1262 round-trips: 3
1263 heads summary:
1263 heads summary:
1264 total common heads: 1
1264 total common heads: 1
1265 also local heads: 0
1265 also local heads: 0
1266 also remote heads: 0
1266 also remote heads: 0
1267 both: 0
1267 both: 0
1268 local heads: 1
1268 local heads: 1
1269 common: 0
1269 common: 0
1270 missing: 1
1270 missing: 1
1271 remote heads: 1
1271 remote heads: 1
1272 common: 0
1272 common: 0
1273 unknown: 1
1273 unknown: 1
1274 local changesets: 1030
1274 local changesets: 1030
1275 common: 1000
1275 common: 1000
1276 heads: 1
1276 heads: 1
1277 roots: 1
1277 roots: 1
1278 missing: 30
1278 missing: 30
1279 heads: 1
1279 heads: 1
1280 roots: 1
1280 roots: 1
1281 first undecided set: 1030
1281 first undecided set: 1030
1282 heads: 1
1282 heads: 1
1283 roots: 1
1283 roots: 1
1284 common: 1000
1284 common: 1000
1285 missing: 30
1285 missing: 30
1286 common heads: 7ead0cba2838
1286 common heads: 7ead0cba2838
1287
1287
1288
1288
1289 One with >200 heads. We now switch to send them all in the initial roundtrip, but still do sampling for the later request.
1289 One with >200 heads. We now switch to send them all in the initial roundtrip, but still do sampling for the later request.
1290
1290
1291 $ hg init manyheads
1291 $ hg init manyheads
1292 $ cd manyheads
1292 $ cd manyheads
1293 $ echo "+300:r @a" >dagdesc
1293 $ echo "+300:r @a" >dagdesc
1294 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1294 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1295 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1295 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1296 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1296 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1297 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1297 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1298 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1298 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1299 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1299 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1300 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1300 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1301 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1301 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1302 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1302 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1303 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1303 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1304 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1304 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1305 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1305 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1306 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1306 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
1307 $ echo "@b *r+3" >>dagdesc # one more head
1307 $ echo "@b *r+3" >>dagdesc # one more head
1308 $ hg debugbuilddag <dagdesc
1308 $ hg debugbuilddag <dagdesc
1309 reading DAG from stdin
1309 reading DAG from stdin
1310
1310
1311 $ hg heads -t --template . | wc -c
1311 $ hg heads -t --template . | wc -c
1312 \s*261 (re)
1312 \s*261 (re)
1313
1313
1314 $ hg clone -b a . a
1314 $ hg clone -b a . a
1315 adding changesets
1315 adding changesets
1316 adding manifests
1316 adding manifests
1317 adding file changes
1317 adding file changes
1318 added 1340 changesets with 0 changes to 0 files (+259 heads)
1318 added 1340 changesets with 0 changes to 0 files (+259 heads)
1319 new changesets 1ea73414a91b:1c51e2c80832
1319 new changesets 1ea73414a91b:1c51e2c80832
1320 updating to branch a
1320 updating to branch a
1321 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1321 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1322 $ hg clone -b b . b
1322 $ hg clone -b b . b
1323 adding changesets
1323 adding changesets
1324 adding manifests
1324 adding manifests
1325 adding file changes
1325 adding file changes
1326 added 304 changesets with 0 changes to 0 files
1326 added 304 changesets with 0 changes to 0 files
1327 new changesets 1ea73414a91b:513314ca8b3a
1327 new changesets 1ea73414a91b:513314ca8b3a
1328 updating to branch b
1328 updating to branch b
1329 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1329 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1330
1330
1331 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --config devel.discovery.randomize=false --config devel.discovery.sample-size.initial=50
1331 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --config devel.discovery.randomize=false --config devel.discovery.sample-size.initial=50
1332 comparing with b
1332 comparing with b
1333 query 1; heads
1333 query 1; heads
1334 searching for changes
1334 searching for changes
1335 taking quick initial sample
1335 taking quick initial sample
1336 searching: 2 queries
1336 searching: 2 queries
1337 query 2; still undecided: 1080, sample size is: 50
1337 query 2; still undecided: 1080, sample size is: 50
1338 sampling from both directions
1338 sampling from both directions
1339 searching: 3 queries
1339 searching: 3 queries
1340 query 3; still undecided: 1030, sample size is: 200
1340 query 3; still undecided: 1030, sample size is: 200
1341 sampling from both directions
1341 sampling from both directions
1342 searching: 4 queries
1342 searching: 4 queries
1343 query 4; still undecided: 547, sample size is: 210
1343 query 4; still undecided: 547, sample size is: 210
1344 sampling from both directions
1344 sampling from both directions
1345 searching: 5 queries
1345 searching: 5 queries
1346 query 5; still undecided: 336, sample size is: 220
1346 query 5; still undecided: 336, sample size is: 220
1347 sampling from both directions
1347 sampling from both directions
1348 searching: 6 queries
1348 searching: 6 queries
1349 query 6; still undecided: 114, sample size is: 114
1349 query 6; still undecided: 114, sample size is: 114
1350 6 total queries in *.????s (glob)
1350 6 total queries in *.????s (glob)
1351 elapsed time: * seconds (glob)
1351 elapsed time: * seconds (glob)
1352 round-trips: 6
1352 round-trips: 6
1353 heads summary:
1353 heads summary:
1354 total common heads: 1
1354 total common heads: 1
1355 also local heads: 0
1355 also local heads: 0
1356 also remote heads: 0
1356 also remote heads: 0
1357 both: 0
1357 both: 0
1358 local heads: 260
1358 local heads: 260
1359 common: 0
1359 common: 0
1360 missing: 260
1360 missing: 260
1361 remote heads: 1
1361 remote heads: 1
1362 common: 0
1362 common: 0
1363 unknown: 1
1363 unknown: 1
1364 local changesets: 1340
1364 local changesets: 1340
1365 common: 300
1365 common: 300
1366 heads: 1
1366 heads: 1
1367 roots: 1
1367 roots: 1
1368 missing: 1040
1368 missing: 1040
1369 heads: 260
1369 heads: 260
1370 roots: 260
1370 roots: 260
1371 first undecided set: 1340
1371 first undecided set: 1340
1372 heads: 260
1372 heads: 260
1373 roots: 1
1373 roots: 1
1374 common: 300
1374 common: 300
1375 missing: 1040
1375 missing: 1040
1376 common heads: 3ee37d65064a
1376 common heads: 3ee37d65064a
1377 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --rev tip
1377 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --rev tip
1378 comparing with b
1378 comparing with b
1379 query 1; heads
1379 query 1; heads
1380 searching for changes
1380 searching for changes
1381 taking quick initial sample
1381 taking quick initial sample
1382 searching: 2 queries
1382 searching: 2 queries
1383 query 2; still undecided: 303, sample size is: 9
1383 query 2; still undecided: 303, sample size is: 9
1384 sampling from both directions
1384 sampling from both directions
1385 searching: 3 queries
1385 searching: 3 queries
1386 query 3; still undecided: 3, sample size is: 3
1386 query 3; still undecided: 3, sample size is: 3
1387 3 total queries in *.????s (glob)
1387 3 total queries in *.????s (glob)
1388 elapsed time: * seconds (glob)
1388 elapsed time: * seconds (glob)
1389 round-trips: 3
1389 round-trips: 3
1390 heads summary:
1390 heads summary:
1391 total common heads: 1
1391 total common heads: 1
1392 also local heads: 0
1392 also local heads: 0
1393 also remote heads: 0
1393 also remote heads: 0
1394 both: 0
1394 both: 0
1395 local heads: 260
1395 local heads: 260
1396 common: 0
1396 common: 0
1397 missing: 260
1397 missing: 260
1398 remote heads: 1
1398 remote heads: 1
1399 common: 0
1399 common: 0
1400 unknown: 1
1400 unknown: 1
1401 local changesets: 1340
1401 local changesets: 1340
1402 common: 300
1402 common: 300
1403 heads: 1
1403 heads: 1
1404 roots: 1
1404 roots: 1
1405 missing: 1040
1405 missing: 1040
1406 heads: 260
1406 heads: 260
1407 roots: 260
1407 roots: 260
1408 first undecided set: 1340
1408 first undecided set: 1340
1409 heads: 260
1409 heads: 260
1410 roots: 1
1410 roots: 1
1411 common: 300
1411 common: 300
1412 missing: 1040
1412 missing: 1040
1413 common heads: 3ee37d65064a
1413 common heads: 3ee37d65064a
1414
1414
1415 $ hg -R a debugdiscovery b --debug --config devel.discovery.exchange-heads=false --config devel.discovery.randomize=false --config devel.discovery.grow-sample.rate=1.20 --config devel.discovery.sample-size=50
1415 $ hg -R a debugdiscovery b --debug --config devel.discovery.exchange-heads=false --config devel.discovery.randomize=false --config devel.discovery.grow-sample.rate=1.20 --config devel.discovery.sample-size=50
1416 comparing with b
1416 comparing with b
1417 searching for changes
1417 searching for changes
1418 sampling from both directions
1418 sampling from both directions
1419 query 1; still undecided: 1340, sample size is: 50
1419 query 1; still undecided: 1340, sample size is: 50
1420 sampling from both directions
1420 sampling from both directions
1421 query 2; still undecided: 995, sample size is: 60
1421 query 2; still undecided: 995, sample size is: 60
1422 sampling from both directions
1422 sampling from both directions
1423 query 3; still undecided: 913, sample size is: 72
1423 query 3; still undecided: 913, sample size is: 72
1424 sampling from both directions
1424 sampling from both directions
1425 query 4; still undecided: 816, sample size is: 204
1425 query 4; still undecided: 816, sample size is: 204
1426 sampling from both directions
1426 sampling from both directions
1427 query 5; still undecided: 612, sample size is: 153
1427 query 5; still undecided: 612, sample size is: 153
1428 sampling from both directions
1428 sampling from both directions
1429 query 6; still undecided: 456, sample size is: 123
1429 query 6; still undecided: 456, sample size is: 123
1430 sampling from both directions
1430 sampling from both directions
1431 query 7; still undecided: 332, sample size is: 147
1431 query 7; still undecided: 332, sample size is: 147
1432 sampling from both directions
1432 sampling from both directions
1433 query 8; still undecided: 184, sample size is: 176
1433 query 8; still undecided: 184, sample size is: 176
1434 sampling from both directions
1434 sampling from both directions
1435 query 9; still undecided: 8, sample size is: 8
1435 query 9; still undecided: 8, sample size is: 8
1436 9 total queries in *s (glob)
1436 9 total queries in *s (glob)
1437 elapsed time: * seconds (glob)
1437 elapsed time: * seconds (glob)
1438 round-trips: 9
1438 round-trips: 9
1439 heads summary:
1439 heads summary:
1440 total common heads: 1
1440 total common heads: 1
1441 also local heads: 0
1441 also local heads: 0
1442 also remote heads: 0
1442 also remote heads: 0
1443 both: 0
1443 both: 0
1444 local heads: 260
1444 local heads: 260
1445 common: 0
1445 common: 0
1446 missing: 260
1446 missing: 260
1447 remote heads: 1
1447 remote heads: 1
1448 common: 0
1448 common: 0
1449 unknown: 1
1449 unknown: 1
1450 local changesets: 1340
1450 local changesets: 1340
1451 common: 300
1451 common: 300
1452 heads: 1
1452 heads: 1
1453 roots: 1
1453 roots: 1
1454 missing: 1040
1454 missing: 1040
1455 heads: 260
1455 heads: 260
1456 roots: 260
1456 roots: 260
1457 first undecided set: 1340
1457 first undecided set: 1340
1458 heads: 260
1458 heads: 260
1459 roots: 1
1459 roots: 1
1460 common: 300
1460 common: 300
1461 missing: 1040
1461 missing: 1040
1462 common heads: 3ee37d65064a
1462 common heads: 3ee37d65064a
1463
1463
1464 Test actual protocol when pulling one new head in addition to common heads
1464 Test actual protocol when pulling one new head in addition to common heads
1465
1465
1466 $ hg clone -U b c
1466 $ hg clone -U b c
1467 $ hg -R c id -ir tip
1467 $ hg -R c id -ir tip
1468 513314ca8b3a
1468 513314ca8b3a
1469 $ hg -R c up -qr default
1469 $ hg -R c up -qr default
1470 $ touch c/f
1470 $ touch c/f
1471 $ hg -R c ci -Aqm "extra head"
1471 $ hg -R c ci -Aqm "extra head"
1472 $ hg -R c id -i
1472 $ hg -R c id -i
1473 e64a39e7da8b
1473 e64a39e7da8b
1474
1474
1475 $ hg serve -R c -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1475 $ hg serve -R c -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1476 $ cat hg.pid >> $DAEMON_PIDS
1476 $ cat hg.pid >> $DAEMON_PIDS
1477
1477
1478 $ hg -R b incoming http://localhost:$HGPORT/ -T '{node|short}\n'
1478 $ hg -R b incoming http://localhost:$HGPORT/ -T '{node|short}\n'
1479 comparing with http://localhost:$HGPORT/
1479 comparing with http://localhost:$HGPORT/
1480 searching for changes
1480 searching for changes
1481 e64a39e7da8b
1481 e64a39e7da8b
1482
1482
1483 $ killdaemons.py
1483 $ killdaemons.py
1484 $ cut -d' ' -f6- access.log | grep -v cmd=known # cmd=known uses random sampling
1484 $ cut -d' ' -f6- access.log | grep -v cmd=known # cmd=known uses random sampling
1485 "GET /?cmd=capabilities HTTP/1.1" 200 -
1485 "GET /?cmd=capabilities HTTP/1.1" 200 -
1486 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D513314ca8b3ae4dac8eec56966265b00fcf866db x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1486 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D513314ca8b3ae4dac8eec56966265b00fcf866db x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1487 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:$USUAL_BUNDLE_CAPS$&cg=1&common=513314ca8b3ae4dac8eec56966265b00fcf866db&heads=e64a39e7da8b0d54bc63e81169aff001c13b3477 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1487 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:$USUAL_BUNDLE_CAPS$&cg=1&common=513314ca8b3ae4dac8eec56966265b00fcf866db&heads=e64a39e7da8b0d54bc63e81169aff001c13b3477 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1488 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1488 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
1489 $ cat errors.log
1489 $ cat errors.log
1490
1490
1491 $ cd ..
1491 $ cd ..
1492
1492
1493
1493
1494 Issue 4438 - test coverage for 3ef893520a85 issues.
1494 Issue 4438 - test coverage for 3ef893520a85 issues.
1495
1495
1496 $ mkdir issue4438
1496 $ mkdir issue4438
1497 $ cd issue4438
1497 $ cd issue4438
1498 #if false
1498 #if false
1499 generate new bundles:
1499 generate new bundles:
1500 $ hg init r1
1500 $ hg init r1
1501 $ for i in `"$PYTHON" $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
1501 $ for i in `"$PYTHON" $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
1502 $ hg clone -q r1 r2
1502 $ hg clone -q r1 r2
1503 $ for i in `"$PYTHON" $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
1503 $ for i in `"$PYTHON" $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
1504 $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
1504 $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
1505 $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
1505 $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
1506 $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
1506 $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
1507 #else
1507 #else
1508 use existing bundles:
1508 use existing bundles:
1509 $ hg init r1
1509 $ hg init r1
1510 $ hg -R r1 -q unbundle $TESTDIR/bundles/issue4438-r1.hg
1510 $ hg -R r1 -q unbundle $TESTDIR/bundles/issue4438-r1.hg
1511 $ hg -R r1 -q up
1511 $ hg -R r1 -q up
1512 $ hg init r2
1512 $ hg init r2
1513 $ hg -R r2 -q unbundle $TESTDIR/bundles/issue4438-r2.hg
1513 $ hg -R r2 -q unbundle $TESTDIR/bundles/issue4438-r2.hg
1514 $ hg -R r2 -q up
1514 $ hg -R r2 -q up
1515 #endif
1515 #endif
1516
1516
1517 Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650:
1517 Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650:
1518
1518
1519 $ hg -R r1 outgoing r2 -T'{rev} '
1519 $ hg -R r1 outgoing r2 -T'{rev} '
1520 comparing with r2
1520 comparing with r2
1521 searching for changes
1521 searching for changes
1522 101 102 103 104 105 106 107 108 109 110 (no-eol)
1522 101 102 103 104 105 106 107 108 109 110 (no-eol)
1523
1523
1524 The case where all the 'initialsamplesize' samples already were common would
1524 The case where all the 'initialsamplesize' samples already were common would
1525 give 'all remote heads known locally' without checking the remaining heads -
1525 give 'all remote heads known locally' without checking the remaining heads -
1526 fixed in 86c35b7ae300:
1526 fixed in 86c35b7ae300:
1527
1527
1528 $ cat >> r1/.hg/hgrc << EOF
1528 $ cat >> r1/.hg/hgrc << EOF
1529 > [devel]
1529 > [devel]
1530 > discovery.randomize = False
1530 > discovery.randomize = False
1531 > EOF
1531 > EOF
1532
1532
1533 $ hg -R r1 outgoing r2 -T'{rev} ' --config extensions.blackbox= \
1533 $ hg -R r1 outgoing r2 -T'{rev} ' --config extensions.blackbox= \
1534 > --config blackbox.track='command commandfinish discovery'
1534 > --config blackbox.track='command commandfinish discovery'
1535 comparing with r2
1535 comparing with r2
1536 searching for changes
1536 searching for changes
1537 101 102 103 104 105 106 107 108 109 110 (no-eol)
1537 101 102 103 104 105 106 107 108 109 110 (no-eol)
1538 $ hg -R r1 --config extensions.blackbox= blackbox --config blackbox.track=
1538 $ hg -R r1 --config extensions.blackbox= blackbox --config blackbox.track=
1539 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> serve --cmdserver chgunix * (glob) (chg !)
1539 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> serve --cmdserver chgunix * (glob) (chg !)
1540 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* (glob)
1540 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* (glob)
1541 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> found 101 common and 1 unknown server heads, 1 roundtrips in *.????s (glob)
1541 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> found 101 common and 1 unknown server heads, 1 roundtrips in *.????s (glob)
1542 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* exited 0 after *.?? seconds (glob)
1542 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* exited 0 after *.?? seconds (glob)
1543 $ cd ..
1543 $ cd ..
1544
1544
1545 Even if the set of revs to discover is restricted, unrelated revs may be
1545 Even if the set of revs to discover is restricted, unrelated revs may be
1546 returned as common heads.
1546 returned as common heads.
1547
1547
1548 $ mkdir ancestorsof
1548 $ mkdir ancestorsof
1549 $ cd ancestorsof
1549 $ cd ancestorsof
1550 $ hg init a
1550 $ hg init a
1551 $ hg clone a b -q
1551 $ hg clone a b -q
1552 $ cd b
1552 $ cd b
1553 $ hg debugbuilddag '.:root *root *root'
1553 $ hg debugbuilddag '.:root *root *root'
1554 $ hg log -G -T '{node|short}'
1554 $ hg log -G -T '{node|short}'
1555 o fa942426a6fd
1555 o fa942426a6fd
1556 |
1556 |
1557 | o 66f7d451a68b
1557 | o 66f7d451a68b
1558 |/
1558 |/
1559 o 1ea73414a91b
1559 o 1ea73414a91b
1560
1560
1561 $ hg push -r 66f7d451a68b -q
1561 $ hg push -r 66f7d451a68b -q
1562 $ hg debugdiscovery --verbose --rev fa942426a6fd
1562 $ hg debugdiscovery --verbose --rev fa942426a6fd
1563 comparing with $TESTTMP/ancestorsof/a
1563 comparing with $TESTTMP/ancestorsof/a
1564 searching for changes
1564 searching for changes
1565 elapsed time: * seconds (glob)
1565 elapsed time: * seconds (glob)
1566 round-trips: 1
1566 round-trips: 1
1567 heads summary:
1567 heads summary:
1568 total common heads: 1
1568 total common heads: 1
1569 also local heads: 1
1569 also local heads: 1
1570 also remote heads: 1
1570 also remote heads: 1
1571 both: 1
1571 both: 1
1572 local heads: 2
1572 local heads: 2
1573 common: 1
1573 common: 1
1574 missing: 1
1574 missing: 1
1575 remote heads: 1
1575 remote heads: 1
1576 common: 1
1576 common: 1
1577 unknown: 0
1577 unknown: 0
1578 local changesets: 3
1578 local changesets: 3
1579 common: 2
1579 common: 2
1580 heads: 1
1580 heads: 1
1581 roots: 1
1581 roots: 1
1582 missing: 1
1582 missing: 1
1583 heads: 1
1583 heads: 1
1584 roots: 1
1584 roots: 1
1585 first undecided set: 1
1585 first undecided set: 1
1586 heads: 1
1586 heads: 1
1587 roots: 1
1587 roots: 1
1588 common: 0
1588 common: 0
1589 missing: 1
1589 missing: 1
1590 common heads: 66f7d451a68b
1590 common heads: 66f7d451a68b
1591
1592 $ cd ..
1593
1594
1595 Test debuging discovery using different subset of the same repository
1596 =====================================================================
1597
1598 remote is a local subset
1599 ------------------------
1600
1601 remote will be last 25 heads of the local graph
1602
1603 $ cd $TESTTMP/manyheads
1604 $ hg -R a debugdiscovery \
1605 > --debug \
1606 > --remote-as-revs 'last(heads(all()), 25)' \
1607 > --config devel.discovery.randomize=false
1608 query 1; heads
1609 searching for changes
1610 all remote heads known locally
1611 elapsed time: * seconds (glob)
1612 round-trips: 1
1613 heads summary:
1614 total common heads: 25
1615 also local heads: 25
1616 also remote heads: 25
1617 both: 25
1618 local heads: 260
1619 common: 25
1620 missing: 235
1621 remote heads: 25
1622 common: 25
1623 unknown: 0
1624 local changesets: 1340
1625 common: 400
1626 heads: 25
1627 roots: 1
1628 missing: 940
1629 heads: 235
1630 roots: 235
1631 first undecided set: 940
1632 heads: 235
1633 roots: 235
1634 common: 0
1635 missing: 940
1636 common heads: 0dfd965d91c6 0fe09b60448d 14a17233ce9d 175c0a3072cf 1c51e2c80832 1e51600e0698 24eb5f9bdbab 25ce09526613 36bd00abde57 426989fdefa0 596d87362679 5dd1039ea5c0 5ef24f022278 5f230dc19419 80b39998accb 88f40688ffb5 9e37ddf8c632 abf4d55b075e b2ce801fddfe b368b6ac3ce3 c959bf2e869c c9fba6ba4e2e d783207cf649 d9a51e256f21 e3717a4e3753
1637
1638 local is a local subset
1639 ------------------------
1640
1641 remote will be last 25 heads of the local graph
1642
1643 $ cd $TESTTMP/manyheads
1644 $ hg -R a debugdiscovery b \
1645 > --debug \
1646 > --local-as-revs 'first(heads(all()), 25)' \
1647 > --config devel.discovery.randomize=false
1648 comparing with b
1649 query 1; heads
1650 searching for changes
1651 taking quick initial sample
1652 query 2; still undecided: 375, sample size is: 81
1653 sampling from both directions
1654 query 3; still undecided: 3, sample size is: 3
1655 3 total queries *s (glob)
1656 elapsed time: * seconds (glob)
1657 round-trips: 3
1658 heads summary:
1659 total common heads: 1
1660 also local heads: 0
1661 also remote heads: 0
1662 both: 0
1663 local heads: 25
1664 common: 0
1665 missing: 25
1666 remote heads: 1
1667 common: 0
1668 unknown: 1
1669 local changesets: 400
1670 common: 300
1671 heads: 1
1672 roots: 1
1673 missing: 100
1674 heads: 25
1675 roots: 25
1676 first undecided set: 400
1677 heads: 25
1678 roots: 1
1679 common: 300
1680 missing: 100
1681 common heads: 3ee37d65064a
1682
1683 both local and remove are subset
1684 ------------------------
1685
1686 remote will be last 25 heads of the local graph
1687
1688 $ cd $TESTTMP/manyheads
1689 $ hg -R a debugdiscovery \
1690 > --debug \
1691 > --local-as-revs 'first(heads(all()), 25)' \
1692 > --remote-as-revs 'last(heads(all()), 25)' \
1693 > --config devel.discovery.randomize=false
1694 query 1; heads
1695 searching for changes
1696 taking quick initial sample
1697 query 2; still undecided: 375, sample size is: 81
1698 sampling from both directions
1699 query 3; still undecided: 3, sample size is: 3
1700 3 total queries in *s (glob)
1701 elapsed time: * seconds (glob)
1702 round-trips: 3
1703 heads summary:
1704 total common heads: 1
1705 also local heads: 0
1706 also remote heads: 0
1707 both: 0
1708 local heads: 25
1709 common: 0
1710 missing: 25
1711 remote heads: 25
1712 common: 0
1713 unknown: 25
1714 local changesets: 400
1715 common: 300
1716 heads: 1
1717 roots: 1
1718 missing: 100
1719 heads: 25
1720 roots: 25
1721 first undecided set: 400
1722 heads: 25
1723 roots: 1
1724 common: 300
1725 missing: 100
1726 common heads: 3ee37d65064a
General Comments 0
You need to be logged in to leave comments. Login now