comparison mercurial/debugcommands.py @ 43076:2372284d9457

formatting: blacken the codebase This is using my patch to black (https://github.com/psf/black/pull/826) so we don't un-wrap collection literals. Done with: hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S # skip-blame mass-reformatting only # no-check-commit reformats foo_bar functions Differential Revision: https://phab.mercurial-scm.org/D6971
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:45:02 -0400
parents 0fde7d47ad6f
children 687b865b95ad
comparison
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
86 dateutil, 86 dateutil,
87 procutil, 87 procutil,
88 stringutil, 88 stringutil,
89 ) 89 )
90 90
91 from .revlogutils import ( 91 from .revlogutils import deltas as deltautil
92 deltas as deltautil
93 )
94 92
95 release = lockmod.release 93 release = lockmod.release
96 94
97 command = registrar.command() 95 command = registrar.command()
96
98 97
99 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True) 98 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
100 def debugancestor(ui, repo, *args): 99 def debugancestor(ui, repo, *args):
101 """find the ancestor revision of two revisions in a given index""" 100 """find the ancestor revision of two revisions in a given index"""
102 if len(args) == 3: 101 if len(args) == 3:
103 index, rev1, rev2 = args 102 index, rev1, rev2 = args
104 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index) 103 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
105 lookup = r.lookup 104 lookup = r.lookup
106 elif len(args) == 2: 105 elif len(args) == 2:
107 if not repo: 106 if not repo:
108 raise error.Abort(_('there is no Mercurial repository here ' 107 raise error.Abort(
109 '(.hg not found)')) 108 _('there is no Mercurial repository here ' '(.hg not found)')
109 )
110 rev1, rev2 = args 110 rev1, rev2 = args
111 r = repo.changelog 111 r = repo.changelog
112 lookup = repo.lookup 112 lookup = repo.lookup
113 else: 113 else:
114 raise error.Abort(_('either two or three arguments required')) 114 raise error.Abort(_('either two or three arguments required'))
115 a = r.ancestor(lookup(rev1), lookup(rev2)) 115 a = r.ancestor(lookup(rev1), lookup(rev2))
116 ui.write('%d:%s\n' % (r.rev(a), hex(a))) 116 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
117 117
118
118 @command('debugapplystreamclonebundle', [], 'FILE') 119 @command('debugapplystreamclonebundle', [], 'FILE')
119 def debugapplystreamclonebundle(ui, repo, fname): 120 def debugapplystreamclonebundle(ui, repo, fname):
120 """apply a stream clone bundle file""" 121 """apply a stream clone bundle file"""
121 f = hg.openpath(ui, fname) 122 f = hg.openpath(ui, fname)
122 gen = exchange.readbundle(ui, f, fname) 123 gen = exchange.readbundle(ui, f, fname)
123 gen.apply(repo) 124 gen.apply(repo)
124 125
125 @command('debugbuilddag', 126
126 [('m', 'mergeable-file', None, _('add single file mergeable changes')), 127 @command(
127 ('o', 'overwritten-file', None, _('add single file all revs overwrite')), 128 'debugbuilddag',
128 ('n', 'new-file', None, _('add new file at each rev'))], 129 [
129 _('[OPTION]... [TEXT]')) 130 ('m', 'mergeable-file', None, _('add single file mergeable changes')),
130 def debugbuilddag(ui, repo, text=None, 131 (
131 mergeable_file=False, 132 'o',
132 overwritten_file=False, 133 'overwritten-file',
133 new_file=False): 134 None,
135 _('add single file all revs overwrite'),
136 ),
137 ('n', 'new-file', None, _('add new file at each rev')),
138 ],
139 _('[OPTION]... [TEXT]'),
140 )
141 def debugbuilddag(
142 ui,
143 repo,
144 text=None,
145 mergeable_file=False,
146 overwritten_file=False,
147 new_file=False,
148 ):
134 """builds a repo with a given DAG from scratch in the current empty repo 149 """builds a repo with a given DAG from scratch in the current empty repo
135 150
136 The description of the DAG is read from stdin if not given on the 151 The description of the DAG is read from stdin if not given on the
137 command line. 152 command line.
138 153
178 total += 1 193 total += 1
179 194
180 if mergeable_file: 195 if mergeable_file:
181 linesperrev = 2 196 linesperrev = 2
182 # make a file with k lines per rev 197 # make a file with k lines per rev
183 initialmergedlines = ['%d' % i 198 initialmergedlines = [
184 for i in pycompat.xrange(0, total * linesperrev)] 199 '%d' % i for i in pycompat.xrange(0, total * linesperrev)
200 ]
185 initialmergedlines.append("") 201 initialmergedlines.append("")
186 202
187 tags = [] 203 tags = []
188 progress = ui.makeprogress(_('building'), unit=_('revisions'), 204 progress = ui.makeprogress(_('building'), unit=_('revisions'), total=total)
189 total=total)
190 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"): 205 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
191 at = -1 206 at = -1
192 atbranch = 'default' 207 atbranch = 'default'
193 nodeids = [] 208 nodeids = []
194 id = 0 209 id = 0
206 fn = "mf" 221 fn = "mf"
207 p1 = repo[ps[0]] 222 p1 = repo[ps[0]]
208 if len(ps) > 1: 223 if len(ps) > 1:
209 p2 = repo[ps[1]] 224 p2 = repo[ps[1]]
210 pa = p1.ancestor(p2) 225 pa = p1.ancestor(p2)
211 base, local, other = [x[fn].data() for x in (pa, p1, 226 base, local, other = [
212 p2)] 227 x[fn].data() for x in (pa, p1, p2)
228 ]
213 m3 = simplemerge.Merge3Text(base, local, other) 229 m3 = simplemerge.Merge3Text(base, local, other)
214 ml = [l.strip() for l in m3.merge_lines()] 230 ml = [l.strip() for l in m3.merge_lines()]
215 ml.append("") 231 ml.append("")
216 elif at > 0: 232 elif at > 0:
217 ml = p1[fn].data().split("\n") 233 ml = p1[fn].data().split("\n")
239 files.append(fn) 255 files.append(fn)
240 filecontent[fn] = p2[fn].data() 256 filecontent[fn] = p2[fn].data()
241 257
242 def fctxfn(repo, cx, path): 258 def fctxfn(repo, cx, path):
243 if path in filecontent: 259 if path in filecontent:
244 return context.memfilectx(repo, cx, path, 260 return context.memfilectx(
245 filecontent[path]) 261 repo, cx, path, filecontent[path]
262 )
246 return None 263 return None
247 264
248 if len(ps) == 0 or ps[0] < 0: 265 if len(ps) == 0 or ps[0] < 0:
249 pars = [None, None] 266 pars = [None, None]
250 elif len(ps) == 1: 267 elif len(ps) == 1:
251 pars = [nodeids[ps[0]], None] 268 pars = [nodeids[ps[0]], None]
252 else: 269 else:
253 pars = [nodeids[p] for p in ps] 270 pars = [nodeids[p] for p in ps]
254 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn, 271 cx = context.memctx(
255 date=(id, 0), 272 repo,
256 user="debugbuilddag", 273 pars,
257 extra={'branch': atbranch}) 274 "r%i" % id,
275 files,
276 fctxfn,
277 date=(id, 0),
278 user="debugbuilddag",
279 extra={'branch': atbranch},
280 )
258 nodeid = repo.commitctx(cx) 281 nodeid = repo.commitctx(cx)
259 nodeids.append(nodeid) 282 nodeids.append(nodeid)
260 at = id 283 at = id
261 elif type == 'l': 284 elif type == 'l':
262 id, name = data 285 id, name = data
268 progress.update(id) 291 progress.update(id)
269 292
270 if tags: 293 if tags:
271 repo.vfs.write("localtags", "".join(tags)) 294 repo.vfs.write("localtags", "".join(tags))
272 295
296
273 def _debugchangegroup(ui, gen, all=None, indent=0, **opts): 297 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
274 indent_string = ' ' * indent 298 indent_string = ' ' * indent
275 if all: 299 if all:
276 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n") 300 ui.write(
277 % indent_string) 301 "%sformat: id, p1, p2, cset, delta base, len(delta)\n"
302 % indent_string
303 )
278 304
279 def showchunks(named): 305 def showchunks(named):
280 ui.write("\n%s%s\n" % (indent_string, named)) 306 ui.write("\n%s%s\n" % (indent_string, named))
281 for deltadata in gen.deltaiter(): 307 for deltadata in gen.deltaiter():
282 node, p1, p2, cs, deltabase, delta, flags = deltadata 308 node, p1, p2, cs, deltabase, delta, flags = deltadata
283 ui.write("%s%s %s %s %s %s %d\n" % 309 ui.write(
284 (indent_string, hex(node), hex(p1), hex(p2), 310 "%s%s %s %s %s %s %d\n"
285 hex(cs), hex(deltabase), len(delta))) 311 % (
312 indent_string,
313 hex(node),
314 hex(p1),
315 hex(p2),
316 hex(cs),
317 hex(deltabase),
318 len(delta),
319 )
320 )
286 321
287 chunkdata = gen.changelogheader() 322 chunkdata = gen.changelogheader()
288 showchunks("changelog") 323 showchunks("changelog")
289 chunkdata = gen.manifestheader() 324 chunkdata = gen.manifestheader()
290 showchunks("manifest") 325 showchunks("manifest")
296 raise error.Abort(_('use debugbundle2 for this file')) 331 raise error.Abort(_('use debugbundle2 for this file'))
297 chunkdata = gen.changelogheader() 332 chunkdata = gen.changelogheader()
298 for deltadata in gen.deltaiter(): 333 for deltadata in gen.deltaiter():
299 node, p1, p2, cs, deltabase, delta, flags = deltadata 334 node, p1, p2, cs, deltabase, delta, flags = deltadata
300 ui.write("%s%s\n" % (indent_string, hex(node))) 335 ui.write("%s%s\n" % (indent_string, hex(node)))
336
301 337
302 def _debugobsmarkers(ui, part, indent=0, **opts): 338 def _debugobsmarkers(ui, part, indent=0, **opts):
303 """display version and markers contained in 'data'""" 339 """display version and markers contained in 'data'"""
304 opts = pycompat.byteskwargs(opts) 340 opts = pycompat.byteskwargs(opts)
305 data = part.read() 341 data = part.read()
320 fm.startitem() 356 fm.startitem()
321 fm.plain(indent_string) 357 fm.plain(indent_string)
322 cmdutil.showmarker(fm, m) 358 cmdutil.showmarker(fm, m)
323 fm.end() 359 fm.end()
324 360
361
325 def _debugphaseheads(ui, data, indent=0): 362 def _debugphaseheads(ui, data, indent=0):
326 """display version and markers contained in 'data'""" 363 """display version and markers contained in 'data'"""
327 indent_string = ' ' * indent 364 indent_string = ' ' * indent
328 headsbyphase = phases.binarydecode(data) 365 headsbyphase = phases.binarydecode(data)
329 for phase in phases.allphases: 366 for phase in phases.allphases:
330 for head in headsbyphase[phase]: 367 for head in headsbyphase[phase]:
331 ui.write(indent_string) 368 ui.write(indent_string)
332 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase])) 369 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
333 370
371
334 def _quasirepr(thing): 372 def _quasirepr(thing):
335 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)): 373 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
336 return '{%s}' % ( 374 return '{%s}' % (
337 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))) 375 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
376 )
338 return pycompat.bytestr(repr(thing)) 377 return pycompat.bytestr(repr(thing))
378
339 379
340 def _debugbundle2(ui, gen, all=None, **opts): 380 def _debugbundle2(ui, gen, all=None, **opts):
341 """lists the contents of a bundle2""" 381 """lists the contents of a bundle2"""
342 if not isinstance(gen, bundle2.unbundle20): 382 if not isinstance(gen, bundle2.unbundle20):
343 raise error.Abort(_('not a bundle2 file')) 383 raise error.Abort(_('not a bundle2 file'))
358 _debugobsmarkers(ui, part, indent=4, **opts) 398 _debugobsmarkers(ui, part, indent=4, **opts)
359 if part.type == 'phase-heads': 399 if part.type == 'phase-heads':
360 if not ui.quiet: 400 if not ui.quiet:
361 _debugphaseheads(ui, part, indent=4) 401 _debugphaseheads(ui, part, indent=4)
362 402
363 @command('debugbundle', 403
364 [('a', 'all', None, _('show all details')), 404 @command(
365 ('', 'part-type', [], _('show only the named part type')), 405 'debugbundle',
366 ('', 'spec', None, _('print the bundlespec of the bundle'))], 406 [
367 _('FILE'), 407 ('a', 'all', None, _('show all details')),
368 norepo=True) 408 ('', 'part-type', [], _('show only the named part type')),
409 ('', 'spec', None, _('print the bundlespec of the bundle')),
410 ],
411 _('FILE'),
412 norepo=True,
413 )
369 def debugbundle(ui, bundlepath, all=None, spec=None, **opts): 414 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
370 """lists the contents of a bundle""" 415 """lists the contents of a bundle"""
371 with hg.openpath(ui, bundlepath) as f: 416 with hg.openpath(ui, bundlepath) as f:
372 if spec: 417 if spec:
373 spec = exchange.getbundlespec(ui, f) 418 spec = exchange.getbundlespec(ui, f)
377 gen = exchange.readbundle(ui, f, bundlepath) 422 gen = exchange.readbundle(ui, f, bundlepath)
378 if isinstance(gen, bundle2.unbundle20): 423 if isinstance(gen, bundle2.unbundle20):
379 return _debugbundle2(ui, gen, all=all, **opts) 424 return _debugbundle2(ui, gen, all=all, **opts)
380 _debugchangegroup(ui, gen, all=all, **opts) 425 _debugchangegroup(ui, gen, all=all, **opts)
381 426
382 @command('debugcapabilities', 427
383 [], _('PATH'), 428 @command('debugcapabilities', [], _('PATH'), norepo=True)
384 norepo=True)
385 def debugcapabilities(ui, path, **opts): 429 def debugcapabilities(ui, path, **opts):
386 """lists the capabilities of a remote peer""" 430 """lists the capabilities of a remote peer"""
387 opts = pycompat.byteskwargs(opts) 431 opts = pycompat.byteskwargs(opts)
388 peer = hg.peer(ui, opts, path) 432 peer = hg.peer(ui, opts, path)
389 caps = peer.capabilities() 433 caps = peer.capabilities()
390 ui.write(('Main capabilities:\n')) 434 ui.write('Main capabilities:\n')
391 for c in sorted(caps): 435 for c in sorted(caps):
392 ui.write((' %s\n') % c) 436 ui.write(' %s\n' % c)
393 b2caps = bundle2.bundle2caps(peer) 437 b2caps = bundle2.bundle2caps(peer)
394 if b2caps: 438 if b2caps:
395 ui.write(('Bundle2 capabilities:\n')) 439 ui.write('Bundle2 capabilities:\n')
396 for key, values in sorted(b2caps.iteritems()): 440 for key, values in sorted(b2caps.iteritems()):
397 ui.write((' %s\n') % key) 441 ui.write(' %s\n' % key)
398 for v in values: 442 for v in values:
399 ui.write((' %s\n') % v) 443 ui.write(' %s\n' % v)
444
400 445
401 @command('debugcheckstate', [], '') 446 @command('debugcheckstate', [], '')
402 def debugcheckstate(ui, repo): 447 def debugcheckstate(ui, repo):
403 """validate the correctness of the current dirstate""" 448 """validate the correctness of the current dirstate"""
404 parent1, parent2 = repo.dirstate.parents() 449 parent1, parent2 = repo.dirstate.parents()
412 errors += 1 457 errors += 1
413 if state in "a" and f in m1: 458 if state in "a" and f in m1:
414 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state)) 459 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
415 errors += 1 460 errors += 1
416 if state in "m" and f not in m1 and f not in m2: 461 if state in "m" and f not in m1 and f not in m2:
417 ui.warn(_("%s in state %s, but not in either manifest\n") % 462 ui.warn(
418 (f, state)) 463 _("%s in state %s, but not in either manifest\n") % (f, state)
464 )
419 errors += 1 465 errors += 1
420 for f in m1: 466 for f in m1:
421 state = repo.dirstate[f] 467 state = repo.dirstate[f]
422 if state not in "nrm": 468 if state not in "nrm":
423 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state)) 469 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
424 errors += 1 470 errors += 1
425 if errors: 471 if errors:
426 error = _(".hg/dirstate inconsistent with current parent's manifest") 472 error = _(".hg/dirstate inconsistent with current parent's manifest")
427 raise error.Abort(error) 473 raise error.Abort(error)
428 474
429 @command('debugcolor', 475
430 [('', 'style', None, _('show all configured styles'))], 476 @command(
431 'hg debugcolor') 477 'debugcolor',
478 [('', 'style', None, _('show all configured styles'))],
479 'hg debugcolor',
480 )
432 def debugcolor(ui, repo, **opts): 481 def debugcolor(ui, repo, **opts):
433 """show available color, effects or style""" 482 """show available color, effects or style"""
434 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode)) 483 ui.write('color mode: %s\n' % stringutil.pprint(ui._colormode))
435 if opts.get(r'style'): 484 if opts.get(r'style'):
436 return _debugdisplaystyle(ui) 485 return _debugdisplaystyle(ui)
437 else: 486 else:
438 return _debugdisplaycolor(ui) 487 return _debugdisplaycolor(ui)
488
439 489
440 def _debugdisplaycolor(ui): 490 def _debugdisplaycolor(ui):
441 ui = ui.copy() 491 ui = ui.copy()
442 ui._styles.clear() 492 ui._styles.clear()
443 for effect in color._activeeffects(ui).keys(): 493 for effect in color._activeeffects(ui).keys():
448 ui._styles[k] = k[6:] 498 ui._styles[k] = k[6:]
449 elif k.startswith('terminfo.'): 499 elif k.startswith('terminfo.'):
450 ui._styles[k] = k[9:] 500 ui._styles[k] = k[9:]
451 ui.write(_('available colors:\n')) 501 ui.write(_('available colors:\n'))
452 # sort label with a '_' after the other to group '_background' entry. 502 # sort label with a '_' after the other to group '_background' entry.
453 items = sorted(ui._styles.items(), 503 items = sorted(ui._styles.items(), key=lambda i: ('_' in i[0], i[0], i[1]))
454 key=lambda i: ('_' in i[0], i[0], i[1]))
455 for colorname, label in items: 504 for colorname, label in items:
456 ui.write(('%s\n') % colorname, label=label) 505 ui.write('%s\n' % colorname, label=label)
506
457 507
458 def _debugdisplaystyle(ui): 508 def _debugdisplaystyle(ui):
459 ui.write(_('available style:\n')) 509 ui.write(_('available style:\n'))
460 if not ui._styles: 510 if not ui._styles:
461 return 511 return
467 ui.write(': ') 517 ui.write(': ')
468 ui.write(' ' * (max(0, width - len(label)))) 518 ui.write(' ' * (max(0, width - len(label))))
469 ui.write(', '.join(ui.label(e, e) for e in effects.split())) 519 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
470 ui.write('\n') 520 ui.write('\n')
471 521
522
472 @command('debugcreatestreamclonebundle', [], 'FILE') 523 @command('debugcreatestreamclonebundle', [], 'FILE')
473 def debugcreatestreamclonebundle(ui, repo, fname): 524 def debugcreatestreamclonebundle(ui, repo, fname):
474 """create a stream clone bundle file 525 """create a stream clone bundle file
475 526
476 Stream bundles are special bundles that are essentially archives of 527 Stream bundles are special bundles that are essentially archives of
477 revlog files. They are commonly used for cloning very quickly. 528 revlog files. They are commonly used for cloning very quickly.
478 """ 529 """
479 # TODO we may want to turn this into an abort when this functionality 530 # TODO we may want to turn this into an abort when this functionality
480 # is moved into `hg bundle`. 531 # is moved into `hg bundle`.
481 if phases.hassecret(repo): 532 if phases.hassecret(repo):
482 ui.warn(_('(warning: stream clone bundle will contain secret ' 533 ui.warn(
483 'revisions)\n')) 534 _(
535 '(warning: stream clone bundle will contain secret '
536 'revisions)\n'
537 )
538 )
484 539
485 requirements, gen = streamclone.generatebundlev1(repo) 540 requirements, gen = streamclone.generatebundlev1(repo)
486 changegroup.writechunks(ui, gen, fname) 541 changegroup.writechunks(ui, gen, fname)
487 542
488 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements))) 543 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
489 544
490 @command('debugdag', 545
491 [('t', 'tags', None, _('use tags as labels')), 546 @command(
492 ('b', 'branches', None, _('annotate with branch names')), 547 'debugdag',
493 ('', 'dots', None, _('use dots for runs')), 548 [
494 ('s', 'spaces', None, _('separate elements by spaces'))], 549 ('t', 'tags', None, _('use tags as labels')),
550 ('b', 'branches', None, _('annotate with branch names')),
551 ('', 'dots', None, _('use dots for runs')),
552 ('s', 'spaces', None, _('separate elements by spaces')),
553 ],
495 _('[OPTION]... [FILE [REV]...]'), 554 _('[OPTION]... [FILE [REV]...]'),
496 optionalrepo=True) 555 optionalrepo=True,
556 )
497 def debugdag(ui, repo, file_=None, *revs, **opts): 557 def debugdag(ui, repo, file_=None, *revs, **opts):
498 """format the changelog or an index DAG as a concise textual description 558 """format the changelog or an index DAG as a concise textual description
499 559
500 If you pass a revlog index, the revlog's DAG is emitted. If you list 560 If you pass a revlog index, the revlog's DAG is emitted. If you list
501 revision numbers, they get labeled in the output as rN. 561 revision numbers, they get labeled in the output as rN.
503 Otherwise, the changelog DAG of the current repo is emitted. 563 Otherwise, the changelog DAG of the current repo is emitted.
504 """ 564 """
505 spaces = opts.get(r'spaces') 565 spaces = opts.get(r'spaces')
506 dots = opts.get(r'dots') 566 dots = opts.get(r'dots')
507 if file_: 567 if file_:
508 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), 568 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
509 file_)
510 revs = set((int(r) for r in revs)) 569 revs = set((int(r) for r in revs))
570
511 def events(): 571 def events():
512 for r in rlog: 572 for r in rlog:
513 yield 'n', (r, list(p for p in rlog.parentrevs(r) 573 yield 'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
514 if p != -1))
515 if r in revs: 574 if r in revs:
516 yield 'l', (r, "r%i" % r) 575 yield 'l', (r, "r%i" % r)
576
517 elif repo: 577 elif repo:
518 cl = repo.changelog 578 cl = repo.changelog
519 tags = opts.get(r'tags') 579 tags = opts.get(r'tags')
520 branches = opts.get(r'branches') 580 branches = opts.get(r'branches')
521 if tags: 581 if tags:
522 labels = {} 582 labels = {}
523 for l, n in repo.tags().items(): 583 for l, n in repo.tags().items():
524 labels.setdefault(cl.rev(n), []).append(l) 584 labels.setdefault(cl.rev(n), []).append(l)
585
525 def events(): 586 def events():
526 b = "default" 587 b = "default"
527 for r in cl: 588 for r in cl:
528 if branches: 589 if branches:
529 newb = cl.read(cl.node(r))[5]['branch'] 590 newb = cl.read(cl.node(r))[5]['branch']
530 if newb != b: 591 if newb != b:
531 yield 'a', newb 592 yield 'a', newb
532 b = newb 593 b = newb
533 yield 'n', (r, list(p for p in cl.parentrevs(r) 594 yield 'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
534 if p != -1))
535 if tags: 595 if tags:
536 ls = labels.get(r) 596 ls = labels.get(r)
537 if ls: 597 if ls:
538 for l in ls: 598 for l in ls:
539 yield 'l', (r, l) 599 yield 'l', (r, l)
600
540 else: 601 else:
541 raise error.Abort(_('need repo for changelog dag')) 602 raise error.Abort(_('need repo for changelog dag'))
542 603
543 for line in dagparser.dagtextlines(events(), 604 for line in dagparser.dagtextlines(
544 addspaces=spaces, 605 events(),
545 wraplabels=True, 606 addspaces=spaces,
546 wrapannotations=True, 607 wraplabels=True,
547 wrapnonlinear=dots, 608 wrapannotations=True,
548 usedots=dots, 609 wrapnonlinear=dots,
549 maxlinewidth=70): 610 usedots=dots,
611 maxlinewidth=70,
612 ):
550 ui.write(line) 613 ui.write(line)
551 ui.write("\n") 614 ui.write("\n")
615
552 616
553 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV')) 617 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
554 def debugdata(ui, repo, file_, rev=None, **opts): 618 def debugdata(ui, repo, file_, rev=None, **opts):
555 """dump the contents of a data file revision""" 619 """dump the contents of a data file revision"""
556 opts = pycompat.byteskwargs(opts) 620 opts = pycompat.byteskwargs(opts)
564 try: 628 try:
565 ui.write(r.rawdata(r.lookup(rev))) 629 ui.write(r.rawdata(r.lookup(rev)))
566 except KeyError: 630 except KeyError:
567 raise error.Abort(_('invalid revision identifier %s') % rev) 631 raise error.Abort(_('invalid revision identifier %s') % rev)
568 632
569 @command('debugdate', 633
634 @command(
635 'debugdate',
570 [('e', 'extended', None, _('try extended date formats'))], 636 [('e', 'extended', None, _('try extended date formats'))],
571 _('[-e] DATE [RANGE]'), 637 _('[-e] DATE [RANGE]'),
572 norepo=True, optionalrepo=True) 638 norepo=True,
639 optionalrepo=True,
640 )
573 def debugdate(ui, date, range=None, **opts): 641 def debugdate(ui, date, range=None, **opts):
574 """parse and display a date""" 642 """parse and display a date"""
575 if opts[r"extended"]: 643 if opts[r"extended"]:
576 d = dateutil.parsedate(date, util.extendeddateformats) 644 d = dateutil.parsedate(date, util.extendeddateformats)
577 else: 645 else:
578 d = dateutil.parsedate(date) 646 d = dateutil.parsedate(date)
579 ui.write(("internal: %d %d\n") % d) 647 ui.write("internal: %d %d\n" % d)
580 ui.write(("standard: %s\n") % dateutil.datestr(d)) 648 ui.write("standard: %s\n" % dateutil.datestr(d))
581 if range: 649 if range:
582 m = dateutil.matchdate(range) 650 m = dateutil.matchdate(range)
583 ui.write(("match: %s\n") % m(d[0])) 651 ui.write("match: %s\n" % m(d[0]))
584 652
585 @command('debugdeltachain', 653
654 @command(
655 'debugdeltachain',
586 cmdutil.debugrevlogopts + cmdutil.formatteropts, 656 cmdutil.debugrevlogopts + cmdutil.formatteropts,
587 _('-c|-m|FILE'), 657 _('-c|-m|FILE'),
588 optionalrepo=True) 658 optionalrepo=True,
659 )
589 def debugdeltachain(ui, repo, file_=None, **opts): 660 def debugdeltachain(ui, repo, file_=None, **opts):
590 """dump information about delta chains in a revlog 661 """dump information about delta chains in a revlog
591 662
592 Output can be templatized. Available template keywords are: 663 Output can be templatized. Available template keywords are:
593 664
659 730
660 return compsize, uncompsize, deltatype, chain, chainsize 731 return compsize, uncompsize, deltatype, chain, chainsize
661 732
662 fm = ui.formatter('debugdeltachain', opts) 733 fm = ui.formatter('debugdeltachain', opts)
663 734
664 fm.plain(' rev chain# chainlen prev delta ' 735 fm.plain(
665 'size rawsize chainsize ratio lindist extradist ' 736 ' rev chain# chainlen prev delta '
666 'extraratio') 737 'size rawsize chainsize ratio lindist extradist '
738 'extraratio'
739 )
667 if withsparseread: 740 if withsparseread:
668 fm.plain(' readsize largestblk rddensity srchunks') 741 fm.plain(' readsize largestblk rddensity srchunks')
669 fm.plain('\n') 742 fm.plain('\n')
670 743
671 chainbases = {} 744 chainbases = {}
691 extraratio = float(extradist) / float(chainsize) 764 extraratio = float(extradist) / float(chainsize)
692 else: 765 else:
693 extraratio = extradist 766 extraratio = extradist
694 767
695 fm.startitem() 768 fm.startitem()
696 fm.write('rev chainid chainlen prevrev deltatype compsize ' 769 fm.write(
697 'uncompsize chainsize chainratio lindist extradist ' 770 'rev chainid chainlen prevrev deltatype compsize '
698 'extraratio', 771 'uncompsize chainsize chainratio lindist extradist '
699 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f', 772 'extraratio',
700 rev, chainid, len(chain), prevrev, deltatype, comp, 773 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
701 uncomp, chainsize, chainratio, lineardist, extradist, 774 rev,
702 extraratio, 775 chainid,
703 rev=rev, chainid=chainid, chainlen=len(chain), 776 len(chain),
704 prevrev=prevrev, deltatype=deltatype, compsize=comp, 777 prevrev,
705 uncompsize=uncomp, chainsize=chainsize, 778 deltatype,
706 chainratio=chainratio, lindist=lineardist, 779 comp,
707 extradist=extradist, extraratio=extraratio) 780 uncomp,
781 chainsize,
782 chainratio,
783 lineardist,
784 extradist,
785 extraratio,
786 rev=rev,
787 chainid=chainid,
788 chainlen=len(chain),
789 prevrev=prevrev,
790 deltatype=deltatype,
791 compsize=comp,
792 uncompsize=uncomp,
793 chainsize=chainsize,
794 chainratio=chainratio,
795 lindist=lineardist,
796 extradist=extradist,
797 extraratio=extraratio,
798 )
708 if withsparseread: 799 if withsparseread:
709 readsize = 0 800 readsize = 0
710 largestblock = 0 801 largestblock = 0
711 srchunks = 0 802 srchunks = 0
712 803
722 if readsize: 813 if readsize:
723 readdensity = float(chainsize) / float(readsize) 814 readdensity = float(chainsize) / float(readsize)
724 else: 815 else:
725 readdensity = 1 816 readdensity = 1
726 817
727 fm.write('readsize largestblock readdensity srchunks', 818 fm.write(
728 ' %10d %10d %9.5f %8d', 819 'readsize largestblock readdensity srchunks',
729 readsize, largestblock, readdensity, srchunks, 820 ' %10d %10d %9.5f %8d',
730 readsize=readsize, largestblock=largestblock, 821 readsize,
731 readdensity=readdensity, srchunks=srchunks) 822 largestblock,
823 readdensity,
824 srchunks,
825 readsize=readsize,
826 largestblock=largestblock,
827 readdensity=readdensity,
828 srchunks=srchunks,
829 )
732 830
733 fm.plain('\n') 831 fm.plain('\n')
734 832
735 fm.end() 833 fm.end()
736 834
737 @command('debugdirstate|debugstate', 835
738 [('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')), 836 @command(
739 ('', 'dates', True, _('display the saved mtime')), 837 'debugdirstate|debugstate',
740 ('', 'datesort', None, _('sort by saved mtime'))], 838 [
741 _('[OPTION]...')) 839 ('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')),
840 ('', 'dates', True, _('display the saved mtime')),
841 ('', 'datesort', None, _('sort by saved mtime')),
842 ],
843 _('[OPTION]...'),
844 )
742 def debugstate(ui, repo, **opts): 845 def debugstate(ui, repo, **opts):
743 """show the contents of the current dirstate""" 846 """show the contents of the current dirstate"""
744 847
745 nodates = not opts[r'dates'] 848 nodates = not opts[r'dates']
746 if opts.get(r'nodates') is not None: 849 if opts.get(r'nodates') is not None:
747 nodates = True 850 nodates = True
748 datesort = opts.get(r'datesort') 851 datesort = opts.get(r'datesort')
749 852
750 if datesort: 853 if datesort:
751 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename 854 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
752 else: 855 else:
753 keyfunc = None # sort by filename 856 keyfunc = None # sort by filename
754 for file_, ent in sorted(repo.dirstate.iteritems(), key=keyfunc): 857 for file_, ent in sorted(repo.dirstate.iteritems(), key=keyfunc):
755 if ent[3] == -1: 858 if ent[3] == -1:
756 timestr = 'unset ' 859 timestr = 'unset '
757 elif nodates: 860 elif nodates:
758 timestr = 'set ' 861 timestr = 'set '
759 else: 862 else:
760 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ", 863 timestr = time.strftime(
761 time.localtime(ent[3])) 864 r"%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
865 )
762 timestr = encoding.strtolocal(timestr) 866 timestr = encoding.strtolocal(timestr)
763 if ent[1] & 0o20000: 867 if ent[1] & 0o20000:
764 mode = 'lnk' 868 mode = 'lnk'
765 else: 869 else:
766 mode = '%3o' % (ent[1] & 0o777 & ~util.umask) 870 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
767 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_)) 871 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
768 for f in repo.dirstate.copies(): 872 for f in repo.dirstate.copies():
769 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f)) 873 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
770 874
771 @command('debugdiscovery', 875
772 [('', 'old', None, _('use old-style discovery')), 876 @command(
773 ('', 'nonheads', None, 877 'debugdiscovery',
774 _('use old-style discovery with non-heads included')), 878 [
775 ('', 'rev', [], 'restrict discovery to this set of revs'), 879 ('', 'old', None, _('use old-style discovery')),
776 ('', 'seed', '12323', 'specify the random seed use for discovery'), 880 (
777 ] + cmdutil.remoteopts, 881 '',
778 _('[--rev REV] [OTHER]')) 882 'nonheads',
883 None,
884 _('use old-style discovery with non-heads included'),
885 ),
886 ('', 'rev', [], 'restrict discovery to this set of revs'),
887 ('', 'seed', '12323', 'specify the random seed use for discovery'),
888 ]
889 + cmdutil.remoteopts,
890 _('[--rev REV] [OTHER]'),
891 )
779 def debugdiscovery(ui, repo, remoteurl="default", **opts): 892 def debugdiscovery(ui, repo, remoteurl="default", **opts):
780 """runs the changeset discovery protocol in isolation""" 893 """runs the changeset discovery protocol in isolation"""
781 opts = pycompat.byteskwargs(opts) 894 opts = pycompat.byteskwargs(opts)
782 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl)) 895 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
783 remote = hg.peer(repo, opts, remoteurl) 896 remote = hg.peer(repo, opts, remoteurl)
784 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl)) 897 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
785 898
786 # make sure tests are repeatable 899 # make sure tests are repeatable
787 random.seed(int(opts['seed'])) 900 random.seed(int(opts['seed']))
788 901
789
790
791 if opts.get('old'): 902 if opts.get('old'):
903
792 def doit(pushedrevs, remoteheads, remote=remote): 904 def doit(pushedrevs, remoteheads, remote=remote):
793 if not util.safehasattr(remote, 'branches'): 905 if not util.safehasattr(remote, 'branches'):
794 # enable in-client legacy support 906 # enable in-client legacy support
795 remote = localrepo.locallegacypeer(remote.local()) 907 remote = localrepo.locallegacypeer(remote.local())
796 common, _in, hds = treediscovery.findcommonincoming(repo, remote, 908 common, _in, hds = treediscovery.findcommonincoming(
797 force=True) 909 repo, remote, force=True
910 )
798 common = set(common) 911 common = set(common)
799 if not opts.get('nonheads'): 912 if not opts.get('nonheads'):
800 ui.write(("unpruned common: %s\n") % 913 ui.write(
801 " ".join(sorted(short(n) for n in common))) 914 "unpruned common: %s\n"
915 % " ".join(sorted(short(n) for n in common))
916 )
802 917
803 clnode = repo.changelog.node 918 clnode = repo.changelog.node
804 common = repo.revs('heads(::%ln)', common) 919 common = repo.revs('heads(::%ln)', common)
805 common = {clnode(r) for r in common} 920 common = {clnode(r) for r in common}
806 return common, hds 921 return common, hds
922
807 else: 923 else:
924
808 def doit(pushedrevs, remoteheads, remote=remote): 925 def doit(pushedrevs, remoteheads, remote=remote):
809 nodes = None 926 nodes = None
810 if pushedrevs: 927 if pushedrevs:
811 revs = scmutil.revrange(repo, pushedrevs) 928 revs = scmutil.revrange(repo, pushedrevs)
812 nodes = [repo[r].node() for r in revs] 929 nodes = [repo[r].node() for r in revs]
813 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote, 930 common, any, hds = setdiscovery.findcommonheads(
814 ancestorsof=nodes) 931 ui, repo, remote, ancestorsof=nodes
932 )
815 return common, hds 933 return common, hds
816 934
817 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None) 935 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
818 localrevs = opts['rev'] 936 localrevs = opts['rev']
819 with util.timedcm('debug-discovery') as t: 937 with util.timedcm('debug-discovery') as t:
837 data['nb-revs'] = len(repo.revs('all()')) 955 data['nb-revs'] = len(repo.revs('all()'))
838 data['nb-revs-common'] = len(repo.revs('::%ln', common)) 956 data['nb-revs-common'] = len(repo.revs('::%ln', common))
839 data['nb-revs-missing'] = data['nb-revs'] - data['nb-revs-common'] 957 data['nb-revs-missing'] = data['nb-revs'] - data['nb-revs-common']
840 958
841 # display discovery summary 959 # display discovery summary
842 ui.write(("elapsed time: %(elapsed)f seconds\n") % data) 960 ui.write("elapsed time: %(elapsed)f seconds\n" % data)
843 ui.write(("heads summary:\n")) 961 ui.write("heads summary:\n")
844 ui.write((" total common heads: %(nb-common)9d\n") % data) 962 ui.write(" total common heads: %(nb-common)9d\n" % data)
845 ui.write((" also local heads: %(nb-common-local)9d\n") % data) 963 ui.write(" also local heads: %(nb-common-local)9d\n" % data)
846 ui.write((" also remote heads: %(nb-common-remote)9d\n") % data) 964 ui.write(" also remote heads: %(nb-common-remote)9d\n" % data)
847 ui.write((" both: %(nb-common-both)9d\n") % data) 965 ui.write(" both: %(nb-common-both)9d\n" % data)
848 ui.write((" local heads: %(nb-local)9d\n") % data) 966 ui.write(" local heads: %(nb-local)9d\n" % data)
849 ui.write((" common: %(nb-common-local)9d\n") % data) 967 ui.write(" common: %(nb-common-local)9d\n" % data)
850 ui.write((" missing: %(nb-local-missing)9d\n") % data) 968 ui.write(" missing: %(nb-local-missing)9d\n" % data)
851 ui.write((" remote heads: %(nb-remote)9d\n") % data) 969 ui.write(" remote heads: %(nb-remote)9d\n" % data)
852 ui.write((" common: %(nb-common-remote)9d\n") % data) 970 ui.write(" common: %(nb-common-remote)9d\n" % data)
853 ui.write((" unknown: %(nb-remote-unknown)9d\n") % data) 971 ui.write(" unknown: %(nb-remote-unknown)9d\n" % data)
854 ui.write(("local changesets: %(nb-revs)9d\n") % data) 972 ui.write("local changesets: %(nb-revs)9d\n" % data)
855 ui.write((" common: %(nb-revs-common)9d\n") % data) 973 ui.write(" common: %(nb-revs-common)9d\n" % data)
856 ui.write((" missing: %(nb-revs-missing)9d\n") % data) 974 ui.write(" missing: %(nb-revs-missing)9d\n" % data)
857 975
858 if ui.verbose: 976 if ui.verbose:
859 ui.write(("common heads: %s\n") % 977 ui.write(
860 " ".join(sorted(short(n) for n in common))) 978 "common heads: %s\n" % " ".join(sorted(short(n) for n in common))
979 )
980
861 981
862 _chunksize = 4 << 10 982 _chunksize = 4 << 10
863 983
864 @command('debugdownload', 984
865 [ 985 @command('debugdownload', [('o', 'output', '', _('path')),], optionalrepo=True)
866 ('o', 'output', '', _('path')),
867 ],
868 optionalrepo=True)
869 def debugdownload(ui, repo, url, output=None, **opts): 986 def debugdownload(ui, repo, url, output=None, **opts):
870 """download a resource using Mercurial logic and config 987 """download a resource using Mercurial logic and config
871 """ 988 """
872 fh = urlmod.open(ui, url, output) 989 fh = urlmod.open(ui, url, output)
873 990
880 dest.write(data) 997 dest.write(data)
881 data = fh.read(_chunksize) 998 data = fh.read(_chunksize)
882 finally: 999 finally:
883 if output: 1000 if output:
884 dest.close() 1001 dest.close()
1002
885 1003
886 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True) 1004 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
887 def debugextensions(ui, repo, **opts): 1005 def debugextensions(ui, repo, **opts):
888 '''show information about active extensions''' 1006 '''show information about active extensions'''
889 opts = pycompat.byteskwargs(opts) 1007 opts = pycompat.byteskwargs(opts)
911 fm.plain(_(' (untested!)\n')) 1029 fm.plain(_(' (untested!)\n'))
912 else: 1030 else:
913 lasttestedversion = exttestedwith[-1] 1031 lasttestedversion = exttestedwith[-1]
914 fm.plain(' (%s!)\n' % lasttestedversion) 1032 fm.plain(' (%s!)\n' % lasttestedversion)
915 1033
916 fm.condwrite(ui.verbose and extsource, 'source', 1034 fm.condwrite(
917 _(' location: %s\n'), extsource or "") 1035 ui.verbose and extsource,
1036 'source',
1037 _(' location: %s\n'),
1038 extsource or "",
1039 )
918 1040
919 if ui.verbose: 1041 if ui.verbose:
920 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal]) 1042 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
921 fm.data(bundled=isinternal) 1043 fm.data(bundled=isinternal)
922 1044
923 fm.condwrite(ui.verbose and exttestedwith, 'testedwith', 1045 fm.condwrite(
924 _(' tested with: %s\n'), 1046 ui.verbose and exttestedwith,
925 fm.formatlist(exttestedwith, name='ver')) 1047 'testedwith',
926 1048 _(' tested with: %s\n'),
927 fm.condwrite(ui.verbose and extbuglink, 'buglink', 1049 fm.formatlist(exttestedwith, name='ver'),
928 _(' bug reporting: %s\n'), extbuglink or "") 1050 )
1051
1052 fm.condwrite(
1053 ui.verbose and extbuglink,
1054 'buglink',
1055 _(' bug reporting: %s\n'),
1056 extbuglink or "",
1057 )
929 1058
930 fm.end() 1059 fm.end()
931 1060
932 @command('debugfileset', 1061
933 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')), 1062 @command(
934 ('', 'all-files', False, 1063 'debugfileset',
935 _('test files from all revisions and working directory')), 1064 [
936 ('s', 'show-matcher', None, 1065 ('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
937 _('print internal representation of matcher')), 1066 (
938 ('p', 'show-stage', [], 1067 '',
939 _('print parsed tree at the given stage'), _('NAME'))], 1068 'all-files',
940 _('[-r REV] [--all-files] [OPTION]... FILESPEC')) 1069 False,
1070 _('test files from all revisions and working directory'),
1071 ),
1072 (
1073 's',
1074 'show-matcher',
1075 None,
1076 _('print internal representation of matcher'),
1077 ),
1078 (
1079 'p',
1080 'show-stage',
1081 [],
1082 _('print parsed tree at the given stage'),
1083 _('NAME'),
1084 ),
1085 ],
1086 _('[-r REV] [--all-files] [OPTION]... FILESPEC'),
1087 )
941 def debugfileset(ui, repo, expr, **opts): 1088 def debugfileset(ui, repo, expr, **opts):
942 '''parse and apply a fileset specification''' 1089 '''parse and apply a fileset specification'''
943 from . import fileset 1090 from . import fileset
944 fileset.symbols # force import of fileset so we have predicates to optimize 1091
1092 fileset.symbols # force import of fileset so we have predicates to optimize
945 opts = pycompat.byteskwargs(opts) 1093 opts = pycompat.byteskwargs(opts)
946 ctx = scmutil.revsingle(repo, opts.get('rev'), None) 1094 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
947 1095
948 stages = [ 1096 stages = [
949 ('parsed', pycompat.identity), 1097 ('parsed', pycompat.identity),
967 tree = filesetlang.parse(expr) 1115 tree = filesetlang.parse(expr)
968 for n, f in stages: 1116 for n, f in stages:
969 tree = f(tree) 1117 tree = f(tree)
970 if n in showalways: 1118 if n in showalways:
971 if opts['show_stage'] or n != 'parsed': 1119 if opts['show_stage'] or n != 'parsed':
972 ui.write(("* %s:\n") % n) 1120 ui.write("* %s:\n" % n)
973 ui.write(filesetlang.prettyformat(tree), "\n") 1121 ui.write(filesetlang.prettyformat(tree), "\n")
974 1122
975 files = set() 1123 files = set()
976 if opts['all_files']: 1124 if opts['all_files']:
977 for r in repo: 1125 for r in repo:
978 c = repo[r] 1126 c = repo[r]
979 files.update(c.files()) 1127 files.update(c.files())
980 files.update(c.substate) 1128 files.update(c.substate)
981 if opts['all_files'] or ctx.rev() is None: 1129 if opts['all_files'] or ctx.rev() is None:
982 wctx = repo[None] 1130 wctx = repo[None]
983 files.update(repo.dirstate.walk(scmutil.matchall(repo), 1131 files.update(
984 subrepos=list(wctx.substate), 1132 repo.dirstate.walk(
985 unknown=True, ignored=True)) 1133 scmutil.matchall(repo),
1134 subrepos=list(wctx.substate),
1135 unknown=True,
1136 ignored=True,
1137 )
1138 )
986 files.update(wctx.substate) 1139 files.update(wctx.substate)
987 else: 1140 else:
988 files.update(ctx.files()) 1141 files.update(ctx.files())
989 files.update(ctx.substate) 1142 files.update(ctx.substate)
990 1143
991 m = ctx.matchfileset(expr) 1144 m = ctx.matchfileset(expr)
992 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose): 1145 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
993 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n') 1146 ui.write('* matcher:\n', stringutil.prettyrepr(m), '\n')
994 for f in sorted(files): 1147 for f in sorted(files):
995 if not m(f): 1148 if not m(f):
996 continue 1149 continue
997 ui.write("%s\n" % f) 1150 ui.write("%s\n" % f)
998 1151
999 @command('debugformat', 1152
1000 [] + cmdutil.formatteropts) 1153 @command('debugformat', [] + cmdutil.formatteropts)
1001 def debugformat(ui, repo, **opts): 1154 def debugformat(ui, repo, **opts):
1002 """display format information about the current repository 1155 """display format information about the current repository
1003 1156
1004 Use --verbose to get extra information about current config value and 1157 Use --verbose to get extra information about current config value and
1005 Mercurial default.""" 1158 Mercurial default."""
1010 def makeformatname(name): 1163 def makeformatname(name):
1011 return '%s:' + (' ' * (maxvariantlength - len(name))) 1164 return '%s:' + (' ' * (maxvariantlength - len(name)))
1012 1165
1013 fm = ui.formatter('debugformat', opts) 1166 fm = ui.formatter('debugformat', opts)
1014 if fm.isplain(): 1167 if fm.isplain():
1168
1015 def formatvalue(value): 1169 def formatvalue(value):
1016 if util.safehasattr(value, 'startswith'): 1170 if util.safehasattr(value, 'startswith'):
1017 return value 1171 return value
1018 if value: 1172 if value:
1019 return 'yes' 1173 return 'yes'
1020 else: 1174 else:
1021 return 'no' 1175 return 'no'
1176
1022 else: 1177 else:
1023 formatvalue = pycompat.identity 1178 formatvalue = pycompat.identity
1024 1179
1025 fm.plain('format-variant') 1180 fm.plain('format-variant')
1026 fm.plain(' ' * (maxvariantlength - len('format-variant'))) 1181 fm.plain(' ' * (maxvariantlength - len('format-variant')))
1041 repolabel = 'formatvariant.repo.mismatchdefault' 1196 repolabel = 'formatvariant.repo.mismatchdefault'
1042 else: 1197 else:
1043 namelabel = 'formatvariant.name.uptodate' 1198 namelabel = 'formatvariant.name.uptodate'
1044 repolabel = 'formatvariant.repo.uptodate' 1199 repolabel = 'formatvariant.repo.uptodate'
1045 1200
1046 fm.write('name', makeformatname(fv.name), fv.name, 1201 fm.write('name', makeformatname(fv.name), fv.name, label=namelabel)
1047 label=namelabel) 1202 fm.write('repo', ' %3s', formatvalue(repovalue), label=repolabel)
1048 fm.write('repo', ' %3s', formatvalue(repovalue),
1049 label=repolabel)
1050 if fv.default != configvalue: 1203 if fv.default != configvalue:
1051 configlabel = 'formatvariant.config.special' 1204 configlabel = 'formatvariant.config.special'
1052 else: 1205 else:
1053 configlabel = 'formatvariant.config.default' 1206 configlabel = 'formatvariant.config.default'
1054 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue), 1207 fm.condwrite(
1055 label=configlabel) 1208 ui.verbose,
1056 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default), 1209 'config',
1057 label='formatvariant.default') 1210 ' %6s',
1211 formatvalue(configvalue),
1212 label=configlabel,
1213 )
1214 fm.condwrite(
1215 ui.verbose,
1216 'default',
1217 ' %7s',
1218 formatvalue(fv.default),
1219 label='formatvariant.default',
1220 )
1058 fm.plain('\n') 1221 fm.plain('\n')
1059 fm.end() 1222 fm.end()
1223
1060 1224
1061 @command('debugfsinfo', [], _('[PATH]'), norepo=True) 1225 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1062 def debugfsinfo(ui, path="."): 1226 def debugfsinfo(ui, path="."):
1063 """show information detected about current filesystem""" 1227 """show information detected about current filesystem"""
1064 ui.write(('path: %s\n') % path) 1228 ui.write('path: %s\n' % path)
1065 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)')) 1229 ui.write('mounted on: %s\n' % (util.getfsmountpoint(path) or '(unknown)'))
1066 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no')) 1230 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1067 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)')) 1231 ui.write('fstype: %s\n' % (util.getfstype(path) or '(unknown)'))
1068 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no')) 1232 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1069 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no')) 1233 ui.write('hardlink: %s\n' % (util.checknlink(path) and 'yes' or 'no'))
1070 casesensitive = '(unknown)' 1234 casesensitive = '(unknown)'
1071 try: 1235 try:
1072 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f: 1236 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
1073 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no' 1237 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
1074 except OSError: 1238 except OSError:
1075 pass 1239 pass
1076 ui.write(('case-sensitive: %s\n') % casesensitive) 1240 ui.write('case-sensitive: %s\n' % casesensitive)
1077 1241
1078 @command('debuggetbundle', 1242
1079 [('H', 'head', [], _('id of head node'), _('ID')), 1243 @command(
1080 ('C', 'common', [], _('id of common node'), _('ID')), 1244 'debuggetbundle',
1081 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))], 1245 [
1246 ('H', 'head', [], _('id of head node'), _('ID')),
1247 ('C', 'common', [], _('id of common node'), _('ID')),
1248 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1249 ],
1082 _('REPO FILE [-H|-C ID]...'), 1250 _('REPO FILE [-H|-C ID]...'),
1083 norepo=True) 1251 norepo=True,
1252 )
1084 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts): 1253 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1085 """retrieves a bundle from a repo 1254 """retrieves a bundle from a repo
1086 1255
1087 Every ID must be a full-length hex node id string. Saves the bundle to the 1256 Every ID must be a full-length hex node id string. Saves the bundle to the
1088 given file. 1257 given file.
1099 # TODO: get desired bundlecaps from command line. 1268 # TODO: get desired bundlecaps from command line.
1100 args[r'bundlecaps'] = None 1269 args[r'bundlecaps'] = None
1101 bundle = repo.getbundle('debug', **args) 1270 bundle = repo.getbundle('debug', **args)
1102 1271
1103 bundletype = opts.get('type', 'bzip2').lower() 1272 bundletype = opts.get('type', 'bzip2').lower()
1104 btypes = {'none': 'HG10UN', 1273 btypes = {
1105 'bzip2': 'HG10BZ', 1274 'none': 'HG10UN',
1106 'gzip': 'HG10GZ', 1275 'bzip2': 'HG10BZ',
1107 'bundle2': 'HG20'} 1276 'gzip': 'HG10GZ',
1277 'bundle2': 'HG20',
1278 }
1108 bundletype = btypes.get(bundletype) 1279 bundletype = btypes.get(bundletype)
1109 if bundletype not in bundle2.bundletypes: 1280 if bundletype not in bundle2.bundletypes:
1110 raise error.Abort(_('unknown bundle type specified with --type')) 1281 raise error.Abort(_('unknown bundle type specified with --type'))
1111 bundle2.writebundle(ui, bundle, bundlepath, bundletype) 1282 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1283
1112 1284
1113 @command('debugignore', [], '[FILE]') 1285 @command('debugignore', [], '[FILE]')
1114 def debugignore(ui, repo, *files, **opts): 1286 def debugignore(ui, repo, *files, **opts):
1115 """display the combined ignore pattern and information about ignored files 1287 """display the combined ignore pattern and information about ignored files
1116 1288
1142 break 1314 break
1143 if ignored: 1315 if ignored:
1144 if ignored == nf: 1316 if ignored == nf:
1145 ui.write(_("%s is ignored\n") % uipathfn(f)) 1317 ui.write(_("%s is ignored\n") % uipathfn(f))
1146 else: 1318 else:
1147 ui.write(_("%s is ignored because of " 1319 ui.write(
1148 "containing directory %s\n") 1320 _(
1149 % (uipathfn(f), ignored)) 1321 "%s is ignored because of "
1322 "containing directory %s\n"
1323 )
1324 % (uipathfn(f), ignored)
1325 )
1150 ignorefile, lineno, line = ignoredata 1326 ignorefile, lineno, line = ignoredata
1151 ui.write(_("(ignore rule in %s, line %d: '%s')\n") 1327 ui.write(
1152 % (ignorefile, lineno, line)) 1328 _("(ignore rule in %s, line %d: '%s')\n")
1329 % (ignorefile, lineno, line)
1330 )
1153 else: 1331 else:
1154 ui.write(_("%s is not ignored\n") % uipathfn(f)) 1332 ui.write(_("%s is not ignored\n") % uipathfn(f))
1155 1333
1156 @command('debugindex', cmdutil.debugrevlogopts + cmdutil.formatteropts, 1334
1157 _('-c|-m|FILE')) 1335 @command(
1336 'debugindex',
1337 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1338 _('-c|-m|FILE'),
1339 )
1158 def debugindex(ui, repo, file_=None, **opts): 1340 def debugindex(ui, repo, file_=None, **opts):
1159 """dump index data for a storage primitive""" 1341 """dump index data for a storage primitive"""
1160 opts = pycompat.byteskwargs(opts) 1342 opts = pycompat.byteskwargs(opts)
1161 store = cmdutil.openstorage(repo, 'debugindex', file_, opts) 1343 store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
1162 1344
1169 for i in store: 1351 for i in store:
1170 idlen = len(shortfn(store.node(i))) 1352 idlen = len(shortfn(store.node(i)))
1171 break 1353 break
1172 1354
1173 fm = ui.formatter('debugindex', opts) 1355 fm = ui.formatter('debugindex', opts)
1174 fm.plain(b' rev linkrev %s %s p2\n' % ( 1356 fm.plain(
1175 b'nodeid'.ljust(idlen), 1357 b' rev linkrev %s %s p2\n'
1176 b'p1'.ljust(idlen))) 1358 % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
1359 )
1177 1360
1178 for rev in store: 1361 for rev in store:
1179 node = store.node(rev) 1362 node = store.node(rev)
1180 parents = store.parents(node) 1363 parents = store.parents(node)
1181 1364
1187 fm.write(b'p2', '%s', shortfn(parents[1])) 1370 fm.write(b'p2', '%s', shortfn(parents[1]))
1188 fm.plain(b'\n') 1371 fm.plain(b'\n')
1189 1372
1190 fm.end() 1373 fm.end()
1191 1374
1192 @command('debugindexdot', cmdutil.debugrevlogopts, 1375
1193 _('-c|-m|FILE'), optionalrepo=True) 1376 @command(
1377 'debugindexdot', cmdutil.debugrevlogopts, _('-c|-m|FILE'), optionalrepo=True
1378 )
1194 def debugindexdot(ui, repo, file_=None, **opts): 1379 def debugindexdot(ui, repo, file_=None, **opts):
1195 """dump an index DAG as a graphviz dot file""" 1380 """dump an index DAG as a graphviz dot file"""
1196 opts = pycompat.byteskwargs(opts) 1381 opts = pycompat.byteskwargs(opts)
1197 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts) 1382 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
1198 ui.write(("digraph G {\n")) 1383 ui.write("digraph G {\n")
1199 for i in r: 1384 for i in r:
1200 node = r.node(i) 1385 node = r.node(i)
1201 pp = r.parents(node) 1386 pp = r.parents(node)
1202 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i)) 1387 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1203 if pp[1] != nullid: 1388 if pp[1] != nullid:
1204 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i)) 1389 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1205 ui.write("}\n") 1390 ui.write("}\n")
1391
1206 1392
1207 @command('debugindexstats', []) 1393 @command('debugindexstats', [])
1208 def debugindexstats(ui, repo): 1394 def debugindexstats(ui, repo):
1209 """show stats related to the changelog index""" 1395 """show stats related to the changelog index"""
1210 repo.changelog.shortest(nullid, 1) 1396 repo.changelog.shortest(nullid, 1)
1212 if not util.safehasattr(index, 'stats'): 1398 if not util.safehasattr(index, 'stats'):
1213 raise error.Abort(_('debugindexstats only works with native code')) 1399 raise error.Abort(_('debugindexstats only works with native code'))
1214 for k, v in sorted(index.stats().items()): 1400 for k, v in sorted(index.stats().items()):
1215 ui.write('%s: %d\n' % (k, v)) 1401 ui.write('%s: %d\n' % (k, v))
1216 1402
1403
1217 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True) 1404 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1218 def debuginstall(ui, **opts): 1405 def debuginstall(ui, **opts):
1219 '''test Mercurial installation 1406 '''test Mercurial installation
1220 1407
1221 Returns 0 on success. 1408 Returns 0 on success.
1233 try: 1420 try:
1234 codecs.lookup(pycompat.sysstr(encoding.encoding)) 1421 codecs.lookup(pycompat.sysstr(encoding.encoding))
1235 except LookupError as inst: 1422 except LookupError as inst:
1236 err = stringutil.forcebytestr(inst) 1423 err = stringutil.forcebytestr(inst)
1237 problems += 1 1424 problems += 1
1238 fm.condwrite(err, 'encodingerror', _(" %s\n" 1425 fm.condwrite(
1239 " (check that your locale is properly set)\n"), err) 1426 err,
1427 'encodingerror',
1428 _(" %s\n" " (check that your locale is properly set)\n"),
1429 err,
1430 )
1240 1431
1241 # Python 1432 # Python
1242 fm.write('pythonexe', _("checking Python executable (%s)\n"), 1433 fm.write(
1243 pycompat.sysexecutable or _("unknown")) 1434 'pythonexe',
1244 fm.write('pythonver', _("checking Python version (%s)\n"), 1435 _("checking Python executable (%s)\n"),
1245 ("%d.%d.%d" % sys.version_info[:3])) 1436 pycompat.sysexecutable or _("unknown"),
1246 fm.write('pythonlib', _("checking Python lib (%s)...\n"), 1437 )
1247 os.path.dirname(pycompat.fsencode(os.__file__))) 1438 fm.write(
1439 'pythonver',
1440 _("checking Python version (%s)\n"),
1441 ("%d.%d.%d" % sys.version_info[:3]),
1442 )
1443 fm.write(
1444 'pythonlib',
1445 _("checking Python lib (%s)...\n"),
1446 os.path.dirname(pycompat.fsencode(os.__file__)),
1447 )
1248 1448
1249 security = set(sslutil.supportedprotocols) 1449 security = set(sslutil.supportedprotocols)
1250 if sslutil.hassni: 1450 if sslutil.hassni:
1251 security.add('sni') 1451 security.add('sni')
1252 1452
1253 fm.write('pythonsecurity', _("checking Python security support (%s)\n"), 1453 fm.write(
1254 fm.formatlist(sorted(security), name='protocol', 1454 'pythonsecurity',
1255 fmt='%s', sep=',')) 1455 _("checking Python security support (%s)\n"),
1456 fm.formatlist(sorted(security), name='protocol', fmt='%s', sep=','),
1457 )
1256 1458
1257 # These are warnings, not errors. So don't increment problem count. This 1459 # These are warnings, not errors. So don't increment problem count. This
1258 # may change in the future. 1460 # may change in the future.
1259 if 'tls1.2' not in security: 1461 if 'tls1.2' not in security:
1260 fm.plain(_(' TLS 1.2 not supported by Python install; ' 1462 fm.plain(
1261 'network connections lack modern security\n')) 1463 _(
1464 ' TLS 1.2 not supported by Python install; '
1465 'network connections lack modern security\n'
1466 )
1467 )
1262 if 'sni' not in security: 1468 if 'sni' not in security:
1263 fm.plain(_(' SNI not supported by Python install; may have ' 1469 fm.plain(
1264 'connectivity issues with some servers\n')) 1470 _(
1471 ' SNI not supported by Python install; may have '
1472 'connectivity issues with some servers\n'
1473 )
1474 )
1265 1475
1266 # TODO print CA cert info 1476 # TODO print CA cert info
1267 1477
1268 # hg version 1478 # hg version
1269 hgver = util.version() 1479 hgver = util.version()
1270 fm.write('hgver', _("checking Mercurial version (%s)\n"), 1480 fm.write(
1271 hgver.split('+')[0]) 1481 'hgver', _("checking Mercurial version (%s)\n"), hgver.split('+')[0]
1272 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"), 1482 )
1273 '+'.join(hgver.split('+')[1:])) 1483 fm.write(
1484 'hgverextra',
1485 _("checking Mercurial custom build (%s)\n"),
1486 '+'.join(hgver.split('+')[1:]),
1487 )
1274 1488
1275 # compiled modules 1489 # compiled modules
1276 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"), 1490 fm.write(
1277 policy.policy) 1491 'hgmodulepolicy', _("checking module policy (%s)\n"), policy.policy
1278 fm.write('hgmodules', _("checking installed modules (%s)...\n"), 1492 )
1279 os.path.dirname(pycompat.fsencode(__file__))) 1493 fm.write(
1494 'hgmodules',
1495 _("checking installed modules (%s)...\n"),
1496 os.path.dirname(pycompat.fsencode(__file__)),
1497 )
1280 1498
1281 rustandc = policy.policy in ('rust+c', 'rust+c-allow') 1499 rustandc = policy.policy in ('rust+c', 'rust+c-allow')
1282 rustext = rustandc # for now, that's the only case 1500 rustext = rustandc # for now, that's the only case
1283 cext = policy.policy in ('c', 'allow') or rustandc 1501 cext = policy.policy in ('c', 'allow') or rustandc
1284 nopure = cext or rustext 1502 nopure = cext or rustext
1290 base85, 1508 base85,
1291 bdiff, 1509 bdiff,
1292 mpatch, 1510 mpatch,
1293 osutil, 1511 osutil,
1294 ) 1512 )
1513
1295 # quiet pyflakes 1514 # quiet pyflakes
1296 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) 1515 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
1297 if rustext: 1516 if rustext:
1298 from .rustext import ( 1517 from .rustext import (
1299 ancestor, 1518 ancestor,
1300 dirstate, 1519 dirstate,
1301 ) 1520 )
1302 dir(ancestor), dir(dirstate) # quiet pyflakes 1521
1522 dir(ancestor), dir(dirstate) # quiet pyflakes
1303 except Exception as inst: 1523 except Exception as inst:
1304 err = stringutil.forcebytestr(inst) 1524 err = stringutil.forcebytestr(inst)
1305 problems += 1 1525 problems += 1
1306 fm.condwrite(err, 'extensionserror', " %s\n", err) 1526 fm.condwrite(err, 'extensionserror', " %s\n", err)
1307 1527
1308 compengines = util.compengines._engines.values() 1528 compengines = util.compengines._engines.values()
1309 fm.write('compengines', _('checking registered compression engines (%s)\n'), 1529 fm.write(
1310 fm.formatlist(sorted(e.name() for e in compengines), 1530 'compengines',
1311 name='compengine', fmt='%s', sep=', ')) 1531 _('checking registered compression engines (%s)\n'),
1312 fm.write('compenginesavail', _('checking available compression engines ' 1532 fm.formatlist(
1313 '(%s)\n'), 1533 sorted(e.name() for e in compengines),
1314 fm.formatlist(sorted(e.name() for e in compengines 1534 name='compengine',
1315 if e.available()), 1535 fmt='%s',
1316 name='compengine', fmt='%s', sep=', ')) 1536 sep=', ',
1537 ),
1538 )
1539 fm.write(
1540 'compenginesavail',
1541 _('checking available compression engines ' '(%s)\n'),
1542 fm.formatlist(
1543 sorted(e.name() for e in compengines if e.available()),
1544 name='compengine',
1545 fmt='%s',
1546 sep=', ',
1547 ),
1548 )
1317 wirecompengines = compression.compengines.supportedwireengines( 1549 wirecompengines = compression.compengines.supportedwireengines(
1318 compression.SERVERROLE) 1550 compression.SERVERROLE
1319 fm.write('compenginesserver', _('checking available compression engines ' 1551 )
1320 'for wire protocol (%s)\n'), 1552 fm.write(
1321 fm.formatlist([e.name() for e in wirecompengines 1553 'compenginesserver',
1322 if e.wireprotosupport()], 1554 _('checking available compression engines ' 'for wire protocol (%s)\n'),
1323 name='compengine', fmt='%s', sep=', ')) 1555 fm.formatlist(
1556 [e.name() for e in wirecompengines if e.wireprotosupport()],
1557 name='compengine',
1558 fmt='%s',
1559 sep=', ',
1560 ),
1561 )
1324 re2 = 'missing' 1562 re2 = 'missing'
1325 if util._re2: 1563 if util._re2:
1326 re2 = 'available' 1564 re2 = 'available'
1327 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2) 1565 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1328 fm.data(re2=bool(util._re2)) 1566 fm.data(re2=bool(util._re2))
1342 err = stringutil.forcebytestr(inst) 1580 err = stringutil.forcebytestr(inst)
1343 p = None 1581 p = None
1344 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err) 1582 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1345 else: 1583 else:
1346 p = None 1584 p = None
1347 fm.condwrite(p, 'defaulttemplate', 1585 fm.condwrite(
1348 _("checking default template (%s)\n"), m) 1586 p, 'defaulttemplate', _("checking default template (%s)\n"), m
1349 fm.condwrite(not m, 'defaulttemplatenotfound', 1587 )
1350 _(" template '%s' not found\n"), "default") 1588 fm.condwrite(
1589 not m,
1590 'defaulttemplatenotfound',
1591 _(" template '%s' not found\n"),
1592 "default",
1593 )
1351 if not p: 1594 if not p:
1352 problems += 1 1595 problems += 1
1353 fm.condwrite(not p, '', 1596 fm.condwrite(
1354 _(" (templates seem to have been installed incorrectly)\n")) 1597 not p, '', _(" (templates seem to have been installed incorrectly)\n")
1598 )
1355 1599
1356 # editor 1600 # editor
1357 editor = ui.geteditor() 1601 editor = ui.geteditor()
1358 editor = util.expandpath(editor) 1602 editor = util.expandpath(editor)
1359 editorbin = procutil.shellsplit(editor)[0] 1603 editorbin = procutil.shellsplit(editor)[0]
1360 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin) 1604 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1361 cmdpath = procutil.findexe(editorbin) 1605 cmdpath = procutil.findexe(editorbin)
1362 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound', 1606 fm.condwrite(
1363 _(" No commit editor set and can't find %s in PATH\n" 1607 not cmdpath and editor == 'vi',
1364 " (specify a commit editor in your configuration" 1608 'vinotfound',
1365 " file)\n"), not cmdpath and editor == 'vi' and editorbin) 1609 _(
1366 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound', 1610 " No commit editor set and can't find %s in PATH\n"
1367 _(" Can't find editor '%s' in PATH\n" 1611 " (specify a commit editor in your configuration"
1368 " (specify a commit editor in your configuration" 1612 " file)\n"
1369 " file)\n"), not cmdpath and editorbin) 1613 ),
1614 not cmdpath and editor == 'vi' and editorbin,
1615 )
1616 fm.condwrite(
1617 not cmdpath and editor != 'vi',
1618 'editornotfound',
1619 _(
1620 " Can't find editor '%s' in PATH\n"
1621 " (specify a commit editor in your configuration"
1622 " file)\n"
1623 ),
1624 not cmdpath and editorbin,
1625 )
1370 if not cmdpath and editor != 'vi': 1626 if not cmdpath and editor != 'vi':
1371 problems += 1 1627 problems += 1
1372 1628
1373 # check username 1629 # check username
1374 username = None 1630 username = None
1377 username = ui.username() 1633 username = ui.username()
1378 except error.Abort as e: 1634 except error.Abort as e:
1379 err = stringutil.forcebytestr(e) 1635 err = stringutil.forcebytestr(e)
1380 problems += 1 1636 problems += 1
1381 1637
1382 fm.condwrite(username, 'username', _("checking username (%s)\n"), username) 1638 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1383 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n" 1639 fm.condwrite(
1384 " (specify a username in your configuration file)\n"), err) 1640 err,
1641 'usernameerror',
1642 _(
1643 "checking username...\n %s\n"
1644 " (specify a username in your configuration file)\n"
1645 ),
1646 err,
1647 )
1385 1648
1386 for name, mod in extensions.extensions(): 1649 for name, mod in extensions.extensions():
1387 handler = getattr(mod, 'debuginstall', None) 1650 handler = getattr(mod, 'debuginstall', None)
1388 if handler is not None: 1651 if handler is not None:
1389 problems += handler(ui, fm) 1652 problems += handler(ui, fm)
1390 1653
1391 fm.condwrite(not problems, '', 1654 fm.condwrite(not problems, '', _("no problems detected\n"))
1392 _("no problems detected\n"))
1393 if not problems: 1655 if not problems:
1394 fm.data(problems=problems) 1656 fm.data(problems=problems)
1395 fm.condwrite(problems, 'problems', 1657 fm.condwrite(
1396 _("%d problems detected," 1658 problems,
1397 " please check your install!\n"), problems) 1659 'problems',
1660 _("%d problems detected," " please check your install!\n"),
1661 problems,
1662 )
1398 fm.end() 1663 fm.end()
1399 1664
1400 return problems 1665 return problems
1666
1401 1667
1402 @command('debugknown', [], _('REPO ID...'), norepo=True) 1668 @command('debugknown', [], _('REPO ID...'), norepo=True)
1403 def debugknown(ui, repopath, *ids, **opts): 1669 def debugknown(ui, repopath, *ids, **opts):
1404 """test whether node ids are known to a repo 1670 """test whether node ids are known to a repo
1405 1671
1411 if not repo.capable('known'): 1677 if not repo.capable('known'):
1412 raise error.Abort("known() not supported by target repository") 1678 raise error.Abort("known() not supported by target repository")
1413 flags = repo.known([bin(s) for s in ids]) 1679 flags = repo.known([bin(s) for s in ids])
1414 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags]))) 1680 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1415 1681
1682
1416 @command('debuglabelcomplete', [], _('LABEL...')) 1683 @command('debuglabelcomplete', [], _('LABEL...'))
1417 def debuglabelcomplete(ui, repo, *args): 1684 def debuglabelcomplete(ui, repo, *args):
1418 '''backwards compatibility with old bash completion scripts (DEPRECATED)''' 1685 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1419 debugnamecomplete(ui, repo, *args) 1686 debugnamecomplete(ui, repo, *args)
1420 1687
1421 @command('debuglocks', 1688
1422 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')), 1689 @command(
1423 ('W', 'force-wlock', None, 1690 'debuglocks',
1424 _('free the working state lock (DANGEROUS)')), 1691 [
1425 ('s', 'set-lock', None, _('set the store lock until stopped')), 1692 ('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1426 ('S', 'set-wlock', None, 1693 (
1427 _('set the working state lock until stopped'))], 1694 'W',
1428 _('[OPTION]...')) 1695 'force-wlock',
1696 None,
1697 _('free the working state lock (DANGEROUS)'),
1698 ),
1699 ('s', 'set-lock', None, _('set the store lock until stopped')),
1700 ('S', 'set-wlock', None, _('set the working state lock until stopped')),
1701 ],
1702 _('[OPTION]...'),
1703 )
1429 def debuglocks(ui, repo, **opts): 1704 def debuglocks(ui, repo, **opts):
1430 """show or modify state of locks 1705 """show or modify state of locks
1431 1706
1432 By default, this command will show which locks are held. This 1707 By default, this command will show which locks are held. This
1433 includes the user and process holding the lock, the amount of time 1708 includes the user and process holding the lock, the amount of time
1497 if ":" in locker: 1772 if ":" in locker:
1498 host, pid = locker.split(':') 1773 host, pid = locker.split(':')
1499 if host == socket.gethostname(): 1774 if host == socket.gethostname():
1500 locker = 'user %s, process %s' % (user or b'None', pid) 1775 locker = 'user %s, process %s' % (user or b'None', pid)
1501 else: 1776 else:
1502 locker = ('user %s, process %s, host %s' 1777 locker = 'user %s, process %s, host %s' % (
1503 % (user or b'None', pid, host)) 1778 user or b'None',
1504 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age)) 1779 pid,
1780 host,
1781 )
1782 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
1505 return 1 1783 return 1
1506 except OSError as e: 1784 except OSError as e:
1507 if e.errno != errno.ENOENT: 1785 if e.errno != errno.ENOENT:
1508 raise 1786 raise
1509 1787
1510 ui.write(("%-6s free\n") % (name + ":")) 1788 ui.write("%-6s free\n" % (name + ":"))
1511 return 0 1789 return 0
1512 1790
1513 held += report(repo.svfs, "lock", repo.lock) 1791 held += report(repo.svfs, "lock", repo.lock)
1514 held += report(repo.vfs, "wlock", repo.wlock) 1792 held += report(repo.vfs, "wlock", repo.wlock)
1515 1793
1516 return held 1794 return held
1517 1795
1518 @command('debugmanifestfulltextcache', [ 1796
1797 @command(
1798 'debugmanifestfulltextcache',
1799 [
1519 ('', 'clear', False, _('clear the cache')), 1800 ('', 'clear', False, _('clear the cache')),
1520 ('a', 'add', [], _('add the given manifest nodes to the cache'), 1801 (
1521 _('NODE')) 1802 'a',
1522 ], '') 1803 'add',
1804 [],
1805 _('add the given manifest nodes to the cache'),
1806 _('NODE'),
1807 ),
1808 ],
1809 '',
1810 )
1523 def debugmanifestfulltextcache(ui, repo, add=(), **opts): 1811 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
1524 """show, clear or amend the contents of the manifest fulltext cache""" 1812 """show, clear or amend the contents of the manifest fulltext cache"""
1525 1813
1526 def getcache(): 1814 def getcache():
1527 r = repo.manifestlog.getstorage(b'') 1815 r = repo.manifestlog.getstorage(b'')
1528 try: 1816 try:
1529 return r._fulltextcache 1817 return r._fulltextcache
1530 except AttributeError: 1818 except AttributeError:
1531 msg = _("Current revlog implementation doesn't appear to have a " 1819 msg = _(
1532 "manifest fulltext cache\n") 1820 "Current revlog implementation doesn't appear to have a "
1821 "manifest fulltext cache\n"
1822 )
1533 raise error.Abort(msg) 1823 raise error.Abort(msg)
1534 1824
1535 if opts.get(r'clear'): 1825 if opts.get(r'clear'):
1536 with repo.wlock(): 1826 with repo.wlock():
1537 cache = getcache() 1827 cache = getcache()
1553 cache = getcache() 1843 cache = getcache()
1554 if not len(cache): 1844 if not len(cache):
1555 ui.write(_('cache empty\n')) 1845 ui.write(_('cache empty\n'))
1556 else: 1846 else:
1557 ui.write( 1847 ui.write(
1558 _('cache contains %d manifest entries, in order of most to ' 1848 _(
1559 'least recent:\n') % (len(cache),)) 1849 'cache contains %d manifest entries, in order of most to '
1850 'least recent:\n'
1851 )
1852 % (len(cache),)
1853 )
1560 totalsize = 0 1854 totalsize = 0
1561 for nodeid in cache: 1855 for nodeid in cache:
1562 # Use cache.get to not update the LRU order 1856 # Use cache.get to not update the LRU order
1563 data = cache.peek(nodeid) 1857 data = cache.peek(nodeid)
1564 size = len(data) 1858 size = len(data)
1565 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size 1859 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1566 ui.write(_('id: %s, size %s\n') % ( 1860 ui.write(
1567 hex(nodeid), util.bytecount(size))) 1861 _('id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
1862 )
1568 ondisk = cache._opener.stat('manifestfulltextcache').st_size 1863 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1569 ui.write( 1864 ui.write(
1570 _('total cache data size %s, on-disk %s\n') % ( 1865 _('total cache data size %s, on-disk %s\n')
1571 util.bytecount(totalsize), util.bytecount(ondisk)) 1866 % (util.bytecount(totalsize), util.bytecount(ondisk))
1572 ) 1867 )
1868
1573 1869
1574 @command('debugmergestate', [], '') 1870 @command('debugmergestate', [], '')
1575 def debugmergestate(ui, repo, *args): 1871 def debugmergestate(ui, repo, *args):
1576 """print merge state 1872 """print merge state
1577 1873
1578 Use --verbose to print out information about whether v1 or v2 merge state 1874 Use --verbose to print out information about whether v1 or v2 merge state
1579 was chosen.""" 1875 was chosen."""
1876
1580 def _hashornull(h): 1877 def _hashornull(h):
1581 if h == nullhex: 1878 if h == nullhex:
1582 return 'null' 1879 return 'null'
1583 else: 1880 else:
1584 return h 1881 return h
1585 1882
1586 def printrecords(version): 1883 def printrecords(version):
1587 ui.write(('* version %d records\n') % version) 1884 ui.write('* version %d records\n' % version)
1588 if version == 1: 1885 if version == 1:
1589 records = v1records 1886 records = v1records
1590 else: 1887 else:
1591 records = v2records 1888 records = v2records
1592 1889
1593 for rtype, record in records: 1890 for rtype, record in records:
1594 # pretty print some record types 1891 # pretty print some record types
1595 if rtype == 'L': 1892 if rtype == 'L':
1596 ui.write(('local: %s\n') % record) 1893 ui.write('local: %s\n' % record)
1597 elif rtype == 'O': 1894 elif rtype == 'O':
1598 ui.write(('other: %s\n') % record) 1895 ui.write('other: %s\n' % record)
1599 elif rtype == 'm': 1896 elif rtype == 'm':
1600 driver, mdstate = record.split('\0', 1) 1897 driver, mdstate = record.split('\0', 1)
1601 ui.write(('merge driver: %s (state "%s")\n') 1898 ui.write('merge driver: %s (state "%s")\n' % (driver, mdstate))
1602 % (driver, mdstate))
1603 elif rtype in 'FDC': 1899 elif rtype in 'FDC':
1604 r = record.split('\0') 1900 r = record.split('\0')
1605 f, state, hash, lfile, afile, anode, ofile = r[0:7] 1901 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1606 if version == 1: 1902 if version == 1:
1607 onode = 'not stored in v1 format' 1903 onode = 'not stored in v1 format'
1608 flags = r[7] 1904 flags = r[7]
1609 else: 1905 else:
1610 onode, flags = r[7:9] 1906 onode, flags = r[7:9]
1611 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n') 1907 ui.write(
1612 % (f, rtype, state, _hashornull(hash))) 1908 'file: %s (record type "%s", state "%s", hash %s)\n'
1613 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags)) 1909 % (f, rtype, state, _hashornull(hash))
1614 ui.write((' ancestor path: %s (node %s)\n') 1910 )
1615 % (afile, _hashornull(anode))) 1911 ui.write(' local path: %s (flags "%s")\n' % (lfile, flags))
1616 ui.write((' other path: %s (node %s)\n') 1912 ui.write(
1617 % (ofile, _hashornull(onode))) 1913 ' ancestor path: %s (node %s)\n'
1914 % (afile, _hashornull(anode))
1915 )
1916 ui.write(
1917 ' other path: %s (node %s)\n' % (ofile, _hashornull(onode))
1918 )
1618 elif rtype == 'f': 1919 elif rtype == 'f':
1619 filename, rawextras = record.split('\0', 1) 1920 filename, rawextras = record.split('\0', 1)
1620 extras = rawextras.split('\0') 1921 extras = rawextras.split('\0')
1621 i = 0 1922 i = 0
1622 extrastrings = [] 1923 extrastrings = []
1623 while i < len(extras): 1924 while i < len(extras):
1624 extrastrings.append('%s = %s' % (extras[i], extras[i + 1])) 1925 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1625 i += 2 1926 i += 2
1626 1927
1627 ui.write(('file extras: %s (%s)\n') 1928 ui.write(
1628 % (filename, ', '.join(extrastrings))) 1929 'file extras: %s (%s)\n'
1930 % (filename, ', '.join(extrastrings))
1931 )
1629 elif rtype == 'l': 1932 elif rtype == 'l':
1630 labels = record.split('\0', 2) 1933 labels = record.split('\0', 2)
1631 labels = [l for l in labels if len(l) > 0] 1934 labels = [l for l in labels if len(l) > 0]
1632 ui.write(('labels:\n')) 1935 ui.write('labels:\n')
1633 ui.write((' local: %s\n' % labels[0])) 1936 ui.write((' local: %s\n' % labels[0]))
1634 ui.write((' other: %s\n' % labels[1])) 1937 ui.write((' other: %s\n' % labels[1]))
1635 if len(labels) > 2: 1938 if len(labels) > 2:
1636 ui.write((' base: %s\n' % labels[2])) 1939 ui.write((' base: %s\n' % labels[2]))
1637 else: 1940 else:
1638 ui.write(('unrecognized entry: %s\t%s\n') 1941 ui.write(
1639 % (rtype, record.replace('\0', '\t'))) 1942 'unrecognized entry: %s\t%s\n'
1943 % (rtype, record.replace('\0', '\t'))
1944 )
1640 1945
1641 # Avoid mergestate.read() since it may raise an exception for unsupported 1946 # Avoid mergestate.read() since it may raise an exception for unsupported
1642 # merge state records. We shouldn't be doing this, but this is OK since this 1947 # merge state records. We shouldn't be doing this, but this is OK since this
1643 # command is pretty low-level. 1948 # command is pretty low-level.
1644 ms = mergemod.mergestate(repo) 1949 ms = mergemod.mergestate(repo)
1645 1950
1646 # sort so that reasonable information is on top 1951 # sort so that reasonable information is on top
1647 v1records = ms._readrecordsv1() 1952 v1records = ms._readrecordsv1()
1648 v2records = ms._readrecordsv2() 1953 v2records = ms._readrecordsv2()
1649 order = 'LOml' 1954 order = 'LOml'
1955
1650 def key(r): 1956 def key(r):
1651 idx = order.find(r[0]) 1957 idx = order.find(r[0])
1652 if idx == -1: 1958 if idx == -1:
1653 return (1, r[1]) 1959 return (1, r[1])
1654 else: 1960 else:
1655 return (0, idx) 1961 return (0, idx)
1962
1656 v1records.sort(key=key) 1963 v1records.sort(key=key)
1657 v2records.sort(key=key) 1964 v2records.sort(key=key)
1658 1965
1659 if not v1records and not v2records: 1966 if not v1records and not v2records:
1660 ui.write(('no merge state found\n')) 1967 ui.write('no merge state found\n')
1661 elif not v2records: 1968 elif not v2records:
1662 ui.note(('no version 2 merge state\n')) 1969 ui.note('no version 2 merge state\n')
1663 printrecords(1) 1970 printrecords(1)
1664 elif ms._v1v2match(v1records, v2records): 1971 elif ms._v1v2match(v1records, v2records):
1665 ui.note(('v1 and v2 states match: using v2\n')) 1972 ui.note('v1 and v2 states match: using v2\n')
1666 printrecords(2) 1973 printrecords(2)
1667 else: 1974 else:
1668 ui.note(('v1 and v2 states mismatch: using v1\n')) 1975 ui.note('v1 and v2 states mismatch: using v1\n')
1669 printrecords(1) 1976 printrecords(1)
1670 if ui.verbose: 1977 if ui.verbose:
1671 printrecords(2) 1978 printrecords(2)
1979
1672 1980
1673 @command('debugnamecomplete', [], _('NAME...')) 1981 @command('debugnamecomplete', [], _('NAME...'))
1674 def debugnamecomplete(ui, repo, *args): 1982 def debugnamecomplete(ui, repo, *args):
1675 '''complete "names" - tags, open branch names, bookmark names''' 1983 '''complete "names" - tags, open branch names, bookmark names'''
1676 1984
1678 # since we previously only listed open branches, we will handle that 1986 # since we previously only listed open branches, we will handle that
1679 # specially (after this for loop) 1987 # specially (after this for loop)
1680 for name, ns in repo.names.iteritems(): 1988 for name, ns in repo.names.iteritems():
1681 if name != 'branches': 1989 if name != 'branches':
1682 names.update(ns.listnames(repo)) 1990 names.update(ns.listnames(repo))
1683 names.update(tag for (tag, heads, tip, closed) 1991 names.update(
1684 in repo.branchmap().iterbranches() if not closed) 1992 tag
1993 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
1994 if not closed
1995 )
1685 completions = set() 1996 completions = set()
1686 if not args: 1997 if not args:
1687 args = [''] 1998 args = ['']
1688 for a in args: 1999 for a in args:
1689 completions.update(n for n in names if n.startswith(a)) 2000 completions.update(n for n in names if n.startswith(a))
1690 ui.write('\n'.join(sorted(completions))) 2001 ui.write('\n'.join(sorted(completions)))
1691 ui.write('\n') 2002 ui.write('\n')
1692 2003
1693 @command('debugobsolete', 2004
1694 [('', 'flags', 0, _('markers flag')), 2005 @command(
1695 ('', 'record-parents', False, 2006 'debugobsolete',
1696 _('record parent information for the precursor')), 2007 [
1697 ('r', 'rev', [], _('display markers relevant to REV')), 2008 ('', 'flags', 0, _('markers flag')),
1698 ('', 'exclusive', False, _('restrict display to markers only ' 2009 (
1699 'relevant to REV')), 2010 '',
1700 ('', 'index', False, _('display index of the marker')), 2011 'record-parents',
1701 ('', 'delete', [], _('delete markers specified by indices')), 2012 False,
1702 ] + cmdutil.commitopts2 + cmdutil.formatteropts, 2013 _('record parent information for the precursor'),
1703 _('[OBSOLETED [REPLACEMENT ...]]')) 2014 ),
2015 ('r', 'rev', [], _('display markers relevant to REV')),
2016 (
2017 '',
2018 'exclusive',
2019 False,
2020 _('restrict display to markers only ' 'relevant to REV'),
2021 ),
2022 ('', 'index', False, _('display index of the marker')),
2023 ('', 'delete', [], _('delete markers specified by indices')),
2024 ]
2025 + cmdutil.commitopts2
2026 + cmdutil.formatteropts,
2027 _('[OBSOLETED [REPLACEMENT ...]]'),
2028 )
1704 def debugobsolete(ui, repo, precursor=None, *successors, **opts): 2029 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1705 """create arbitrary obsolete marker 2030 """create arbitrary obsolete marker
1706 2031
1707 With no arguments, displays the list of obsolescence markers.""" 2032 With no arguments, displays the list of obsolescence markers."""
1708 2033
1716 n = bin(s) 2041 n = bin(s)
1717 if len(n) != len(nullid): 2042 if len(n) != len(nullid):
1718 raise TypeError() 2043 raise TypeError()
1719 return n 2044 return n
1720 except TypeError: 2045 except TypeError:
1721 raise error.Abort('changeset references must be full hexadecimal ' 2046 raise error.Abort(
1722 'node identifiers') 2047 'changeset references must be full hexadecimal '
2048 'node identifiers'
2049 )
1723 2050
1724 if opts.get('delete'): 2051 if opts.get('delete'):
1725 indices = [] 2052 indices = []
1726 for v in opts.get('delete'): 2053 for v in opts.get('delete'):
1727 try: 2054 try:
1728 indices.append(int(v)) 2055 indices.append(int(v))
1729 except ValueError: 2056 except ValueError:
1730 raise error.Abort(_('invalid index value: %r') % v, 2057 raise error.Abort(
1731 hint=_('use integers for indices')) 2058 _('invalid index value: %r') % v,
2059 hint=_('use integers for indices'),
2060 )
1732 2061
1733 if repo.currenttransaction(): 2062 if repo.currenttransaction():
1734 raise error.Abort(_('cannot delete obsmarkers in the middle ' 2063 raise error.Abort(
1735 'of transaction.')) 2064 _('cannot delete obsmarkers in the middle ' 'of transaction.')
2065 )
1736 2066
1737 with repo.lock(): 2067 with repo.lock():
1738 n = repair.deleteobsmarkers(repo.obsstore, indices) 2068 n = repair.deleteobsmarkers(repo.obsstore, indices)
1739 ui.write(_('deleted %i obsolescence markers\n') % n) 2069 ui.write(_('deleted %i obsolescence markers\n') % n)
1740 2070
1757 date = None 2087 date = None
1758 prec = parsenodeid(precursor) 2088 prec = parsenodeid(precursor)
1759 parents = None 2089 parents = None
1760 if opts['record_parents']: 2090 if opts['record_parents']:
1761 if prec not in repo.unfiltered(): 2091 if prec not in repo.unfiltered():
1762 raise error.Abort('cannot used --record-parents on ' 2092 raise error.Abort(
1763 'unknown changesets') 2093 'cannot used --record-parents on '
2094 'unknown changesets'
2095 )
1764 parents = repo.unfiltered()[prec].parents() 2096 parents = repo.unfiltered()[prec].parents()
1765 parents = tuple(p.node() for p in parents) 2097 parents = tuple(p.node() for p in parents)
1766 repo.obsstore.create(tr, prec, succs, opts['flags'], 2098 repo.obsstore.create(
1767 parents=parents, date=date, 2099 tr,
1768 metadata=metadata, ui=ui) 2100 prec,
2101 succs,
2102 opts['flags'],
2103 parents=parents,
2104 date=date,
2105 metadata=metadata,
2106 ui=ui,
2107 )
1769 tr.close() 2108 tr.close()
1770 except ValueError as exc: 2109 except ValueError as exc:
1771 raise error.Abort(_('bad obsmarker input: %s') % 2110 raise error.Abort(
1772 pycompat.bytestr(exc)) 2111 _('bad obsmarker input: %s') % pycompat.bytestr(exc)
2112 )
1773 finally: 2113 finally:
1774 tr.release() 2114 tr.release()
1775 finally: 2115 finally:
1776 l.release() 2116 l.release()
1777 else: 2117 else:
1778 if opts['rev']: 2118 if opts['rev']:
1779 revs = scmutil.revrange(repo, opts['rev']) 2119 revs = scmutil.revrange(repo, opts['rev'])
1780 nodes = [repo[r].node() for r in revs] 2120 nodes = [repo[r].node() for r in revs]
1781 markers = list(obsutil.getmarkers(repo, nodes=nodes, 2121 markers = list(
1782 exclusive=opts['exclusive'])) 2122 obsutil.getmarkers(
2123 repo, nodes=nodes, exclusive=opts['exclusive']
2124 )
2125 )
1783 markers.sort(key=lambda x: x._data) 2126 markers.sort(key=lambda x: x._data)
1784 else: 2127 else:
1785 markers = obsutil.getmarkers(repo) 2128 markers = obsutil.getmarkers(repo)
1786 2129
1787 markerstoiter = markers 2130 markerstoiter = markers
1805 fm.startitem() 2148 fm.startitem()
1806 ind = i if opts.get('index') else None 2149 ind = i if opts.get('index') else None
1807 cmdutil.showmarker(fm, m, index=ind) 2150 cmdutil.showmarker(fm, m, index=ind)
1808 fm.end() 2151 fm.end()
1809 2152
1810 @command('debugp1copies', 2153
1811 [('r', 'rev', '', _('revision to debug'), _('REV'))], 2154 @command(
1812 _('[-r REV]')) 2155 'debugp1copies',
2156 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2157 _('[-r REV]'),
2158 )
1813 def debugp1copies(ui, repo, **opts): 2159 def debugp1copies(ui, repo, **opts):
1814 """dump copy information compared to p1""" 2160 """dump copy information compared to p1"""
1815 2161
1816 opts = pycompat.byteskwargs(opts) 2162 opts = pycompat.byteskwargs(opts)
1817 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None) 2163 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
1818 for dst, src in ctx.p1copies().items(): 2164 for dst, src in ctx.p1copies().items():
1819 ui.write('%s -> %s\n' % (src, dst)) 2165 ui.write('%s -> %s\n' % (src, dst))
1820 2166
1821 @command('debugp2copies', 2167
1822 [('r', 'rev', '', _('revision to debug'), _('REV'))], 2168 @command(
1823 _('[-r REV]')) 2169 'debugp2copies',
2170 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2171 _('[-r REV]'),
2172 )
1824 def debugp1copies(ui, repo, **opts): 2173 def debugp1copies(ui, repo, **opts):
1825 """dump copy information compared to p2""" 2174 """dump copy information compared to p2"""
1826 2175
1827 opts = pycompat.byteskwargs(opts) 2176 opts = pycompat.byteskwargs(opts)
1828 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None) 2177 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
1829 for dst, src in ctx.p2copies().items(): 2178 for dst, src in ctx.p2copies().items():
1830 ui.write('%s -> %s\n' % (src, dst)) 2179 ui.write('%s -> %s\n' % (src, dst))
1831 2180
1832 @command('debugpathcomplete', 2181
1833 [('f', 'full', None, _('complete an entire path')), 2182 @command(
1834 ('n', 'normal', None, _('show only normal files')), 2183 'debugpathcomplete',
1835 ('a', 'added', None, _('show only added files')), 2184 [
1836 ('r', 'removed', None, _('show only removed files'))], 2185 ('f', 'full', None, _('complete an entire path')),
1837 _('FILESPEC...')) 2186 ('n', 'normal', None, _('show only normal files')),
2187 ('a', 'added', None, _('show only added files')),
2188 ('r', 'removed', None, _('show only removed files')),
2189 ],
2190 _('FILESPEC...'),
2191 )
1838 def debugpathcomplete(ui, repo, *specs, **opts): 2192 def debugpathcomplete(ui, repo, *specs, **opts):
1839 '''complete part or all of a tracked path 2193 '''complete part or all of a tracked path
1840 2194
1841 This command supports shells that offer path name completion. It 2195 This command supports shells that offer path name completion. It
1842 currently completes only files already known to the dirstate. 2196 currently completes only files already known to the dirstate.
1850 rootdir = repo.root + pycompat.ossep 2204 rootdir = repo.root + pycompat.ossep
1851 if spec != repo.root and not spec.startswith(rootdir): 2205 if spec != repo.root and not spec.startswith(rootdir):
1852 return [], [] 2206 return [], []
1853 if os.path.isdir(spec): 2207 if os.path.isdir(spec):
1854 spec += '/' 2208 spec += '/'
1855 spec = spec[len(rootdir):] 2209 spec = spec[len(rootdir) :]
1856 fixpaths = pycompat.ossep != '/' 2210 fixpaths = pycompat.ossep != '/'
1857 if fixpaths: 2211 if fixpaths:
1858 spec = spec.replace(pycompat.ossep, '/') 2212 spec = spec.replace(pycompat.ossep, '/')
1859 speclen = len(spec) 2213 speclen = len(spec)
1860 fullpaths = opts[r'full'] 2214 fullpaths = opts[r'full']
1892 dirs.update(d) 2246 dirs.update(d)
1893 files.update(dirs) 2247 files.update(dirs)
1894 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files))) 2248 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1895 ui.write('\n') 2249 ui.write('\n')
1896 2250
1897 @command('debugpathcopies', 2251
1898 cmdutil.walkopts, 2252 @command(
1899 'hg debugpathcopies REV1 REV2 [FILE]', 2253 'debugpathcopies',
1900 inferrepo=True) 2254 cmdutil.walkopts,
2255 'hg debugpathcopies REV1 REV2 [FILE]',
2256 inferrepo=True,
2257 )
1901 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts): 2258 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
1902 """show copies between two revisions""" 2259 """show copies between two revisions"""
1903 ctx1 = scmutil.revsingle(repo, rev1) 2260 ctx1 = scmutil.revsingle(repo, rev1)
1904 ctx2 = scmutil.revsingle(repo, rev2) 2261 ctx2 = scmutil.revsingle(repo, rev2)
1905 m = scmutil.match(ctx1, pats, opts) 2262 m = scmutil.match(ctx1, pats, opts)
1906 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()): 2263 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
1907 ui.write('%s -> %s\n' % (src, dst)) 2264 ui.write('%s -> %s\n' % (src, dst))
2265
1908 2266
1909 @command('debugpeer', [], _('PATH'), norepo=True) 2267 @command('debugpeer', [], _('PATH'), norepo=True)
1910 def debugpeer(ui, path): 2268 def debugpeer(ui, path):
1911 """establish a connection to a peer repository""" 2269 """establish a connection to a peer repository"""
1912 # Always enable peer request logging. Requires --debug to display 2270 # Always enable peer request logging. Requires --debug to display
1923 2281
1924 ui.write(_('url: %s\n') % peer.url()) 2282 ui.write(_('url: %s\n') % peer.url())
1925 ui.write(_('local: %s\n') % (_('yes') if local else _('no'))) 2283 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1926 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no'))) 2284 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1927 2285
1928 @command('debugpickmergetool', 2286
1929 [('r', 'rev', '', _('check for files in this revision'), _('REV')), 2287 @command(
1930 ('', 'changedelete', None, _('emulate merging change and delete')), 2288 'debugpickmergetool',
1931 ] + cmdutil.walkopts + cmdutil.mergetoolopts, 2289 [
1932 _('[PATTERN]...'), 2290 ('r', 'rev', '', _('check for files in this revision'), _('REV')),
1933 inferrepo=True) 2291 ('', 'changedelete', None, _('emulate merging change and delete')),
2292 ]
2293 + cmdutil.walkopts
2294 + cmdutil.mergetoolopts,
2295 _('[PATTERN]...'),
2296 inferrepo=True,
2297 )
1934 def debugpickmergetool(ui, repo, *pats, **opts): 2298 def debugpickmergetool(ui, repo, *pats, **opts):
1935 """examine which merge tool is chosen for specified file 2299 """examine which merge tool is chosen for specified file
1936 2300
1937 As described in :hg:`help merge-tools`, Mercurial examines 2301 As described in :hg:`help merge-tools`, Mercurial examines
1938 configurations below in this order to decide which merge tool is 2302 configurations below in this order to decide which merge tool is
1975 """ 2339 """
1976 opts = pycompat.byteskwargs(opts) 2340 opts = pycompat.byteskwargs(opts)
1977 overrides = {} 2341 overrides = {}
1978 if opts['tool']: 2342 if opts['tool']:
1979 overrides[('ui', 'forcemerge')] = opts['tool'] 2343 overrides[('ui', 'forcemerge')] = opts['tool']
1980 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool']))) 2344 ui.note('with --tool %r\n' % (pycompat.bytestr(opts['tool'])))
1981 2345
1982 with ui.configoverride(overrides, 'debugmergepatterns'): 2346 with ui.configoverride(overrides, 'debugmergepatterns'):
1983 hgmerge = encoding.environ.get("HGMERGE") 2347 hgmerge = encoding.environ.get("HGMERGE")
1984 if hgmerge is not None: 2348 if hgmerge is not None:
1985 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge))) 2349 ui.note('with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
1986 uimerge = ui.config("ui", "merge") 2350 uimerge = ui.config("ui", "merge")
1987 if uimerge: 2351 if uimerge:
1988 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge))) 2352 ui.note('with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
1989 2353
1990 ctx = scmutil.revsingle(repo, opts.get('rev')) 2354 ctx = scmutil.revsingle(repo, opts.get('rev'))
1991 m = scmutil.match(ctx, pats, opts) 2355 m = scmutil.match(ctx, pats, opts)
1992 changedelete = opts['changedelete'] 2356 changedelete = opts['changedelete']
1993 for path in ctx.walk(m): 2357 for path in ctx.walk(m):
1994 fctx = ctx[path] 2358 fctx = ctx[path]
1995 try: 2359 try:
1996 if not ui.debugflag: 2360 if not ui.debugflag:
1997 ui.pushbuffer(error=True) 2361 ui.pushbuffer(error=True)
1998 tool, toolpath = filemerge._picktool(repo, ui, path, 2362 tool, toolpath = filemerge._picktool(
1999 fctx.isbinary(), 2363 repo,
2000 'l' in fctx.flags(), 2364 ui,
2001 changedelete) 2365 path,
2366 fctx.isbinary(),
2367 'l' in fctx.flags(),
2368 changedelete,
2369 )
2002 finally: 2370 finally:
2003 if not ui.debugflag: 2371 if not ui.debugflag:
2004 ui.popbuffer() 2372 ui.popbuffer()
2005 ui.write(('%s = %s\n') % (path, tool)) 2373 ui.write('%s = %s\n' % (path, tool))
2374
2006 2375
2007 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True) 2376 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2008 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts): 2377 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2009 '''access the pushkey key/value protocol 2378 '''access the pushkey key/value protocol
2010 2379
2016 2385
2017 target = hg.peer(ui, {}, repopath) 2386 target = hg.peer(ui, {}, repopath)
2018 if keyinfo: 2387 if keyinfo:
2019 key, old, new = keyinfo 2388 key, old, new = keyinfo
2020 with target.commandexecutor() as e: 2389 with target.commandexecutor() as e:
2021 r = e.callcommand('pushkey', { 2390 r = e.callcommand(
2022 'namespace': namespace, 2391 'pushkey',
2023 'key': key, 2392 {'namespace': namespace, 'key': key, 'old': old, 'new': new,},
2024 'old': old, 2393 ).result()
2025 'new': new,
2026 }).result()
2027 2394
2028 ui.status(pycompat.bytestr(r) + '\n') 2395 ui.status(pycompat.bytestr(r) + '\n')
2029 return not r 2396 return not r
2030 else: 2397 else:
2031 for k, v in sorted(target.listkeys(namespace).iteritems()): 2398 for k, v in sorted(target.listkeys(namespace).iteritems()):
2032 ui.write("%s\t%s\n" % (stringutil.escapestr(k), 2399 ui.write(
2033 stringutil.escapestr(v))) 2400 "%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
2401 )
2402
2034 2403
2035 @command('debugpvec', [], _('A B')) 2404 @command('debugpvec', [], _('A B'))
2036 def debugpvec(ui, repo, a, b=None): 2405 def debugpvec(ui, repo, a, b=None):
2037 ca = scmutil.revsingle(repo, a) 2406 ca = scmutil.revsingle(repo, a)
2038 cb = scmutil.revsingle(repo, b) 2407 cb = scmutil.revsingle(repo, b)
2047 elif pa | pb: 2416 elif pa | pb:
2048 rel = "|" 2417 rel = "|"
2049 ui.write(_("a: %s\n") % pa) 2418 ui.write(_("a: %s\n") % pa)
2050 ui.write(_("b: %s\n") % pb) 2419 ui.write(_("b: %s\n") % pb)
2051 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth)) 2420 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2052 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") % 2421 ui.write(
2053 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec), 2422 _("delta: %d hdist: %d distance: %d relation: %s\n")
2054 pa.distance(pb), rel)) 2423 % (
2055 2424 abs(pa._depth - pb._depth),
2056 @command('debugrebuilddirstate|debugrebuildstate', 2425 pvec._hamming(pa._vec, pb._vec),
2057 [('r', 'rev', '', _('revision to rebuild to'), _('REV')), 2426 pa.distance(pb),
2058 ('', 'minimal', None, _('only rebuild files that are inconsistent with ' 2427 rel,
2059 'the working copy parent')), 2428 )
2429 )
2430
2431
2432 @command(
2433 'debugrebuilddirstate|debugrebuildstate',
2434 [
2435 ('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2436 (
2437 '',
2438 'minimal',
2439 None,
2440 _(
2441 'only rebuild files that are inconsistent with '
2442 'the working copy parent'
2443 ),
2444 ),
2060 ], 2445 ],
2061 _('[-r REV]')) 2446 _('[-r REV]'),
2447 )
2062 def debugrebuilddirstate(ui, repo, rev, **opts): 2448 def debugrebuilddirstate(ui, repo, rev, **opts):
2063 """rebuild the dirstate as it would look like for the given revision 2449 """rebuild the dirstate as it would look like for the given revision
2064 2450
2065 If no revision is specified the first current parent will be used. 2451 If no revision is specified the first current parent will be used.
2066 2452
2089 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a') 2475 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2090 changedfiles = manifestonly | dsnotadded 2476 changedfiles = manifestonly | dsnotadded
2091 2477
2092 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles) 2478 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2093 2479
2480
2094 @command('debugrebuildfncache', [], '') 2481 @command('debugrebuildfncache', [], '')
2095 def debugrebuildfncache(ui, repo): 2482 def debugrebuildfncache(ui, repo):
2096 """rebuild the fncache file""" 2483 """rebuild the fncache file"""
2097 repair.rebuildfncache(ui, repo) 2484 repair.rebuildfncache(ui, repo)
2098 2485
2099 @command('debugrename', 2486
2487 @command(
2488 'debugrename',
2100 [('r', 'rev', '', _('revision to debug'), _('REV'))], 2489 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2101 _('[-r REV] [FILE]...')) 2490 _('[-r REV] [FILE]...'),
2491 )
2102 def debugrename(ui, repo, *pats, **opts): 2492 def debugrename(ui, repo, *pats, **opts):
2103 """dump rename information""" 2493 """dump rename information"""
2104 2494
2105 opts = pycompat.byteskwargs(opts) 2495 opts = pycompat.byteskwargs(opts)
2106 ctx = scmutil.revsingle(repo, opts.get('rev')) 2496 ctx = scmutil.revsingle(repo, opts.get('rev'))
2112 if o: 2502 if o:
2113 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1]))) 2503 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2114 else: 2504 else:
2115 ui.write(_("%s not renamed\n") % rel) 2505 ui.write(_("%s not renamed\n") % rel)
2116 2506
2117 @command('debugrevlog', cmdutil.debugrevlogopts + 2507
2118 [('d', 'dump', False, _('dump index data'))], 2508 @command(
2509 'debugrevlog',
2510 cmdutil.debugrevlogopts + [('d', 'dump', False, _('dump index data'))],
2119 _('-c|-m|FILE'), 2511 _('-c|-m|FILE'),
2120 optionalrepo=True) 2512 optionalrepo=True,
2513 )
2121 def debugrevlog(ui, repo, file_=None, **opts): 2514 def debugrevlog(ui, repo, file_=None, **opts):
2122 """show data and statistics about a revlog""" 2515 """show data and statistics about a revlog"""
2123 opts = pycompat.byteskwargs(opts) 2516 opts = pycompat.byteskwargs(opts)
2124 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts) 2517 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2125 2518
2126 if opts.get("dump"): 2519 if opts.get("dump"):
2127 numrevs = len(r) 2520 numrevs = len(r)
2128 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2" 2521 ui.write(
2129 " rawsize totalsize compression heads chainlen\n")) 2522 (
2523 "# rev p1rev p2rev start end deltastart base p1 p2"
2524 " rawsize totalsize compression heads chainlen\n"
2525 )
2526 )
2130 ts = 0 2527 ts = 0
2131 heads = set() 2528 heads = set()
2132 2529
2133 for rev in pycompat.xrange(numrevs): 2530 for rev in pycompat.xrange(numrevs):
2134 dbase = r.deltaparent(rev) 2531 dbase = r.deltaparent(rev)
2143 heads.add(rev) 2540 heads.add(rev)
2144 try: 2541 try:
2145 compression = ts / r.end(rev) 2542 compression = ts / r.end(rev)
2146 except ZeroDivisionError: 2543 except ZeroDivisionError:
2147 compression = 0 2544 compression = 0
2148 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d " 2545 ui.write(
2149 "%11d %5d %8d\n" % 2546 "%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2150 (rev, p1, p2, r.start(rev), r.end(rev), 2547 "%11d %5d %8d\n"
2151 r.start(dbase), r.start(cbase), 2548 % (
2152 r.start(p1), r.start(p2), 2549 rev,
2153 rs, ts, compression, len(heads), clen)) 2550 p1,
2551 p2,
2552 r.start(rev),
2553 r.end(rev),
2554 r.start(dbase),
2555 r.start(cbase),
2556 r.start(p1),
2557 r.start(p2),
2558 rs,
2559 ts,
2560 compression,
2561 len(heads),
2562 clen,
2563 )
2564 )
2154 return 0 2565 return 0
2155 2566
2156 v = r.version 2567 v = r.version
2157 format = v & 0xFFFF 2568 format = v & 0xFFFF
2158 flags = [] 2569 flags = []
2317 basedfmtstr = '%%%dd\n' 2728 basedfmtstr = '%%%dd\n'
2318 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n' 2729 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2319 2730
2320 def dfmtstr(max): 2731 def dfmtstr(max):
2321 return basedfmtstr % len(str(max)) 2732 return basedfmtstr % len(str(max))
2733
2322 def pcfmtstr(max, padding=0): 2734 def pcfmtstr(max, padding=0):
2323 return basepcfmtstr % (len(str(max)), ' ' * padding) 2735 return basepcfmtstr % (len(str(max)), ' ' * padding)
2324 2736
2325 def pcfmt(value, total): 2737 def pcfmt(value, total):
2326 if total: 2738 if total:
2327 return (value, 100 * float(value) / total) 2739 return (value, 100 * float(value) / total)
2328 else: 2740 else:
2329 return value, 100.0 2741 return value, 100.0
2330 2742
2331 ui.write(('format : %d\n') % format) 2743 ui.write('format : %d\n' % format)
2332 ui.write(('flags : %s\n') % ', '.join(flags)) 2744 ui.write('flags : %s\n' % ', '.join(flags))
2333 2745
2334 ui.write('\n') 2746 ui.write('\n')
2335 fmt = pcfmtstr(totalsize) 2747 fmt = pcfmtstr(totalsize)
2336 fmt2 = dfmtstr(totalsize) 2748 fmt2 = dfmtstr(totalsize)
2337 ui.write(('revisions : ') + fmt2 % numrevs) 2749 ui.write('revisions : ' + fmt2 % numrevs)
2338 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs)) 2750 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2339 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs)) 2751 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2340 ui.write(('revisions : ') + fmt2 % numrevs) 2752 ui.write('revisions : ' + fmt2 % numrevs)
2341 ui.write((' empty : ') + fmt % pcfmt(numempty, numrevs)) 2753 ui.write(' empty : ' + fmt % pcfmt(numempty, numrevs))
2342 ui.write((' text : ') 2754 ui.write(
2343 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)) 2755 ' text : '
2344 ui.write((' delta : ') 2756 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
2345 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)) 2757 )
2346 ui.write((' snapshot : ') + fmt % pcfmt(numfull + numsemi, numrevs)) 2758 ui.write(
2759 ' delta : '
2760 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
2761 )
2762 ui.write(' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs))
2347 for depth in sorted(numsnapdepth): 2763 for depth in sorted(numsnapdepth):
2348 ui.write((' lvl-%-3d : ' % depth) 2764 ui.write(
2349 + fmt % pcfmt(numsnapdepth[depth], numrevs)) 2765 (' lvl-%-3d : ' % depth)
2350 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs)) 2766 + fmt % pcfmt(numsnapdepth[depth], numrevs)
2351 ui.write(('revision size : ') + fmt2 % totalsize) 2767 )
2352 ui.write((' snapshot : ') 2768 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2353 + fmt % pcfmt(fulltotal + semitotal, totalsize)) 2769 ui.write('revision size : ' + fmt2 % totalsize)
2770 ui.write(' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize))
2354 for depth in sorted(numsnapdepth): 2771 for depth in sorted(numsnapdepth):
2355 ui.write((' lvl-%-3d : ' % depth) 2772 ui.write(
2356 + fmt % pcfmt(snaptotal[depth], totalsize)) 2773 (' lvl-%-3d : ' % depth)
2357 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize)) 2774 + fmt % pcfmt(snaptotal[depth], totalsize)
2775 )
2776 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2358 2777
2359 def fmtchunktype(chunktype): 2778 def fmtchunktype(chunktype):
2360 if chunktype == 'empty': 2779 if chunktype == 'empty':
2361 return ' %s : ' % chunktype 2780 return ' %s : ' % chunktype
2362 elif chunktype in pycompat.bytestr(string.ascii_letters): 2781 elif chunktype in pycompat.bytestr(string.ascii_letters):
2363 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype) 2782 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2364 else: 2783 else:
2365 return ' 0x%s : ' % hex(chunktype) 2784 return ' 0x%s : ' % hex(chunktype)
2366 2785
2367 ui.write('\n') 2786 ui.write('\n')
2368 ui.write(('chunks : ') + fmt2 % numrevs) 2787 ui.write('chunks : ' + fmt2 % numrevs)
2369 for chunktype in sorted(chunktypecounts): 2788 for chunktype in sorted(chunktypecounts):
2370 ui.write(fmtchunktype(chunktype)) 2789 ui.write(fmtchunktype(chunktype))
2371 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs)) 2790 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2372 ui.write(('chunks size : ') + fmt2 % totalsize) 2791 ui.write('chunks size : ' + fmt2 % totalsize)
2373 for chunktype in sorted(chunktypecounts): 2792 for chunktype in sorted(chunktypecounts):
2374 ui.write(fmtchunktype(chunktype)) 2793 ui.write(fmtchunktype(chunktype))
2375 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize)) 2794 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2376 2795
2377 ui.write('\n') 2796 ui.write('\n')
2378 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio)) 2797 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2379 ui.write(('avg chain length : ') + fmt % avgchainlen) 2798 ui.write('avg chain length : ' + fmt % avgchainlen)
2380 ui.write(('max chain length : ') + fmt % maxchainlen) 2799 ui.write('max chain length : ' + fmt % maxchainlen)
2381 ui.write(('max chain reach : ') + fmt % maxchainspan) 2800 ui.write('max chain reach : ' + fmt % maxchainspan)
2382 ui.write(('compression ratio : ') + fmt % compratio) 2801 ui.write('compression ratio : ' + fmt % compratio)
2383 2802
2384 if format > 0: 2803 if format > 0:
2385 ui.write('\n') 2804 ui.write('\n')
2386 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n') 2805 ui.write(
2387 % tuple(datasize)) 2806 'uncompressed data size (min/max/avg) : %d / %d / %d\n'
2388 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n') 2807 % tuple(datasize)
2389 % tuple(fullsize)) 2808 )
2390 ui.write(('inter-snapshot size (min/max/avg) : %d / %d / %d\n') 2809 ui.write(
2391 % tuple(semisize)) 2810 'full revision size (min/max/avg) : %d / %d / %d\n'
2811 % tuple(fullsize)
2812 )
2813 ui.write(
2814 'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
2815 % tuple(semisize)
2816 )
2392 for depth in sorted(snapsizedepth): 2817 for depth in sorted(snapsizedepth):
2393 if depth == 0: 2818 if depth == 0:
2394 continue 2819 continue
2395 ui.write((' level-%-3d (min/max/avg) : %d / %d / %d\n') 2820 ui.write(
2396 % ((depth,) + tuple(snapsizedepth[depth]))) 2821 ' level-%-3d (min/max/avg) : %d / %d / %d\n'
2397 ui.write(('delta size (min/max/avg) : %d / %d / %d\n') 2822 % ((depth,) + tuple(snapsizedepth[depth]))
2398 % tuple(deltasize)) 2823 )
2824 ui.write(
2825 'delta size (min/max/avg) : %d / %d / %d\n'
2826 % tuple(deltasize)
2827 )
2399 2828
2400 if numdeltas > 0: 2829 if numdeltas > 0:
2401 ui.write('\n') 2830 ui.write('\n')
2402 fmt = pcfmtstr(numdeltas) 2831 fmt = pcfmtstr(numdeltas)
2403 fmt2 = pcfmtstr(numdeltas, 4) 2832 fmt2 = pcfmtstr(numdeltas, 4)
2404 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas)) 2833 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2405 if numprev > 0: 2834 if numprev > 0:
2406 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev, 2835 ui.write(
2407 numprev)) 2836 ' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
2408 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev, 2837 )
2409 numprev)) 2838 ui.write(
2410 ui.write((' other : ') + fmt2 % pcfmt(numoprev, 2839 ' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
2411 numprev)) 2840 )
2841 ui.write(
2842 ' other : ' + fmt2 % pcfmt(numoprev, numprev)
2843 )
2412 if gdelta: 2844 if gdelta:
2413 ui.write(('deltas against p1 : ') 2845 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2414 + fmt % pcfmt(nump1, numdeltas)) 2846 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2415 ui.write(('deltas against p2 : ') 2847 ui.write(
2416 + fmt % pcfmt(nump2, numdeltas)) 2848 'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
2417 ui.write(('deltas against other : ') + fmt % pcfmt(numother, 2849 )
2418 numdeltas)) 2850
2419 2851
2420 @command('debugrevlogindex', cmdutil.debugrevlogopts + 2852 @command(
2421 [('f', 'format', 0, _('revlog format'), _('FORMAT'))], 2853 'debugrevlogindex',
2854 cmdutil.debugrevlogopts
2855 + [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2422 _('[-f FORMAT] -c|-m|FILE'), 2856 _('[-f FORMAT] -c|-m|FILE'),
2423 optionalrepo=True) 2857 optionalrepo=True,
2858 )
2424 def debugrevlogindex(ui, repo, file_=None, **opts): 2859 def debugrevlogindex(ui, repo, file_=None, **opts):
2425 """dump the contents of a revlog index""" 2860 """dump the contents of a revlog index"""
2426 opts = pycompat.byteskwargs(opts) 2861 opts = pycompat.byteskwargs(opts)
2427 r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts) 2862 r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
2428 format = opts.get('format', 0) 2863 format = opts.get('format', 0)
2440 idlen = len(shortfn(r.node(i))) 2875 idlen = len(shortfn(r.node(i)))
2441 break 2876 break
2442 2877
2443 if format == 0: 2878 if format == 0:
2444 if ui.verbose: 2879 if ui.verbose:
2445 ui.write((" rev offset length linkrev" 2880 ui.write(
2446 " %s %s p2\n") % ("nodeid".ljust(idlen), 2881 (" rev offset length linkrev" " %s %s p2\n")
2447 "p1".ljust(idlen))) 2882 % ("nodeid".ljust(idlen), "p1".ljust(idlen))
2883 )
2448 else: 2884 else:
2449 ui.write((" rev linkrev %s %s p2\n") % ( 2885 ui.write(
2450 "nodeid".ljust(idlen), "p1".ljust(idlen))) 2886 " rev linkrev %s %s p2\n"
2887 % ("nodeid".ljust(idlen), "p1".ljust(idlen))
2888 )
2451 elif format == 1: 2889 elif format == 1:
2452 if ui.verbose: 2890 if ui.verbose:
2453 ui.write((" rev flag offset length size link p1" 2891 ui.write(
2454 " p2 %s\n") % "nodeid".rjust(idlen)) 2892 (
2893 " rev flag offset length size link p1"
2894 " p2 %s\n"
2895 )
2896 % "nodeid".rjust(idlen)
2897 )
2455 else: 2898 else:
2456 ui.write((" rev flag size link p1 p2 %s\n") % 2899 ui.write(
2457 "nodeid".rjust(idlen)) 2900 " rev flag size link p1 p2 %s\n"
2901 % "nodeid".rjust(idlen)
2902 )
2458 2903
2459 for i in r: 2904 for i in r:
2460 node = r.node(i) 2905 node = r.node(i)
2461 if format == 0: 2906 if format == 0:
2462 try: 2907 try:
2463 pp = r.parents(node) 2908 pp = r.parents(node)
2464 except Exception: 2909 except Exception:
2465 pp = [nullid, nullid] 2910 pp = [nullid, nullid]
2466 if ui.verbose: 2911 if ui.verbose:
2467 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % ( 2912 ui.write(
2468 i, r.start(i), r.length(i), r.linkrev(i), 2913 "% 6d % 9d % 7d % 7d %s %s %s\n"
2469 shortfn(node), shortfn(pp[0]), shortfn(pp[1]))) 2914 % (
2915 i,
2916 r.start(i),
2917 r.length(i),
2918 r.linkrev(i),
2919 shortfn(node),
2920 shortfn(pp[0]),
2921 shortfn(pp[1]),
2922 )
2923 )
2470 else: 2924 else:
2471 ui.write("% 6d % 7d %s %s %s\n" % ( 2925 ui.write(
2472 i, r.linkrev(i), shortfn(node), shortfn(pp[0]), 2926 "% 6d % 7d %s %s %s\n"
2473 shortfn(pp[1]))) 2927 % (
2928 i,
2929 r.linkrev(i),
2930 shortfn(node),
2931 shortfn(pp[0]),
2932 shortfn(pp[1]),
2933 )
2934 )
2474 elif format == 1: 2935 elif format == 1:
2475 pr = r.parentrevs(i) 2936 pr = r.parentrevs(i)
2476 if ui.verbose: 2937 if ui.verbose:
2477 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % ( 2938 ui.write(
2478 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i), 2939 "% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
2479 r.linkrev(i), pr[0], pr[1], shortfn(node))) 2940 % (
2941 i,
2942 r.flags(i),
2943 r.start(i),
2944 r.length(i),
2945 r.rawsize(i),
2946 r.linkrev(i),
2947 pr[0],
2948 pr[1],
2949 shortfn(node),
2950 )
2951 )
2480 else: 2952 else:
2481 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % ( 2953 ui.write(
2482 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1], 2954 "% 6d %04x % 8d % 6d % 6d % 6d %s\n"
2483 shortfn(node))) 2955 % (
2484 2956 i,
2485 @command('debugrevspec', 2957 r.flags(i),
2486 [('', 'optimize', None, 2958 r.rawsize(i),
2487 _('print parsed tree after optimizing (DEPRECATED)')), 2959 r.linkrev(i),
2488 ('', 'show-revs', True, _('print list of result revisions (default)')), 2960 pr[0],
2489 ('s', 'show-set', None, _('print internal representation of result set')), 2961 pr[1],
2490 ('p', 'show-stage', [], 2962 shortfn(node),
2491 _('print parsed tree at the given stage'), _('NAME')), 2963 )
2492 ('', 'no-optimized', False, _('evaluate tree without optimization')), 2964 )
2493 ('', 'verify-optimized', False, _('verify optimized result')), 2965
2494 ], 2966
2495 ('REVSPEC')) 2967 @command(
2968 'debugrevspec',
2969 [
2970 (
2971 '',
2972 'optimize',
2973 None,
2974 _('print parsed tree after optimizing (DEPRECATED)'),
2975 ),
2976 ('', 'show-revs', True, _('print list of result revisions (default)')),
2977 (
2978 's',
2979 'show-set',
2980 None,
2981 _('print internal representation of result set'),
2982 ),
2983 (
2984 'p',
2985 'show-stage',
2986 [],
2987 _('print parsed tree at the given stage'),
2988 _('NAME'),
2989 ),
2990 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2991 ('', 'verify-optimized', False, _('verify optimized result')),
2992 ],
2993 'REVSPEC',
2994 )
2496 def debugrevspec(ui, repo, expr, **opts): 2995 def debugrevspec(ui, repo, expr, **opts):
2497 """parse and apply a revision specification 2996 """parse and apply a revision specification
2498 2997
2499 Use -p/--show-stage option to print the parsed tree at the given stages. 2998 Use -p/--show-stage option to print the parsed tree at the given stages.
2500 Use -p all to print tree at every stage. 2999 Use -p all to print tree at every stage.
2507 """ 3006 """
2508 opts = pycompat.byteskwargs(opts) 3007 opts = pycompat.byteskwargs(opts)
2509 aliases = ui.configitems('revsetalias') 3008 aliases = ui.configitems('revsetalias')
2510 stages = [ 3009 stages = [
2511 ('parsed', lambda tree: tree), 3010 ('parsed', lambda tree: tree),
2512 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases, 3011 (
2513 ui.warn)), 3012 'expanded',
3013 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3014 ),
2514 ('concatenated', revsetlang.foldconcat), 3015 ('concatenated', revsetlang.foldconcat),
2515 ('analyzed', revsetlang.analyze), 3016 ('analyzed', revsetlang.analyze),
2516 ('optimized', revsetlang.optimize), 3017 ('optimized', revsetlang.optimize),
2517 ] 3018 ]
2518 if opts['no_optimized']: 3019 if opts['no_optimized']:
2519 stages = stages[:-1] 3020 stages = stages[:-1]
2520 if opts['verify_optimized'] and opts['no_optimized']: 3021 if opts['verify_optimized'] and opts['no_optimized']:
2521 raise error.Abort(_('cannot use --verify-optimized with ' 3022 raise error.Abort(
2522 '--no-optimized')) 3023 _('cannot use --verify-optimized with ' '--no-optimized')
3024 )
2523 stagenames = set(n for n, f in stages) 3025 stagenames = set(n for n, f in stages)
2524 3026
2525 showalways = set() 3027 showalways = set()
2526 showchanged = set() 3028 showchanged = set()
2527 if ui.verbose and not opts['show_stage']: 3029 if ui.verbose and not opts['show_stage']:
2545 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo)) 3047 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2546 for n, f in stages: 3048 for n, f in stages:
2547 treebystage[n] = tree = f(tree) 3049 treebystage[n] = tree = f(tree)
2548 if n in showalways or (n in showchanged and tree != printedtree): 3050 if n in showalways or (n in showchanged and tree != printedtree):
2549 if opts['show_stage'] or n != 'parsed': 3051 if opts['show_stage'] or n != 'parsed':
2550 ui.write(("* %s:\n") % n) 3052 ui.write("* %s:\n" % n)
2551 ui.write(revsetlang.prettyformat(tree), "\n") 3053 ui.write(revsetlang.prettyformat(tree), "\n")
2552 printedtree = tree 3054 printedtree = tree
2553 3055
2554 if opts['verify_optimized']: 3056 if opts['verify_optimized']:
2555 arevs = revset.makematcher(treebystage['analyzed'])(repo) 3057 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2556 brevs = revset.makematcher(treebystage['optimized'])(repo) 3058 brevs = revset.makematcher(treebystage['optimized'])(repo)
2557 if opts['show_set'] or (opts['show_set'] is None and ui.verbose): 3059 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2558 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n") 3060 ui.write("* analyzed set:\n", stringutil.prettyrepr(arevs), "\n")
2559 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n") 3061 ui.write("* optimized set:\n", stringutil.prettyrepr(brevs), "\n")
2560 arevs = list(arevs) 3062 arevs = list(arevs)
2561 brevs = list(brevs) 3063 brevs = list(brevs)
2562 if arevs == brevs: 3064 if arevs == brevs:
2563 return 0 3065 return 0
2564 ui.write(('--- analyzed\n'), label='diff.file_a') 3066 ui.write('--- analyzed\n', label='diff.file_a')
2565 ui.write(('+++ optimized\n'), label='diff.file_b') 3067 ui.write('+++ optimized\n', label='diff.file_b')
2566 sm = difflib.SequenceMatcher(None, arevs, brevs) 3068 sm = difflib.SequenceMatcher(None, arevs, brevs)
2567 for tag, alo, ahi, blo, bhi in sm.get_opcodes(): 3069 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2568 if tag in (r'delete', r'replace'): 3070 if tag in (r'delete', r'replace'):
2569 for c in arevs[alo:ahi]: 3071 for c in arevs[alo:ahi]:
2570 ui.write('-%d\n' % c, label='diff.deleted') 3072 ui.write('-%d\n' % c, label='diff.deleted')
2577 return 1 3079 return 1
2578 3080
2579 func = revset.makematcher(tree) 3081 func = revset.makematcher(tree)
2580 revs = func(repo) 3082 revs = func(repo)
2581 if opts['show_set'] or (opts['show_set'] is None and ui.verbose): 3083 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2582 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n") 3084 ui.write("* set:\n", stringutil.prettyrepr(revs), "\n")
2583 if not opts['show_revs']: 3085 if not opts['show_revs']:
2584 return 3086 return
2585 for c in revs: 3087 for c in revs:
2586 ui.write("%d\n" % c) 3088 ui.write("%d\n" % c)
2587 3089
2588 @command('debugserve', [ 3090
2589 ('', 'sshstdio', False, _('run an SSH server bound to process handles')), 3091 @command(
2590 ('', 'logiofd', '', _('file descriptor to log server I/O to')), 3092 'debugserve',
2591 ('', 'logiofile', '', _('file to log server I/O to')), 3093 [
2592 ], '') 3094 (
3095 '',
3096 'sshstdio',
3097 False,
3098 _('run an SSH server bound to process handles'),
3099 ),
3100 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
3101 ('', 'logiofile', '', _('file to log server I/O to')),
3102 ],
3103 '',
3104 )
2593 def debugserve(ui, repo, **opts): 3105 def debugserve(ui, repo, **opts):
2594 """run a server with advanced settings 3106 """run a server with advanced settings
2595 3107
2596 This command is similar to :hg:`serve`. It exists partially as a 3108 This command is similar to :hg:`serve`. It exists partially as a
2597 workaround to the fact that ``hg serve --stdio`` must have specific 3109 workaround to the fact that ``hg serve --stdio`` must have specific
2620 logfh = open(opts['logiofile'], 'ab', 1) 3132 logfh = open(opts['logiofile'], 'ab', 1)
2621 3133
2622 s = wireprotoserver.sshserver(ui, repo, logfh=logfh) 3134 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2623 s.serve_forever() 3135 s.serve_forever()
2624 3136
3137
2625 @command('debugsetparents', [], _('REV1 [REV2]')) 3138 @command('debugsetparents', [], _('REV1 [REV2]'))
2626 def debugsetparents(ui, repo, rev1, rev2=None): 3139 def debugsetparents(ui, repo, rev1, rev2=None):
2627 """manually set the parents of the current working directory 3140 """manually set the parents of the current working directory
2628 3141
2629 This is useful for writing repository conversion tools, but should 3142 This is useful for writing repository conversion tools, but should
2637 node1 = scmutil.revsingle(repo, rev1).node() 3150 node1 = scmutil.revsingle(repo, rev1).node()
2638 node2 = scmutil.revsingle(repo, rev2, 'null').node() 3151 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2639 3152
2640 with repo.wlock(): 3153 with repo.wlock():
2641 repo.setparents(node1, node2) 3154 repo.setparents(node1, node2)
3155
2642 3156
2643 @command('debugsidedata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV')) 3157 @command('debugsidedata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
2644 def debugsidedata(ui, repo, file_, rev=None, **opts): 3158 def debugsidedata(ui, repo, file_, rev=None, **opts):
2645 """dump the side data for a cl/manifest/file revision""" 3159 """dump the side data for a cl/manifest/file revision"""
2646 opts = pycompat.byteskwargs(opts) 3160 opts = pycompat.byteskwargs(opts)
2663 for key, value in sidedata: 3177 for key, value in sidedata:
2664 ui.write((' entry-%04o size %d\n' % (key, len(value)))) 3178 ui.write((' entry-%04o size %d\n' % (key, len(value))))
2665 if ui.verbose: 3179 if ui.verbose:
2666 ui.write((' %s\n' % stringutil.pprint(value))) 3180 ui.write((' %s\n' % stringutil.pprint(value)))
2667 3181
3182
2668 @command('debugssl', [], '[SOURCE]', optionalrepo=True) 3183 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2669 def debugssl(ui, repo, source=None, **opts): 3184 def debugssl(ui, repo, source=None, **opts):
2670 '''test a secure connection to a server 3185 '''test a secure connection to a server
2671 3186
2672 This builds the certificate chain for the server on Windows, installing the 3187 This builds the certificate chain for the server on Windows, installing the
2678 3193
2679 If the update succeeds, retry the original operation. Otherwise, the cause 3194 If the update succeeds, retry the original operation. Otherwise, the cause
2680 of the SSL error is likely another issue. 3195 of the SSL error is likely another issue.
2681 ''' 3196 '''
2682 if not pycompat.iswindows: 3197 if not pycompat.iswindows:
2683 raise error.Abort(_('certificate chain building is only possible on ' 3198 raise error.Abort(
2684 'Windows')) 3199 _('certificate chain building is only possible on ' 'Windows')
3200 )
2685 3201
2686 if not source: 3202 if not source:
2687 if not repo: 3203 if not repo:
2688 raise error.Abort(_("there is no Mercurial repository here, and no " 3204 raise error.Abort(
2689 "server specified")) 3205 _(
3206 "there is no Mercurial repository here, and no "
3207 "server specified"
3208 )
3209 )
2690 source = "default" 3210 source = "default"
2691 3211
2692 source, branches = hg.parseurl(ui.expandpath(source)) 3212 source, branches = hg.parseurl(ui.expandpath(source))
2693 url = util.url(source) 3213 url = util.url(source)
2694 3214
2701 else: 3221 else:
2702 raise error.Abort(_("only https and ssh connections are supported")) 3222 raise error.Abort(_("only https and ssh connections are supported"))
2703 3223
2704 from . import win32 3224 from . import win32
2705 3225
2706 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS, 3226 s = ssl.wrap_socket(
2707 cert_reqs=ssl.CERT_NONE, ca_certs=None) 3227 socket.socket(),
3228 ssl_version=ssl.PROTOCOL_TLS,
3229 cert_reqs=ssl.CERT_NONE,
3230 ca_certs=None,
3231 )
2708 3232
2709 try: 3233 try:
2710 s.connect(addr) 3234 s.connect(addr)
2711 cert = s.getpeercert(True) 3235 cert = s.getpeercert(True)
2712 3236
2724 else: 3248 else:
2725 ui.status(_('full certificate chain is available\n')) 3249 ui.status(_('full certificate chain is available\n'))
2726 finally: 3250 finally:
2727 s.close() 3251 s.close()
2728 3252
2729 @command('debugsub', 3253
2730 [('r', 'rev', '', 3254 @command(
2731 _('revision to check'), _('REV'))], 3255 'debugsub',
2732 _('[-r REV] [REV]')) 3256 [('r', 'rev', '', _('revision to check'), _('REV'))],
3257 _('[-r REV] [REV]'),
3258 )
2733 def debugsub(ui, repo, rev=None): 3259 def debugsub(ui, repo, rev=None):
2734 ctx = scmutil.revsingle(repo, rev, None) 3260 ctx = scmutil.revsingle(repo, rev, None)
2735 for k, v in sorted(ctx.substate.items()): 3261 for k, v in sorted(ctx.substate.items()):
2736 ui.write(('path %s\n') % k) 3262 ui.write('path %s\n' % k)
2737 ui.write((' source %s\n') % v[0]) 3263 ui.write(' source %s\n' % v[0])
2738 ui.write((' revision %s\n') % v[1]) 3264 ui.write(' revision %s\n' % v[1])
2739 3265
2740 @command('debugsuccessorssets', 3266
3267 @command(
3268 'debugsuccessorssets',
2741 [('', 'closest', False, _('return closest successors sets only'))], 3269 [('', 'closest', False, _('return closest successors sets only'))],
2742 _('[REV]')) 3270 _('[REV]'),
3271 )
2743 def debugsuccessorssets(ui, repo, *revs, **opts): 3272 def debugsuccessorssets(ui, repo, *revs, **opts):
2744 """show set of successors for revision 3273 """show set of successors for revision
2745 3274
2746 A successors set of changeset A is a consistent group of revisions that 3275 A successors set of changeset A is a consistent group of revisions that
2747 succeed A. It contains non-obsolete changesets only unless closests 3276 succeed A. It contains non-obsolete changesets only unless closests
2776 cache = {} 3305 cache = {}
2777 ctx2str = bytes 3306 ctx2str = bytes
2778 node2str = short 3307 node2str = short
2779 for rev in scmutil.revrange(repo, revs): 3308 for rev in scmutil.revrange(repo, revs):
2780 ctx = repo[rev] 3309 ctx = repo[rev]
2781 ui.write('%s\n'% ctx2str(ctx)) 3310 ui.write('%s\n' % ctx2str(ctx))
2782 for succsset in obsutil.successorssets(repo, ctx.node(), 3311 for succsset in obsutil.successorssets(
2783 closest=opts[r'closest'], 3312 repo, ctx.node(), closest=opts[r'closest'], cache=cache
2784 cache=cache): 3313 ):
2785 if succsset: 3314 if succsset:
2786 ui.write(' ') 3315 ui.write(' ')
2787 ui.write(node2str(succsset[0])) 3316 ui.write(node2str(succsset[0]))
2788 for node in succsset[1:]: 3317 for node in succsset[1:]:
2789 ui.write(' ') 3318 ui.write(' ')
2790 ui.write(node2str(node)) 3319 ui.write(node2str(node))
2791 ui.write('\n') 3320 ui.write('\n')
2792 3321
2793 @command('debugtemplate', 3322
2794 [('r', 'rev', [], _('apply template on changesets'), _('REV')), 3323 @command(
2795 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))], 3324 'debugtemplate',
3325 [
3326 ('r', 'rev', [], _('apply template on changesets'), _('REV')),
3327 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE')),
3328 ],
2796 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'), 3329 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2797 optionalrepo=True) 3330 optionalrepo=True,
3331 )
2798 def debugtemplate(ui, repo, tmpl, **opts): 3332 def debugtemplate(ui, repo, tmpl, **opts):
2799 """parse and apply a template 3333 """parse and apply a template
2800 3334
2801 If -r/--rev is given, the template is processed as a log template and 3335 If -r/--rev is given, the template is processed as a log template and
2802 applied to the given changesets. Otherwise, it is processed as a generic 3336 applied to the given changesets. Otherwise, it is processed as a generic
2805 Use --verbose to print the parsed tree. 3339 Use --verbose to print the parsed tree.
2806 """ 3340 """
2807 revs = None 3341 revs = None
2808 if opts[r'rev']: 3342 if opts[r'rev']:
2809 if repo is None: 3343 if repo is None:
2810 raise error.RepoError(_('there is no Mercurial repository here ' 3344 raise error.RepoError(
2811 '(.hg not found)')) 3345 _('there is no Mercurial repository here ' '(.hg not found)')
3346 )
2812 revs = scmutil.revrange(repo, opts[r'rev']) 3347 revs = scmutil.revrange(repo, opts[r'rev'])
2813 3348
2814 props = {} 3349 props = {}
2815 for d in opts[r'define']: 3350 for d in opts[r'define']:
2816 try: 3351 try:
2825 aliases = ui.configitems('templatealias') 3360 aliases = ui.configitems('templatealias')
2826 tree = templater.parse(tmpl) 3361 tree = templater.parse(tmpl)
2827 ui.note(templater.prettyformat(tree), '\n') 3362 ui.note(templater.prettyformat(tree), '\n')
2828 newtree = templater.expandaliases(tree, aliases) 3363 newtree = templater.expandaliases(tree, aliases)
2829 if newtree != tree: 3364 if newtree != tree:
2830 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n') 3365 ui.note("* expanded:\n", templater.prettyformat(newtree), '\n')
2831 3366
2832 if revs is None: 3367 if revs is None:
2833 tres = formatter.templateresources(ui, repo) 3368 tres = formatter.templateresources(ui, repo)
2834 t = formatter.maketemplater(ui, tmpl, resources=tres) 3369 t = formatter.maketemplater(ui, tmpl, resources=tres)
2835 if ui.verbose: 3370 if ui.verbose:
2836 kwds, funcs = t.symbolsuseddefault() 3371 kwds, funcs = t.symbolsuseddefault()
2837 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds))) 3372 ui.write("* keywords: %s\n" % ', '.join(sorted(kwds)))
2838 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs))) 3373 ui.write("* functions: %s\n" % ', '.join(sorted(funcs)))
2839 ui.write(t.renderdefault(props)) 3374 ui.write(t.renderdefault(props))
2840 else: 3375 else:
2841 displayer = logcmdutil.maketemplater(ui, repo, tmpl) 3376 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2842 if ui.verbose: 3377 if ui.verbose:
2843 kwds, funcs = displayer.t.symbolsuseddefault() 3378 kwds, funcs = displayer.t.symbolsuseddefault()
2844 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds))) 3379 ui.write("* keywords: %s\n" % ', '.join(sorted(kwds)))
2845 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs))) 3380 ui.write("* functions: %s\n" % ', '.join(sorted(funcs)))
2846 for r in revs: 3381 for r in revs:
2847 displayer.show(repo[r], **pycompat.strkwargs(props)) 3382 displayer.show(repo[r], **pycompat.strkwargs(props))
2848 displayer.close() 3383 displayer.close()
2849 3384
2850 @command('debuguigetpass', [ 3385
2851 ('p', 'prompt', '', _('prompt text'), _('TEXT')), 3386 @command(
2852 ], _('[-p TEXT]'), norepo=True) 3387 'debuguigetpass',
3388 [('p', 'prompt', '', _('prompt text'), _('TEXT')),],
3389 _('[-p TEXT]'),
3390 norepo=True,
3391 )
2853 def debuguigetpass(ui, prompt=''): 3392 def debuguigetpass(ui, prompt=''):
2854 """show prompt to type password""" 3393 """show prompt to type password"""
2855 r = ui.getpass(prompt) 3394 r = ui.getpass(prompt)
2856 ui.write(('respose: %s\n') % r) 3395 ui.write('respose: %s\n' % r)
2857 3396
2858 @command('debuguiprompt', [ 3397
2859 ('p', 'prompt', '', _('prompt text'), _('TEXT')), 3398 @command(
2860 ], _('[-p TEXT]'), norepo=True) 3399 'debuguiprompt',
3400 [('p', 'prompt', '', _('prompt text'), _('TEXT')),],
3401 _('[-p TEXT]'),
3402 norepo=True,
3403 )
2861 def debuguiprompt(ui, prompt=''): 3404 def debuguiprompt(ui, prompt=''):
2862 """show plain prompt""" 3405 """show plain prompt"""
2863 r = ui.prompt(prompt) 3406 r = ui.prompt(prompt)
2864 ui.write(('response: %s\n') % r) 3407 ui.write('response: %s\n' % r)
3408
2865 3409
2866 @command('debugupdatecaches', []) 3410 @command('debugupdatecaches', [])
2867 def debugupdatecaches(ui, repo, *pats, **opts): 3411 def debugupdatecaches(ui, repo, *pats, **opts):
2868 """warm all known caches in the repository""" 3412 """warm all known caches in the repository"""
2869 with repo.wlock(), repo.lock(): 3413 with repo.wlock(), repo.lock():
2870 repo.updatecaches(full=True) 3414 repo.updatecaches(full=True)
2871 3415
2872 @command('debugupgraderepo', [ 3416
2873 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')), 3417 @command(
2874 ('', 'run', False, _('performs an upgrade')), 3418 'debugupgraderepo',
2875 ('', 'backup', True, _('keep the old repository content around')), 3419 [
2876 ('', 'changelog', None, _('select the changelog for upgrade')), 3420 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2877 ('', 'manifest', None, _('select the manifest for upgrade')), 3421 ('', 'run', False, _('performs an upgrade')),
2878 ]) 3422 ('', 'backup', True, _('keep the old repository content around')),
3423 ('', 'changelog', None, _('select the changelog for upgrade')),
3424 ('', 'manifest', None, _('select the manifest for upgrade')),
3425 ],
3426 )
2879 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts): 3427 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
2880 """upgrade a repository to use different features 3428 """upgrade a repository to use different features
2881 3429
2882 If no arguments are specified, the repository is evaluated for upgrade 3430 If no arguments are specified, the repository is evaluated for upgrade
2883 and a list of problems and potential optimizations is printed. 3431 and a list of problems and potential optimizations is printed.
2901 * `--manifest`: only optimize the manifest 3449 * `--manifest`: only optimize the manifest
2902 * `--no-manifest`: optimize all revlog but the manifest 3450 * `--no-manifest`: optimize all revlog but the manifest
2903 * `--changelog`: optimize the changelog only 3451 * `--changelog`: optimize the changelog only
2904 * `--no-changelog --no-manifest`: optimize filelogs only 3452 * `--no-changelog --no-manifest`: optimize filelogs only
2905 """ 3453 """
2906 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize, 3454 return upgrade.upgraderepo(
2907 backup=backup, **opts) 3455 ui, repo, run=run, optimize=optimize, backup=backup, **opts
2908 3456 )
2909 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'), 3457
2910 inferrepo=True) 3458
3459 @command(
3460 'debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'), inferrepo=True
3461 )
2911 def debugwalk(ui, repo, *pats, **opts): 3462 def debugwalk(ui, repo, *pats, **opts):
2912 """show how files match on given patterns""" 3463 """show how files match on given patterns"""
2913 opts = pycompat.byteskwargs(opts) 3464 opts = pycompat.byteskwargs(opts)
2914 m = scmutil.match(repo[None], pats, opts) 3465 m = scmutil.match(repo[None], pats, opts)
2915 if ui.verbose: 3466 if ui.verbose:
2916 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n') 3467 ui.write('* matcher:\n', stringutil.prettyrepr(m), '\n')
2917 items = list(repo[None].walk(m)) 3468 items = list(repo[None].walk(m))
2918 if not items: 3469 if not items:
2919 return 3470 return
2920 f = lambda fn: fn 3471 f = lambda fn: fn
2921 if ui.configbool('ui', 'slash') and pycompat.ossep != '/': 3472 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2922 f = lambda fn: util.normpath(fn) 3473 f = lambda fn: util.normpath(fn)
2923 fmt = 'f %%-%ds %%-%ds %%s' % ( 3474 fmt = 'f %%-%ds %%-%ds %%s' % (
2924 max([len(abs) for abs in items]), 3475 max([len(abs) for abs in items]),
2925 max([len(repo.pathto(abs)) for abs in items])) 3476 max([len(repo.pathto(abs)) for abs in items]),
3477 )
2926 for abs in items: 3478 for abs in items:
2927 line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and 'exact' or '') 3479 line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and 'exact' or '')
2928 ui.write("%s\n" % line.rstrip()) 3480 ui.write("%s\n" % line.rstrip())
3481
2929 3482
2930 @command('debugwhyunstable', [], _('REV')) 3483 @command('debugwhyunstable', [], _('REV'))
2931 def debugwhyunstable(ui, repo, rev): 3484 def debugwhyunstable(ui, repo, rev):
2932 """explain instabilities of a changeset""" 3485 """explain instabilities of a changeset"""
2933 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)): 3486 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2934 dnodes = '' 3487 dnodes = ''
2935 if entry.get('divergentnodes'): 3488 if entry.get('divergentnodes'):
2936 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr()) 3489 dnodes = (
2937 for ctx in entry['divergentnodes']) + ' ' 3490 ' '.join(
2938 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes, 3491 '%s (%s)' % (ctx.hex(), ctx.phasestr())
2939 entry['reason'], entry['node'])) 3492 for ctx in entry['divergentnodes']
2940 3493 )
2941 @command('debugwireargs', 3494 + ' '
2942 [('', 'three', '', 'three'), 3495 )
2943 ('', 'four', '', 'four'), 3496 ui.write(
2944 ('', 'five', '', 'five'), 3497 '%s: %s%s %s\n'
2945 ] + cmdutil.remoteopts, 3498 % (entry['instability'], dnodes, entry['reason'], entry['node'])
3499 )
3500
3501
3502 @command(
3503 'debugwireargs',
3504 [
3505 ('', 'three', '', 'three'),
3506 ('', 'four', '', 'four'),
3507 ('', 'five', '', 'five'),
3508 ]
3509 + cmdutil.remoteopts,
2946 _('REPO [OPTIONS]... [ONE [TWO]]'), 3510 _('REPO [OPTIONS]... [ONE [TWO]]'),
2947 norepo=True) 3511 norepo=True,
3512 )
2948 def debugwireargs(ui, repopath, *vals, **opts): 3513 def debugwireargs(ui, repopath, *vals, **opts):
2949 opts = pycompat.byteskwargs(opts) 3514 opts = pycompat.byteskwargs(opts)
2950 repo = hg.peer(ui, opts, repopath) 3515 repo = hg.peer(ui, opts, repopath)
2951 for opt in cmdutil.remoteopts: 3516 for opt in cmdutil.remoteopts:
2952 del opts[opt[1]] 3517 del opts[opt[1]]
2960 res2 = repo.debugwireargs(*vals, **args) 3525 res2 = repo.debugwireargs(*vals, **args)
2961 ui.write("%s\n" % res1) 3526 ui.write("%s\n" % res1)
2962 if res1 != res2: 3527 if res1 != res2:
2963 ui.warn("%s\n" % res2) 3528 ui.warn("%s\n" % res2)
2964 3529
3530
2965 def _parsewirelangblocks(fh): 3531 def _parsewirelangblocks(fh):
2966 activeaction = None 3532 activeaction = None
2967 blocklines = [] 3533 blocklines = []
2968 lastindent = 0 3534 lastindent = 0
2969 3535
3001 3567
3002 # Flush last block. 3568 # Flush last block.
3003 if activeaction: 3569 if activeaction:
3004 yield activeaction, blocklines 3570 yield activeaction, blocklines
3005 3571
3006 @command('debugwireproto', 3572
3573 @command(
3574 'debugwireproto',
3007 [ 3575 [
3008 ('', 'localssh', False, _('start an SSH server for this repo')), 3576 ('', 'localssh', False, _('start an SSH server for this repo')),
3009 ('', 'peer', '', _('construct a specific version of the peer')), 3577 ('', 'peer', '', _('construct a specific version of the peer')),
3010 ('', 'noreadstderr', False, _('do not read from stderr of the remote')), 3578 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
3011 ('', 'nologhandshake', False, 3579 (
3012 _('do not log I/O related to the peer handshake')), 3580 '',
3013 ] + cmdutil.remoteopts, 3581 'nologhandshake',
3582 False,
3583 _('do not log I/O related to the peer handshake'),
3584 ),
3585 ]
3586 + cmdutil.remoteopts,
3014 _('[PATH]'), 3587 _('[PATH]'),
3015 optionalrepo=True) 3588 optionalrepo=True,
3589 )
3016 def debugwireproto(ui, repo, path=None, **opts): 3590 def debugwireproto(ui, repo, path=None, **opts):
3017 """send wire protocol commands to a server 3591 """send wire protocol commands to a server
3018 3592
3019 This command can be used to issue wire protocol commands to remote 3593 This command can be used to issue wire protocol commands to remote
3020 peers and to debug the raw data being exchanged. 3594 peers and to debug the raw data being exchanged.
3198 3772
3199 if opts['localssh'] and not repo: 3773 if opts['localssh'] and not repo:
3200 raise error.Abort(_('--localssh requires a repository')) 3774 raise error.Abort(_('--localssh requires a repository'))
3201 3775
3202 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'): 3776 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
3203 raise error.Abort(_('invalid value for --peer'), 3777 raise error.Abort(
3204 hint=_('valid values are "raw", "ssh1", and "ssh2"')) 3778 _('invalid value for --peer'),
3779 hint=_('valid values are "raw", "ssh1", and "ssh2"'),
3780 )
3205 3781
3206 if path and opts['localssh']: 3782 if path and opts['localssh']:
3207 raise error.Abort(_('cannot specify --localssh with an explicit ' 3783 raise error.Abort(
3208 'path')) 3784 _('cannot specify --localssh with an explicit ' 'path')
3785 )
3209 3786
3210 if ui.interactive(): 3787 if ui.interactive():
3211 ui.write(_('(waiting for commands on stdin)\n')) 3788 ui.write(_('(waiting for commands on stdin)\n'))
3212 3789
3213 blocks = list(_parsewirelangblocks(ui.fin)) 3790 blocks = list(_parsewirelangblocks(ui.fin))
3221 if opts['localssh']: 3798 if opts['localssh']:
3222 # We start the SSH server in its own process so there is process 3799 # We start the SSH server in its own process so there is process
3223 # separation. This prevents a whole class of potential bugs around 3800 # separation. This prevents a whole class of potential bugs around
3224 # shared state from interfering with server operation. 3801 # shared state from interfering with server operation.
3225 args = procutil.hgcmd() + [ 3802 args = procutil.hgcmd() + [
3226 '-R', repo.root, 3803 '-R',
3227 'debugserve', '--sshstdio', 3804 repo.root,
3805 'debugserve',
3806 '--sshstdio',
3228 ] 3807 ]
3229 proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, args), 3808 proc = subprocess.Popen(
3230 stdin=subprocess.PIPE, 3809 pycompat.rapply(procutil.tonativestr, args),
3231 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 3810 stdin=subprocess.PIPE,
3232 bufsize=0) 3811 stdout=subprocess.PIPE,
3812 stderr=subprocess.PIPE,
3813 bufsize=0,
3814 )
3233 3815
3234 stdin = proc.stdin 3816 stdin = proc.stdin
3235 stdout = proc.stdout 3817 stdout = proc.stdout
3236 stderr = proc.stderr 3818 stderr = proc.stderr
3237 3819
3238 # We turn the pipes into observers so we can log I/O. 3820 # We turn the pipes into observers so we can log I/O.
3239 if ui.verbose or opts['peer'] == 'raw': 3821 if ui.verbose or opts['peer'] == 'raw':
3240 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i', 3822 stdin = util.makeloggingfileobject(
3241 logdata=True) 3823 ui, proc.stdin, b'i', logdata=True
3242 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o', 3824 )
3243 logdata=True) 3825 stdout = util.makeloggingfileobject(
3244 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e', 3826 ui, proc.stdout, b'o', logdata=True
3245 logdata=True) 3827 )
3828 stderr = util.makeloggingfileobject(
3829 ui, proc.stderr, b'e', logdata=True
3830 )
3246 3831
3247 # --localssh also implies the peer connection settings. 3832 # --localssh also implies the peer connection settings.
3248 3833
3249 url = 'ssh://localserver' 3834 url = 'ssh://localserver'
3250 autoreadstderr = not opts['noreadstderr'] 3835 autoreadstderr = not opts['noreadstderr']
3251 3836
3252 if opts['peer'] == 'ssh1': 3837 if opts['peer'] == 'ssh1':
3253 ui.write(_('creating ssh peer for wire protocol version 1\n')) 3838 ui.write(_('creating ssh peer for wire protocol version 1\n'))
3254 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr, 3839 peer = sshpeer.sshv1peer(
3255 None, autoreadstderr=autoreadstderr) 3840 ui,
3841 url,
3842 proc,
3843 stdin,
3844 stdout,
3845 stderr,
3846 None,
3847 autoreadstderr=autoreadstderr,
3848 )
3256 elif opts['peer'] == 'ssh2': 3849 elif opts['peer'] == 'ssh2':
3257 ui.write(_('creating ssh peer for wire protocol version 2\n')) 3850 ui.write(_('creating ssh peer for wire protocol version 2\n'))
3258 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr, 3851 peer = sshpeer.sshv2peer(
3259 None, autoreadstderr=autoreadstderr) 3852 ui,
3853 url,
3854 proc,
3855 stdin,
3856 stdout,
3857 stderr,
3858 None,
3859 autoreadstderr=autoreadstderr,
3860 )
3260 elif opts['peer'] == 'raw': 3861 elif opts['peer'] == 'raw':
3261 ui.write(_('using raw connection to peer\n')) 3862 ui.write(_('using raw connection to peer\n'))
3262 peer = None 3863 peer = None
3263 else: 3864 else:
3264 ui.write(_('creating ssh peer from handshake results\n')) 3865 ui.write(_('creating ssh peer from handshake results\n'))
3265 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr, 3866 peer = sshpeer.makepeer(
3266 autoreadstderr=autoreadstderr) 3867 ui,
3868 url,
3869 proc,
3870 stdin,
3871 stdout,
3872 stderr,
3873 autoreadstderr=autoreadstderr,
3874 )
3267 3875
3268 elif path: 3876 elif path:
3269 # We bypass hg.peer() so we can proxy the sockets. 3877 # We bypass hg.peer() so we can proxy the sockets.
3270 # TODO consider not doing this because we skip 3878 # TODO consider not doing this because we skip
3271 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality. 3879 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
3278 r'useragent': b'Mercurial debugwireproto', 3886 r'useragent': b'Mercurial debugwireproto',
3279 } 3887 }
3280 3888
3281 # Turn pipes/sockets into observers so we can log I/O. 3889 # Turn pipes/sockets into observers so we can log I/O.
3282 if ui.verbose: 3890 if ui.verbose:
3283 openerargs.update({ 3891 openerargs.update(
3284 r'loggingfh': ui, 3892 {
3285 r'loggingname': b's', 3893 r'loggingfh': ui,
3286 r'loggingopts': { 3894 r'loggingname': b's',
3287 r'logdata': True, 3895 r'loggingopts': {r'logdata': True, r'logdataapis': False,},
3288 r'logdataapis': False, 3896 }
3289 }, 3897 )
3290 })
3291 3898
3292 if ui.debugflag: 3899 if ui.debugflag:
3293 openerargs[r'loggingopts'][r'logdataapis'] = True 3900 openerargs[r'loggingopts'][r'logdataapis'] = True
3294 3901
3295 # Don't send default headers when in raw mode. This allows us to 3902 # Don't send default headers when in raw mode. This allows us to
3302 3909
3303 if opts['peer'] == 'http2': 3910 if opts['peer'] == 'http2':
3304 ui.write(_('creating http peer for wire protocol version 2\n')) 3911 ui.write(_('creating http peer for wire protocol version 2\n'))
3305 # We go through makepeer() because we need an API descriptor for 3912 # We go through makepeer() because we need an API descriptor for
3306 # the peer instance to be useful. 3913 # the peer instance to be useful.
3307 with ui.configoverride({ 3914 with ui.configoverride(
3308 ('experimental', 'httppeer.advertise-v2'): True}): 3915 {('experimental', 'httppeer.advertise-v2'): True}
3916 ):
3309 if opts['nologhandshake']: 3917 if opts['nologhandshake']:
3310 ui.pushbuffer() 3918 ui.pushbuffer()
3311 3919
3312 peer = httppeer.makepeer(ui, path, opener=opener) 3920 peer = httppeer.makepeer(ui, path, opener=opener)
3313 3921
3314 if opts['nologhandshake']: 3922 if opts['nologhandshake']:
3315 ui.popbuffer() 3923 ui.popbuffer()
3316 3924
3317 if not isinstance(peer, httppeer.httpv2peer): 3925 if not isinstance(peer, httppeer.httpv2peer):
3318 raise error.Abort(_('could not instantiate HTTP peer for ' 3926 raise error.Abort(
3319 'wire protocol version 2'), 3927 _(
3320 hint=_('the server may not have the feature ' 3928 'could not instantiate HTTP peer for '
3321 'enabled or is not allowing this ' 3929 'wire protocol version 2'
3322 'client version')) 3930 ),
3931 hint=_(
3932 'the server may not have the feature '
3933 'enabled or is not allowing this '
3934 'client version'
3935 ),
3936 )
3323 3937
3324 elif opts['peer'] == 'raw': 3938 elif opts['peer'] == 'raw':
3325 ui.write(_('using raw connection to peer\n')) 3939 ui.write(_('using raw connection to peer\n'))
3326 peer = None 3940 peer = None
3327 elif opts['peer']: 3941 elif opts['peer']:
3328 raise error.Abort(_('--peer %s not supported with HTTP peers') % 3942 raise error.Abort(
3329 opts['peer']) 3943 _('--peer %s not supported with HTTP peers') % opts['peer']
3944 )
3330 else: 3945 else:
3331 peer = httppeer.makepeer(ui, path, opener=opener) 3946 peer = httppeer.makepeer(ui, path, opener=opener)
3332 3947
3333 # We /could/ populate stdin/stdout with sock.makefile()... 3948 # We /could/ populate stdin/stdout with sock.makefile()...
3334 else: 3949 else:
3353 if not stdin: 3968 if not stdin:
3354 raise error.Abort(_('cannot call flush on this peer')) 3969 raise error.Abort(_('cannot call flush on this peer'))
3355 stdin.flush() 3970 stdin.flush()
3356 elif action.startswith('command'): 3971 elif action.startswith('command'):
3357 if not peer: 3972 if not peer:
3358 raise error.Abort(_('cannot send commands unless peer instance ' 3973 raise error.Abort(
3359 'is available')) 3974 _(
3975 'cannot send commands unless peer instance '
3976 'is available'
3977 )
3978 )
3360 3979
3361 command = action.split(' ', 1)[1] 3980 command = action.split(' ', 1)[1]
3362 3981
3363 args = {} 3982 args = {}
3364 for line in lines: 3983 for line in lines:
3384 ui.status(_('sending %s command\n') % command) 4003 ui.status(_('sending %s command\n') % command)
3385 4004
3386 if 'PUSHFILE' in args: 4005 if 'PUSHFILE' in args:
3387 with open(args['PUSHFILE'], r'rb') as fh: 4006 with open(args['PUSHFILE'], r'rb') as fh:
3388 del args['PUSHFILE'] 4007 del args['PUSHFILE']
3389 res, output = peer._callpush(command, fh, 4008 res, output = peer._callpush(
3390 **pycompat.strkwargs(args)) 4009 command, fh, **pycompat.strkwargs(args)
4010 )
3391 ui.status(_('result: %s\n') % stringutil.escapestr(res)) 4011 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3392 ui.status(_('remote output: %s\n') % 4012 ui.status(
3393 stringutil.escapestr(output)) 4013 _('remote output: %s\n') % stringutil.escapestr(output)
4014 )
3394 else: 4015 else:
3395 with peer.commandexecutor() as e: 4016 with peer.commandexecutor() as e:
3396 res = e.callcommand(command, args).result() 4017 res = e.callcommand(command, args).result()
3397 4018
3398 if isinstance(res, wireprotov2peer.commandresponse): 4019 if isinstance(res, wireprotov2peer.commandresponse):
3399 val = res.objects() 4020 val = res.objects()
3400 ui.status(_('response: %s\n') % 4021 ui.status(
3401 stringutil.pprint(val, bprefix=True, indent=2)) 4022 _('response: %s\n')
4023 % stringutil.pprint(val, bprefix=True, indent=2)
4024 )
3402 else: 4025 else:
3403 ui.status(_('response: %s\n') % 4026 ui.status(
3404 stringutil.pprint(res, bprefix=True, indent=2)) 4027 _('response: %s\n')
4028 % stringutil.pprint(res, bprefix=True, indent=2)
4029 )
3405 4030
3406 elif action == 'batchbegin': 4031 elif action == 'batchbegin':
3407 if batchedcommands is not None: 4032 if batchedcommands is not None:
3408 raise error.Abort(_('nested batchbegin not allowed')) 4033 raise error.Abort(_('nested batchbegin not allowed'))
3409 4034
3410 batchedcommands = [] 4035 batchedcommands = []
3411 elif action == 'batchsubmit': 4036 elif action == 'batchsubmit':
3412 # There is a batching API we could go through. But it would be 4037 # There is a batching API we could go through. But it would be
3413 # difficult to normalize requests into function calls. It is easier 4038 # difficult to normalize requests into function calls. It is easier
3414 # to bypass this layer and normalize to commands + args. 4039 # to bypass this layer and normalize to commands + args.
3415 ui.status(_('sending batch with %d sub-commands\n') % 4040 ui.status(
3416 len(batchedcommands)) 4041 _('sending batch with %d sub-commands\n') % len(batchedcommands)
4042 )
3417 for i, chunk in enumerate(peer._submitbatch(batchedcommands)): 4043 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3418 ui.status(_('response #%d: %s\n') % 4044 ui.status(
3419 (i, stringutil.escapestr(chunk))) 4045 _('response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4046 )
3420 4047
3421 batchedcommands = None 4048 batchedcommands = None
3422 4049
3423 elif action.startswith('httprequest '): 4050 elif action.startswith('httprequest '):
3424 if not opener: 4051 if not opener:
3425 raise error.Abort(_('cannot use httprequest without an HTTP ' 4052 raise error.Abort(
3426 'peer')) 4053 _('cannot use httprequest without an HTTP ' 'peer')
4054 )
3427 4055
3428 request = action.split(' ', 2) 4056 request = action.split(' ', 2)
3429 if len(request) != 3: 4057 if len(request) != 3:
3430 raise error.Abort(_('invalid httprequest: expected format is ' 4058 raise error.Abort(
3431 '"httprequest <method> <path>')) 4059 _(
4060 'invalid httprequest: expected format is '
4061 '"httprequest <method> <path>'
4062 )
4063 )
3432 4064
3433 method, httppath = request[1:] 4065 method, httppath = request[1:]
3434 headers = {} 4066 headers = {}
3435 body = None 4067 body = None
3436 frames = [] 4068 frames = []
3447 if line.startswith(b'BODYFILE '): 4079 if line.startswith(b'BODYFILE '):
3448 with open(line.split(b' ', 1), 'rb') as fh: 4080 with open(line.split(b' ', 1), 'rb') as fh:
3449 body = fh.read() 4081 body = fh.read()
3450 elif line.startswith(b'frame '): 4082 elif line.startswith(b'frame '):
3451 frame = wireprotoframing.makeframefromhumanstring( 4083 frame = wireprotoframing.makeframefromhumanstring(
3452 line[len(b'frame '):]) 4084 line[len(b'frame ') :]
4085 )
3453 4086
3454 frames.append(frame) 4087 frames.append(frame)
3455 else: 4088 else:
3456 raise error.Abort(_('unknown argument to httprequest: %s') % 4089 raise error.Abort(
3457 line) 4090 _('unknown argument to httprequest: %s') % line
4091 )
3458 4092
3459 url = path + httppath 4093 url = path + httppath
3460 4094
3461 if frames: 4095 if frames:
3462 body = b''.join(bytes(f) for f in frames) 4096 body = b''.join(bytes(f) for f in frames)
3476 getattr(e, 'read', lambda: None)() 4110 getattr(e, 'read', lambda: None)()
3477 continue 4111 continue
3478 4112
3479 ct = res.headers.get(r'Content-Type') 4113 ct = res.headers.get(r'Content-Type')
3480 if ct == r'application/mercurial-cbor': 4114 if ct == r'application/mercurial-cbor':
3481 ui.write(_('cbor> %s\n') % 4115 ui.write(
3482 stringutil.pprint(cborutil.decodeall(body), 4116 _('cbor> %s\n')
3483 bprefix=True, 4117 % stringutil.pprint(
3484 indent=2)) 4118 cborutil.decodeall(body), bprefix=True, indent=2
4119 )
4120 )
3485 4121
3486 elif action == 'close': 4122 elif action == 'close':
3487 peer.close() 4123 peer.close()
3488 elif action == 'readavailable': 4124 elif action == 'readavailable':
3489 if not stdout or not stderr: 4125 if not stdout or not stderr: