##// END OF EJS Templates
debugrevspec: add option to suppress list of computed revisions...
Yuya Nishihara -
r32796:bcca357b default
parent child Browse files
Show More
@@ -1,2200 +1,2206 b''
1 1 # debugcommands.py - command processing for debug* commands
2 2 #
3 3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import difflib
11 11 import errno
12 12 import operator
13 13 import os
14 14 import random
15 15 import socket
16 16 import string
17 17 import sys
18 18 import tempfile
19 19 import time
20 20
21 21 from .i18n import _
22 22 from .node import (
23 23 bin,
24 24 hex,
25 25 nullhex,
26 26 nullid,
27 27 nullrev,
28 28 short,
29 29 )
30 30 from . import (
31 31 bundle2,
32 32 changegroup,
33 33 cmdutil,
34 34 color,
35 35 context,
36 36 dagparser,
37 37 dagutil,
38 38 encoding,
39 39 error,
40 40 exchange,
41 41 extensions,
42 42 filemerge,
43 43 fileset,
44 44 formatter,
45 45 hg,
46 46 localrepo,
47 47 lock as lockmod,
48 48 merge as mergemod,
49 49 obsolete,
50 50 phases,
51 51 policy,
52 52 pvec,
53 53 pycompat,
54 54 registrar,
55 55 repair,
56 56 revlog,
57 57 revset,
58 58 revsetlang,
59 59 scmutil,
60 60 setdiscovery,
61 61 simplemerge,
62 62 smartset,
63 63 sslutil,
64 64 streamclone,
65 65 templater,
66 66 treediscovery,
67 67 upgrade,
68 68 util,
69 69 vfs as vfsmod,
70 70 )
71 71
72 72 release = lockmod.release
73 73
74 74 command = registrar.command()
75 75
76 76 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
77 77 def debugancestor(ui, repo, *args):
78 78 """find the ancestor revision of two revisions in a given index"""
79 79 if len(args) == 3:
80 80 index, rev1, rev2 = args
81 81 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
82 82 lookup = r.lookup
83 83 elif len(args) == 2:
84 84 if not repo:
85 85 raise error.Abort(_('there is no Mercurial repository here '
86 86 '(.hg not found)'))
87 87 rev1, rev2 = args
88 88 r = repo.changelog
89 89 lookup = repo.lookup
90 90 else:
91 91 raise error.Abort(_('either two or three arguments required'))
92 92 a = r.ancestor(lookup(rev1), lookup(rev2))
93 93 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
94 94
95 95 @command('debugapplystreamclonebundle', [], 'FILE')
96 96 def debugapplystreamclonebundle(ui, repo, fname):
97 97 """apply a stream clone bundle file"""
98 98 f = hg.openpath(ui, fname)
99 99 gen = exchange.readbundle(ui, f, fname)
100 100 gen.apply(repo)
101 101
102 102 @command('debugbuilddag',
103 103 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
104 104 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
105 105 ('n', 'new-file', None, _('add new file at each rev'))],
106 106 _('[OPTION]... [TEXT]'))
107 107 def debugbuilddag(ui, repo, text=None,
108 108 mergeable_file=False,
109 109 overwritten_file=False,
110 110 new_file=False):
111 111 """builds a repo with a given DAG from scratch in the current empty repo
112 112
113 113 The description of the DAG is read from stdin if not given on the
114 114 command line.
115 115
116 116 Elements:
117 117
118 118 - "+n" is a linear run of n nodes based on the current default parent
119 119 - "." is a single node based on the current default parent
120 120 - "$" resets the default parent to null (implied at the start);
121 121 otherwise the default parent is always the last node created
122 122 - "<p" sets the default parent to the backref p
123 123 - "*p" is a fork at parent p, which is a backref
124 124 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
125 125 - "/p2" is a merge of the preceding node and p2
126 126 - ":tag" defines a local tag for the preceding node
127 127 - "@branch" sets the named branch for subsequent nodes
128 128 - "#...\\n" is a comment up to the end of the line
129 129
130 130 Whitespace between the above elements is ignored.
131 131
132 132 A backref is either
133 133
134 134 - a number n, which references the node curr-n, where curr is the current
135 135 node, or
136 136 - the name of a local tag you placed earlier using ":tag", or
137 137 - empty to denote the default parent.
138 138
139 139 All string valued-elements are either strictly alphanumeric, or must
140 140 be enclosed in double quotes ("..."), with "\\" as escape character.
141 141 """
142 142
143 143 if text is None:
144 144 ui.status(_("reading DAG from stdin\n"))
145 145 text = ui.fin.read()
146 146
147 147 cl = repo.changelog
148 148 if len(cl) > 0:
149 149 raise error.Abort(_('repository is not empty'))
150 150
151 151 # determine number of revs in DAG
152 152 total = 0
153 153 for type, data in dagparser.parsedag(text):
154 154 if type == 'n':
155 155 total += 1
156 156
157 157 if mergeable_file:
158 158 linesperrev = 2
159 159 # make a file with k lines per rev
160 160 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
161 161 initialmergedlines.append("")
162 162
163 163 tags = []
164 164
165 165 wlock = lock = tr = None
166 166 try:
167 167 wlock = repo.wlock()
168 168 lock = repo.lock()
169 169 tr = repo.transaction("builddag")
170 170
171 171 at = -1
172 172 atbranch = 'default'
173 173 nodeids = []
174 174 id = 0
175 175 ui.progress(_('building'), id, unit=_('revisions'), total=total)
176 176 for type, data in dagparser.parsedag(text):
177 177 if type == 'n':
178 178 ui.note(('node %s\n' % str(data)))
179 179 id, ps = data
180 180
181 181 files = []
182 182 fctxs = {}
183 183
184 184 p2 = None
185 185 if mergeable_file:
186 186 fn = "mf"
187 187 p1 = repo[ps[0]]
188 188 if len(ps) > 1:
189 189 p2 = repo[ps[1]]
190 190 pa = p1.ancestor(p2)
191 191 base, local, other = [x[fn].data() for x in (pa, p1,
192 192 p2)]
193 193 m3 = simplemerge.Merge3Text(base, local, other)
194 194 ml = [l.strip() for l in m3.merge_lines()]
195 195 ml.append("")
196 196 elif at > 0:
197 197 ml = p1[fn].data().split("\n")
198 198 else:
199 199 ml = initialmergedlines
200 200 ml[id * linesperrev] += " r%i" % id
201 201 mergedtext = "\n".join(ml)
202 202 files.append(fn)
203 203 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
204 204
205 205 if overwritten_file:
206 206 fn = "of"
207 207 files.append(fn)
208 208 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
209 209
210 210 if new_file:
211 211 fn = "nf%i" % id
212 212 files.append(fn)
213 213 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
214 214 if len(ps) > 1:
215 215 if not p2:
216 216 p2 = repo[ps[1]]
217 217 for fn in p2:
218 218 if fn.startswith("nf"):
219 219 files.append(fn)
220 220 fctxs[fn] = p2[fn]
221 221
222 222 def fctxfn(repo, cx, path):
223 223 return fctxs.get(path)
224 224
225 225 if len(ps) == 0 or ps[0] < 0:
226 226 pars = [None, None]
227 227 elif len(ps) == 1:
228 228 pars = [nodeids[ps[0]], None]
229 229 else:
230 230 pars = [nodeids[p] for p in ps]
231 231 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
232 232 date=(id, 0),
233 233 user="debugbuilddag",
234 234 extra={'branch': atbranch})
235 235 nodeid = repo.commitctx(cx)
236 236 nodeids.append(nodeid)
237 237 at = id
238 238 elif type == 'l':
239 239 id, name = data
240 240 ui.note(('tag %s\n' % name))
241 241 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
242 242 elif type == 'a':
243 243 ui.note(('branch %s\n' % data))
244 244 atbranch = data
245 245 ui.progress(_('building'), id, unit=_('revisions'), total=total)
246 246 tr.close()
247 247
248 248 if tags:
249 249 repo.vfs.write("localtags", "".join(tags))
250 250 finally:
251 251 ui.progress(_('building'), None)
252 252 release(tr, lock, wlock)
253 253
254 254 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
255 255 indent_string = ' ' * indent
256 256 if all:
257 257 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
258 258 % indent_string)
259 259
260 260 def showchunks(named):
261 261 ui.write("\n%s%s\n" % (indent_string, named))
262 262 chain = None
263 263 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
264 264 node = chunkdata['node']
265 265 p1 = chunkdata['p1']
266 266 p2 = chunkdata['p2']
267 267 cs = chunkdata['cs']
268 268 deltabase = chunkdata['deltabase']
269 269 delta = chunkdata['delta']
270 270 ui.write("%s%s %s %s %s %s %s\n" %
271 271 (indent_string, hex(node), hex(p1), hex(p2),
272 272 hex(cs), hex(deltabase), len(delta)))
273 273 chain = node
274 274
275 275 chunkdata = gen.changelogheader()
276 276 showchunks("changelog")
277 277 chunkdata = gen.manifestheader()
278 278 showchunks("manifest")
279 279 for chunkdata in iter(gen.filelogheader, {}):
280 280 fname = chunkdata['filename']
281 281 showchunks(fname)
282 282 else:
283 283 if isinstance(gen, bundle2.unbundle20):
284 284 raise error.Abort(_('use debugbundle2 for this file'))
285 285 chunkdata = gen.changelogheader()
286 286 chain = None
287 287 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
288 288 node = chunkdata['node']
289 289 ui.write("%s%s\n" % (indent_string, hex(node)))
290 290 chain = node
291 291
292 292 def _debugobsmarkers(ui, data, all=None, indent=0, **opts):
293 293 """display version and markers contained in 'data'"""
294 294 indent_string = ' ' * indent
295 295 try:
296 296 version, markers = obsolete._readmarkers(data)
297 297 except error.UnknownVersion as exc:
298 298 msg = "%sunsupported version: %s (%d bytes)\n"
299 299 msg %= indent_string, exc.version, len(data)
300 300 ui.write(msg)
301 301 else:
302 302 msg = "%sversion: %s (%d bytes)\n"
303 303 msg %= indent_string, version, len(data)
304 304 ui.write(msg)
305 305 fm = ui.formatter('debugobsolete', opts)
306 306 for rawmarker in sorted(markers):
307 307 m = obsolete.marker(None, rawmarker)
308 308 fm.startitem()
309 309 fm.plain(indent_string)
310 310 cmdutil.showmarker(fm, m)
311 311 fm.end()
312 312
313 313 def _debugbundle2(ui, gen, all=None, **opts):
314 314 """lists the contents of a bundle2"""
315 315 if not isinstance(gen, bundle2.unbundle20):
316 316 raise error.Abort(_('not a bundle2 file'))
317 317 ui.write(('Stream params: %s\n' % repr(gen.params)))
318 318 parttypes = opts.get('part_type', [])
319 319 for part in gen.iterparts():
320 320 if parttypes and part.type not in parttypes:
321 321 continue
322 322 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
323 323 if part.type == 'changegroup':
324 324 version = part.params.get('version', '01')
325 325 cg = changegroup.getunbundler(version, part, 'UN')
326 326 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
327 327 if part.type == 'obsmarkers':
328 328 _debugobsmarkers(ui, part.read(), all=all, indent=4, **opts)
329 329
330 330 @command('debugbundle',
331 331 [('a', 'all', None, _('show all details')),
332 332 ('', 'part-type', [], _('show only the named part type')),
333 333 ('', 'spec', None, _('print the bundlespec of the bundle'))],
334 334 _('FILE'),
335 335 norepo=True)
336 336 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
337 337 """lists the contents of a bundle"""
338 338 with hg.openpath(ui, bundlepath) as f:
339 339 if spec:
340 340 spec = exchange.getbundlespec(ui, f)
341 341 ui.write('%s\n' % spec)
342 342 return
343 343
344 344 gen = exchange.readbundle(ui, f, bundlepath)
345 345 if isinstance(gen, bundle2.unbundle20):
346 346 return _debugbundle2(ui, gen, all=all, **opts)
347 347 _debugchangegroup(ui, gen, all=all, **opts)
348 348
349 349 @command('debugcheckstate', [], '')
350 350 def debugcheckstate(ui, repo):
351 351 """validate the correctness of the current dirstate"""
352 352 parent1, parent2 = repo.dirstate.parents()
353 353 m1 = repo[parent1].manifest()
354 354 m2 = repo[parent2].manifest()
355 355 errors = 0
356 356 for f in repo.dirstate:
357 357 state = repo.dirstate[f]
358 358 if state in "nr" and f not in m1:
359 359 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
360 360 errors += 1
361 361 if state in "a" and f in m1:
362 362 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
363 363 errors += 1
364 364 if state in "m" and f not in m1 and f not in m2:
365 365 ui.warn(_("%s in state %s, but not in either manifest\n") %
366 366 (f, state))
367 367 errors += 1
368 368 for f in m1:
369 369 state = repo.dirstate[f]
370 370 if state not in "nrm":
371 371 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
372 372 errors += 1
373 373 if errors:
374 374 error = _(".hg/dirstate inconsistent with current parent's manifest")
375 375 raise error.Abort(error)
376 376
377 377 @command('debugcolor',
378 378 [('', 'style', None, _('show all configured styles'))],
379 379 'hg debugcolor')
380 380 def debugcolor(ui, repo, **opts):
381 381 """show available color, effects or style"""
382 382 ui.write(('color mode: %s\n') % ui._colormode)
383 383 if opts.get('style'):
384 384 return _debugdisplaystyle(ui)
385 385 else:
386 386 return _debugdisplaycolor(ui)
387 387
388 388 def _debugdisplaycolor(ui):
389 389 ui = ui.copy()
390 390 ui._styles.clear()
391 391 for effect in color._activeeffects(ui).keys():
392 392 ui._styles[effect] = effect
393 393 if ui._terminfoparams:
394 394 for k, v in ui.configitems('color'):
395 395 if k.startswith('color.'):
396 396 ui._styles[k] = k[6:]
397 397 elif k.startswith('terminfo.'):
398 398 ui._styles[k] = k[9:]
399 399 ui.write(_('available colors:\n'))
400 400 # sort label with a '_' after the other to group '_background' entry.
401 401 items = sorted(ui._styles.items(),
402 402 key=lambda i: ('_' in i[0], i[0], i[1]))
403 403 for colorname, label in items:
404 404 ui.write(('%s\n') % colorname, label=label)
405 405
406 406 def _debugdisplaystyle(ui):
407 407 ui.write(_('available style:\n'))
408 408 width = max(len(s) for s in ui._styles)
409 409 for label, effects in sorted(ui._styles.items()):
410 410 ui.write('%s' % label, label=label)
411 411 if effects:
412 412 # 50
413 413 ui.write(': ')
414 414 ui.write(' ' * (max(0, width - len(label))))
415 415 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
416 416 ui.write('\n')
417 417
418 418 @command('debugcreatestreamclonebundle', [], 'FILE')
419 419 def debugcreatestreamclonebundle(ui, repo, fname):
420 420 """create a stream clone bundle file
421 421
422 422 Stream bundles are special bundles that are essentially archives of
423 423 revlog files. They are commonly used for cloning very quickly.
424 424 """
425 425 # TODO we may want to turn this into an abort when this functionality
426 426 # is moved into `hg bundle`.
427 427 if phases.hassecret(repo):
428 428 ui.warn(_('(warning: stream clone bundle will contain secret '
429 429 'revisions)\n'))
430 430
431 431 requirements, gen = streamclone.generatebundlev1(repo)
432 432 changegroup.writechunks(ui, gen, fname)
433 433
434 434 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
435 435
436 436 @command('debugdag',
437 437 [('t', 'tags', None, _('use tags as labels')),
438 438 ('b', 'branches', None, _('annotate with branch names')),
439 439 ('', 'dots', None, _('use dots for runs')),
440 440 ('s', 'spaces', None, _('separate elements by spaces'))],
441 441 _('[OPTION]... [FILE [REV]...]'),
442 442 optionalrepo=True)
443 443 def debugdag(ui, repo, file_=None, *revs, **opts):
444 444 """format the changelog or an index DAG as a concise textual description
445 445
446 446 If you pass a revlog index, the revlog's DAG is emitted. If you list
447 447 revision numbers, they get labeled in the output as rN.
448 448
449 449 Otherwise, the changelog DAG of the current repo is emitted.
450 450 """
451 451 spaces = opts.get('spaces')
452 452 dots = opts.get('dots')
453 453 if file_:
454 454 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
455 455 file_)
456 456 revs = set((int(r) for r in revs))
457 457 def events():
458 458 for r in rlog:
459 459 yield 'n', (r, list(p for p in rlog.parentrevs(r)
460 460 if p != -1))
461 461 if r in revs:
462 462 yield 'l', (r, "r%i" % r)
463 463 elif repo:
464 464 cl = repo.changelog
465 465 tags = opts.get('tags')
466 466 branches = opts.get('branches')
467 467 if tags:
468 468 labels = {}
469 469 for l, n in repo.tags().items():
470 470 labels.setdefault(cl.rev(n), []).append(l)
471 471 def events():
472 472 b = "default"
473 473 for r in cl:
474 474 if branches:
475 475 newb = cl.read(cl.node(r))[5]['branch']
476 476 if newb != b:
477 477 yield 'a', newb
478 478 b = newb
479 479 yield 'n', (r, list(p for p in cl.parentrevs(r)
480 480 if p != -1))
481 481 if tags:
482 482 ls = labels.get(r)
483 483 if ls:
484 484 for l in ls:
485 485 yield 'l', (r, l)
486 486 else:
487 487 raise error.Abort(_('need repo for changelog dag'))
488 488
489 489 for line in dagparser.dagtextlines(events(),
490 490 addspaces=spaces,
491 491 wraplabels=True,
492 492 wrapannotations=True,
493 493 wrapnonlinear=dots,
494 494 usedots=dots,
495 495 maxlinewidth=70):
496 496 ui.write(line)
497 497 ui.write("\n")
498 498
499 499 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
500 500 def debugdata(ui, repo, file_, rev=None, **opts):
501 501 """dump the contents of a data file revision"""
502 502 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
503 503 if rev is not None:
504 504 raise error.CommandError('debugdata', _('invalid arguments'))
505 505 file_, rev = None, file_
506 506 elif rev is None:
507 507 raise error.CommandError('debugdata', _('invalid arguments'))
508 508 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
509 509 try:
510 510 ui.write(r.revision(r.lookup(rev), raw=True))
511 511 except KeyError:
512 512 raise error.Abort(_('invalid revision identifier %s') % rev)
513 513
514 514 @command('debugdate',
515 515 [('e', 'extended', None, _('try extended date formats'))],
516 516 _('[-e] DATE [RANGE]'),
517 517 norepo=True, optionalrepo=True)
518 518 def debugdate(ui, date, range=None, **opts):
519 519 """parse and display a date"""
520 520 if opts["extended"]:
521 521 d = util.parsedate(date, util.extendeddateformats)
522 522 else:
523 523 d = util.parsedate(date)
524 524 ui.write(("internal: %s %s\n") % d)
525 525 ui.write(("standard: %s\n") % util.datestr(d))
526 526 if range:
527 527 m = util.matchdate(range)
528 528 ui.write(("match: %s\n") % m(d[0]))
529 529
530 530 @command('debugdeltachain',
531 531 cmdutil.debugrevlogopts + cmdutil.formatteropts,
532 532 _('-c|-m|FILE'),
533 533 optionalrepo=True)
534 534 def debugdeltachain(ui, repo, file_=None, **opts):
535 535 """dump information about delta chains in a revlog
536 536
537 537 Output can be templatized. Available template keywords are:
538 538
539 539 :``rev``: revision number
540 540 :``chainid``: delta chain identifier (numbered by unique base)
541 541 :``chainlen``: delta chain length to this revision
542 542 :``prevrev``: previous revision in delta chain
543 543 :``deltatype``: role of delta / how it was computed
544 544 :``compsize``: compressed size of revision
545 545 :``uncompsize``: uncompressed size of revision
546 546 :``chainsize``: total size of compressed revisions in chain
547 547 :``chainratio``: total chain size divided by uncompressed revision size
548 548 (new delta chains typically start at ratio 2.00)
549 549 :``lindist``: linear distance from base revision in delta chain to end
550 550 of this revision
551 551 :``extradist``: total size of revisions not part of this delta chain from
552 552 base of delta chain to end of this revision; a measurement
553 553 of how much extra data we need to read/seek across to read
554 554 the delta chain for this revision
555 555 :``extraratio``: extradist divided by chainsize; another representation of
556 556 how much unrelated data is needed to load this delta chain
557 557 """
558 558 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
559 559 index = r.index
560 560 generaldelta = r.version & revlog.FLAG_GENERALDELTA
561 561
562 562 def revinfo(rev):
563 563 e = index[rev]
564 564 compsize = e[1]
565 565 uncompsize = e[2]
566 566 chainsize = 0
567 567
568 568 if generaldelta:
569 569 if e[3] == e[5]:
570 570 deltatype = 'p1'
571 571 elif e[3] == e[6]:
572 572 deltatype = 'p2'
573 573 elif e[3] == rev - 1:
574 574 deltatype = 'prev'
575 575 elif e[3] == rev:
576 576 deltatype = 'base'
577 577 else:
578 578 deltatype = 'other'
579 579 else:
580 580 if e[3] == rev:
581 581 deltatype = 'base'
582 582 else:
583 583 deltatype = 'prev'
584 584
585 585 chain = r._deltachain(rev)[0]
586 586 for iterrev in chain:
587 587 e = index[iterrev]
588 588 chainsize += e[1]
589 589
590 590 return compsize, uncompsize, deltatype, chain, chainsize
591 591
592 592 fm = ui.formatter('debugdeltachain', opts)
593 593
594 594 fm.plain(' rev chain# chainlen prev delta '
595 595 'size rawsize chainsize ratio lindist extradist '
596 596 'extraratio\n')
597 597
598 598 chainbases = {}
599 599 for rev in r:
600 600 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
601 601 chainbase = chain[0]
602 602 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
603 603 basestart = r.start(chainbase)
604 604 revstart = r.start(rev)
605 605 lineardist = revstart + comp - basestart
606 606 extradist = lineardist - chainsize
607 607 try:
608 608 prevrev = chain[-2]
609 609 except IndexError:
610 610 prevrev = -1
611 611
612 612 chainratio = float(chainsize) / float(uncomp)
613 613 extraratio = float(extradist) / float(chainsize)
614 614
615 615 fm.startitem()
616 616 fm.write('rev chainid chainlen prevrev deltatype compsize '
617 617 'uncompsize chainsize chainratio lindist extradist '
618 618 'extraratio',
619 619 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
620 620 rev, chainid, len(chain), prevrev, deltatype, comp,
621 621 uncomp, chainsize, chainratio, lineardist, extradist,
622 622 extraratio,
623 623 rev=rev, chainid=chainid, chainlen=len(chain),
624 624 prevrev=prevrev, deltatype=deltatype, compsize=comp,
625 625 uncompsize=uncomp, chainsize=chainsize,
626 626 chainratio=chainratio, lindist=lineardist,
627 627 extradist=extradist, extraratio=extraratio)
628 628
629 629 fm.end()
630 630
631 631 @command('debugdirstate|debugstate',
632 632 [('', 'nodates', None, _('do not display the saved mtime')),
633 633 ('', 'datesort', None, _('sort by saved mtime'))],
634 634 _('[OPTION]...'))
635 635 def debugstate(ui, repo, **opts):
636 636 """show the contents of the current dirstate"""
637 637
638 638 nodates = opts.get('nodates')
639 639 datesort = opts.get('datesort')
640 640
641 641 timestr = ""
642 642 if datesort:
643 643 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
644 644 else:
645 645 keyfunc = None # sort by filename
646 646 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
647 647 if ent[3] == -1:
648 648 timestr = 'unset '
649 649 elif nodates:
650 650 timestr = 'set '
651 651 else:
652 652 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
653 653 time.localtime(ent[3]))
654 654 if ent[1] & 0o20000:
655 655 mode = 'lnk'
656 656 else:
657 657 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
658 658 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
659 659 for f in repo.dirstate.copies():
660 660 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
661 661
662 662 @command('debugdiscovery',
663 663 [('', 'old', None, _('use old-style discovery')),
664 664 ('', 'nonheads', None,
665 665 _('use old-style discovery with non-heads included')),
666 666 ] + cmdutil.remoteopts,
667 667 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
668 668 def debugdiscovery(ui, repo, remoteurl="default", **opts):
669 669 """runs the changeset discovery protocol in isolation"""
670 670 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
671 671 opts.get('branch'))
672 672 remote = hg.peer(repo, opts, remoteurl)
673 673 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
674 674
675 675 # make sure tests are repeatable
676 676 random.seed(12323)
677 677
678 678 def doit(localheads, remoteheads, remote=remote):
679 679 if opts.get('old'):
680 680 if localheads:
681 681 raise error.Abort('cannot use localheads with old style '
682 682 'discovery')
683 683 if not util.safehasattr(remote, 'branches'):
684 684 # enable in-client legacy support
685 685 remote = localrepo.locallegacypeer(remote.local())
686 686 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
687 687 force=True)
688 688 common = set(common)
689 689 if not opts.get('nonheads'):
690 690 ui.write(("unpruned common: %s\n") %
691 691 " ".join(sorted(short(n) for n in common)))
692 692 dag = dagutil.revlogdag(repo.changelog)
693 693 all = dag.ancestorset(dag.internalizeall(common))
694 694 common = dag.externalizeall(dag.headsetofconnecteds(all))
695 695 else:
696 696 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
697 697 common = set(common)
698 698 rheads = set(hds)
699 699 lheads = set(repo.heads())
700 700 ui.write(("common heads: %s\n") %
701 701 " ".join(sorted(short(n) for n in common)))
702 702 if lheads <= common:
703 703 ui.write(("local is subset\n"))
704 704 elif rheads <= common:
705 705 ui.write(("remote is subset\n"))
706 706
707 707 serverlogs = opts.get('serverlog')
708 708 if serverlogs:
709 709 for filename in serverlogs:
710 710 with open(filename, 'r') as logfile:
711 711 line = logfile.readline()
712 712 while line:
713 713 parts = line.strip().split(';')
714 714 op = parts[1]
715 715 if op == 'cg':
716 716 pass
717 717 elif op == 'cgss':
718 718 doit(parts[2].split(' '), parts[3].split(' '))
719 719 elif op == 'unb':
720 720 doit(parts[3].split(' '), parts[2].split(' '))
721 721 line = logfile.readline()
722 722 else:
723 723 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
724 724 opts.get('remote_head'))
725 725 localrevs = opts.get('local_head')
726 726 doit(localrevs, remoterevs)
727 727
728 728 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
729 729 def debugextensions(ui, **opts):
730 730 '''show information about active extensions'''
731 731 exts = extensions.extensions(ui)
732 732 hgver = util.version()
733 733 fm = ui.formatter('debugextensions', opts)
734 734 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
735 735 isinternal = extensions.ismoduleinternal(extmod)
736 736 extsource = pycompat.fsencode(extmod.__file__)
737 737 if isinternal:
738 738 exttestedwith = [] # never expose magic string to users
739 739 else:
740 740 exttestedwith = getattr(extmod, 'testedwith', '').split()
741 741 extbuglink = getattr(extmod, 'buglink', None)
742 742
743 743 fm.startitem()
744 744
745 745 if ui.quiet or ui.verbose:
746 746 fm.write('name', '%s\n', extname)
747 747 else:
748 748 fm.write('name', '%s', extname)
749 749 if isinternal or hgver in exttestedwith:
750 750 fm.plain('\n')
751 751 elif not exttestedwith:
752 752 fm.plain(_(' (untested!)\n'))
753 753 else:
754 754 lasttestedversion = exttestedwith[-1]
755 755 fm.plain(' (%s!)\n' % lasttestedversion)
756 756
757 757 fm.condwrite(ui.verbose and extsource, 'source',
758 758 _(' location: %s\n'), extsource or "")
759 759
760 760 if ui.verbose:
761 761 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
762 762 fm.data(bundled=isinternal)
763 763
764 764 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
765 765 _(' tested with: %s\n'),
766 766 fm.formatlist(exttestedwith, name='ver'))
767 767
768 768 fm.condwrite(ui.verbose and extbuglink, 'buglink',
769 769 _(' bug reporting: %s\n'), extbuglink or "")
770 770
771 771 fm.end()
772 772
773 773 @command('debugfileset',
774 774 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
775 775 _('[-r REV] FILESPEC'))
776 776 def debugfileset(ui, repo, expr, **opts):
777 777 '''parse and apply a fileset specification'''
778 778 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
779 779 if ui.verbose:
780 780 tree = fileset.parse(expr)
781 781 ui.note(fileset.prettyformat(tree), "\n")
782 782
783 783 for f in ctx.getfileset(expr):
784 784 ui.write("%s\n" % f)
785 785
786 786 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
787 787 def debugfsinfo(ui, path="."):
788 788 """show information detected about current filesystem"""
789 789 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
790 790 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
791 791 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
792 792 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
793 793 casesensitive = '(unknown)'
794 794 try:
795 795 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
796 796 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
797 797 except OSError:
798 798 pass
799 799 ui.write(('case-sensitive: %s\n') % casesensitive)
800 800
801 801 @command('debuggetbundle',
802 802 [('H', 'head', [], _('id of head node'), _('ID')),
803 803 ('C', 'common', [], _('id of common node'), _('ID')),
804 804 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
805 805 _('REPO FILE [-H|-C ID]...'),
806 806 norepo=True)
807 807 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
808 808 """retrieves a bundle from a repo
809 809
810 810 Every ID must be a full-length hex node id string. Saves the bundle to the
811 811 given file.
812 812 """
813 813 repo = hg.peer(ui, opts, repopath)
814 814 if not repo.capable('getbundle'):
815 815 raise error.Abort("getbundle() not supported by target repository")
816 816 args = {}
817 817 if common:
818 818 args['common'] = [bin(s) for s in common]
819 819 if head:
820 820 args['heads'] = [bin(s) for s in head]
821 821 # TODO: get desired bundlecaps from command line.
822 822 args['bundlecaps'] = None
823 823 bundle = repo.getbundle('debug', **args)
824 824
825 825 bundletype = opts.get('type', 'bzip2').lower()
826 826 btypes = {'none': 'HG10UN',
827 827 'bzip2': 'HG10BZ',
828 828 'gzip': 'HG10GZ',
829 829 'bundle2': 'HG20'}
830 830 bundletype = btypes.get(bundletype)
831 831 if bundletype not in bundle2.bundletypes:
832 832 raise error.Abort(_('unknown bundle type specified with --type'))
833 833 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
834 834
835 835 @command('debugignore', [], '[FILE]')
836 836 def debugignore(ui, repo, *files, **opts):
837 837 """display the combined ignore pattern and information about ignored files
838 838
839 839 With no argument display the combined ignore pattern.
840 840
841 841 Given space separated file names, shows if the given file is ignored and
842 842 if so, show the ignore rule (file and line number) that matched it.
843 843 """
844 844 ignore = repo.dirstate._ignore
845 845 if not files:
846 846 # Show all the patterns
847 847 ui.write("%s\n" % repr(ignore))
848 848 else:
849 849 for f in files:
850 850 nf = util.normpath(f)
851 851 ignored = None
852 852 ignoredata = None
853 853 if nf != '.':
854 854 if ignore(nf):
855 855 ignored = nf
856 856 ignoredata = repo.dirstate._ignorefileandline(nf)
857 857 else:
858 858 for p in util.finddirs(nf):
859 859 if ignore(p):
860 860 ignored = p
861 861 ignoredata = repo.dirstate._ignorefileandline(p)
862 862 break
863 863 if ignored:
864 864 if ignored == nf:
865 865 ui.write(_("%s is ignored\n") % f)
866 866 else:
867 867 ui.write(_("%s is ignored because of "
868 868 "containing folder %s\n")
869 869 % (f, ignored))
870 870 ignorefile, lineno, line = ignoredata
871 871 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
872 872 % (ignorefile, lineno, line))
873 873 else:
874 874 ui.write(_("%s is not ignored\n") % f)
875 875
876 876 @command('debugindex', cmdutil.debugrevlogopts +
877 877 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
878 878 _('[-f FORMAT] -c|-m|FILE'),
879 879 optionalrepo=True)
880 880 def debugindex(ui, repo, file_=None, **opts):
881 881 """dump the contents of an index file"""
882 882 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
883 883 format = opts.get('format', 0)
884 884 if format not in (0, 1):
885 885 raise error.Abort(_("unknown format %d") % format)
886 886
887 887 generaldelta = r.version & revlog.FLAG_GENERALDELTA
888 888 if generaldelta:
889 889 basehdr = ' delta'
890 890 else:
891 891 basehdr = ' base'
892 892
893 893 if ui.debugflag:
894 894 shortfn = hex
895 895 else:
896 896 shortfn = short
897 897
898 898 # There might not be anything in r, so have a sane default
899 899 idlen = 12
900 900 for i in r:
901 901 idlen = len(shortfn(r.node(i)))
902 902 break
903 903
904 904 if format == 0:
905 905 ui.write((" rev offset length " + basehdr + " linkrev"
906 906 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
907 907 elif format == 1:
908 908 ui.write((" rev flag offset length"
909 909 " size " + basehdr + " link p1 p2"
910 910 " %s\n") % "nodeid".rjust(idlen))
911 911
912 912 for i in r:
913 913 node = r.node(i)
914 914 if generaldelta:
915 915 base = r.deltaparent(i)
916 916 else:
917 917 base = r.chainbase(i)
918 918 if format == 0:
919 919 try:
920 920 pp = r.parents(node)
921 921 except Exception:
922 922 pp = [nullid, nullid]
923 923 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
924 924 i, r.start(i), r.length(i), base, r.linkrev(i),
925 925 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
926 926 elif format == 1:
927 927 pr = r.parentrevs(i)
928 928 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
929 929 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
930 930 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
931 931
932 932 @command('debugindexdot', cmdutil.debugrevlogopts,
933 933 _('-c|-m|FILE'), optionalrepo=True)
934 934 def debugindexdot(ui, repo, file_=None, **opts):
935 935 """dump an index DAG as a graphviz dot file"""
936 936 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
937 937 ui.write(("digraph G {\n"))
938 938 for i in r:
939 939 node = r.node(i)
940 940 pp = r.parents(node)
941 941 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
942 942 if pp[1] != nullid:
943 943 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
944 944 ui.write("}\n")
945 945
946 946 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
947 947 def debuginstall(ui, **opts):
948 948 '''test Mercurial installation
949 949
950 950 Returns 0 on success.
951 951 '''
952 952
953 953 def writetemp(contents):
954 954 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
955 955 f = os.fdopen(fd, pycompat.sysstr("wb"))
956 956 f.write(contents)
957 957 f.close()
958 958 return name
959 959
960 960 problems = 0
961 961
962 962 fm = ui.formatter('debuginstall', opts)
963 963 fm.startitem()
964 964
965 965 # encoding
966 966 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
967 967 err = None
968 968 try:
969 969 encoding.fromlocal("test")
970 970 except error.Abort as inst:
971 971 err = inst
972 972 problems += 1
973 973 fm.condwrite(err, 'encodingerror', _(" %s\n"
974 974 " (check that your locale is properly set)\n"), err)
975 975
976 976 # Python
977 977 fm.write('pythonexe', _("checking Python executable (%s)\n"),
978 978 pycompat.sysexecutable)
979 979 fm.write('pythonver', _("checking Python version (%s)\n"),
980 980 ("%d.%d.%d" % sys.version_info[:3]))
981 981 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
982 982 os.path.dirname(pycompat.fsencode(os.__file__)))
983 983
984 984 security = set(sslutil.supportedprotocols)
985 985 if sslutil.hassni:
986 986 security.add('sni')
987 987
988 988 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
989 989 fm.formatlist(sorted(security), name='protocol',
990 990 fmt='%s', sep=','))
991 991
992 992 # These are warnings, not errors. So don't increment problem count. This
993 993 # may change in the future.
994 994 if 'tls1.2' not in security:
995 995 fm.plain(_(' TLS 1.2 not supported by Python install; '
996 996 'network connections lack modern security\n'))
997 997 if 'sni' not in security:
998 998 fm.plain(_(' SNI not supported by Python install; may have '
999 999 'connectivity issues with some servers\n'))
1000 1000
1001 1001 # TODO print CA cert info
1002 1002
1003 1003 # hg version
1004 1004 hgver = util.version()
1005 1005 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1006 1006 hgver.split('+')[0])
1007 1007 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1008 1008 '+'.join(hgver.split('+')[1:]))
1009 1009
1010 1010 # compiled modules
1011 1011 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1012 1012 policy.policy)
1013 1013 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1014 1014 os.path.dirname(pycompat.fsencode(__file__)))
1015 1015
1016 1016 if policy.policy in ('c', 'allow'):
1017 1017 err = None
1018 1018 try:
1019 1019 from .cext import (
1020 1020 base85,
1021 1021 bdiff,
1022 1022 mpatch,
1023 1023 osutil,
1024 1024 )
1025 1025 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1026 1026 except Exception as inst:
1027 1027 err = inst
1028 1028 problems += 1
1029 1029 fm.condwrite(err, 'extensionserror', " %s\n", err)
1030 1030
1031 1031 compengines = util.compengines._engines.values()
1032 1032 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1033 1033 fm.formatlist(sorted(e.name() for e in compengines),
1034 1034 name='compengine', fmt='%s', sep=', '))
1035 1035 fm.write('compenginesavail', _('checking available compression engines '
1036 1036 '(%s)\n'),
1037 1037 fm.formatlist(sorted(e.name() for e in compengines
1038 1038 if e.available()),
1039 1039 name='compengine', fmt='%s', sep=', '))
1040 1040 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1041 1041 fm.write('compenginesserver', _('checking available compression engines '
1042 1042 'for wire protocol (%s)\n'),
1043 1043 fm.formatlist([e.name() for e in wirecompengines
1044 1044 if e.wireprotosupport()],
1045 1045 name='compengine', fmt='%s', sep=', '))
1046 1046
1047 1047 # templates
1048 1048 p = templater.templatepaths()
1049 1049 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1050 1050 fm.condwrite(not p, '', _(" no template directories found\n"))
1051 1051 if p:
1052 1052 m = templater.templatepath("map-cmdline.default")
1053 1053 if m:
1054 1054 # template found, check if it is working
1055 1055 err = None
1056 1056 try:
1057 1057 templater.templater.frommapfile(m)
1058 1058 except Exception as inst:
1059 1059 err = inst
1060 1060 p = None
1061 1061 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1062 1062 else:
1063 1063 p = None
1064 1064 fm.condwrite(p, 'defaulttemplate',
1065 1065 _("checking default template (%s)\n"), m)
1066 1066 fm.condwrite(not m, 'defaulttemplatenotfound',
1067 1067 _(" template '%s' not found\n"), "default")
1068 1068 if not p:
1069 1069 problems += 1
1070 1070 fm.condwrite(not p, '',
1071 1071 _(" (templates seem to have been installed incorrectly)\n"))
1072 1072
1073 1073 # editor
1074 1074 editor = ui.geteditor()
1075 1075 editor = util.expandpath(editor)
1076 1076 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
1077 1077 cmdpath = util.findexe(pycompat.shlexsplit(editor)[0])
1078 1078 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1079 1079 _(" No commit editor set and can't find %s in PATH\n"
1080 1080 " (specify a commit editor in your configuration"
1081 1081 " file)\n"), not cmdpath and editor == 'vi' and editor)
1082 1082 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1083 1083 _(" Can't find editor '%s' in PATH\n"
1084 1084 " (specify a commit editor in your configuration"
1085 1085 " file)\n"), not cmdpath and editor)
1086 1086 if not cmdpath and editor != 'vi':
1087 1087 problems += 1
1088 1088
1089 1089 # check username
1090 1090 username = None
1091 1091 err = None
1092 1092 try:
1093 1093 username = ui.username()
1094 1094 except error.Abort as e:
1095 1095 err = e
1096 1096 problems += 1
1097 1097
1098 1098 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1099 1099 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1100 1100 " (specify a username in your configuration file)\n"), err)
1101 1101
1102 1102 fm.condwrite(not problems, '',
1103 1103 _("no problems detected\n"))
1104 1104 if not problems:
1105 1105 fm.data(problems=problems)
1106 1106 fm.condwrite(problems, 'problems',
1107 1107 _("%d problems detected,"
1108 1108 " please check your install!\n"), problems)
1109 1109 fm.end()
1110 1110
1111 1111 return problems
1112 1112
1113 1113 @command('debugknown', [], _('REPO ID...'), norepo=True)
1114 1114 def debugknown(ui, repopath, *ids, **opts):
1115 1115 """test whether node ids are known to a repo
1116 1116
1117 1117 Every ID must be a full-length hex node id string. Returns a list of 0s
1118 1118 and 1s indicating unknown/known.
1119 1119 """
1120 1120 repo = hg.peer(ui, opts, repopath)
1121 1121 if not repo.capable('known'):
1122 1122 raise error.Abort("known() not supported by target repository")
1123 1123 flags = repo.known([bin(s) for s in ids])
1124 1124 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1125 1125
1126 1126 @command('debuglabelcomplete', [], _('LABEL...'))
1127 1127 def debuglabelcomplete(ui, repo, *args):
1128 1128 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1129 1129 debugnamecomplete(ui, repo, *args)
1130 1130
1131 1131 @command('debuglocks',
1132 1132 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1133 1133 ('W', 'force-wlock', None,
1134 1134 _('free the working state lock (DANGEROUS)'))],
1135 1135 _('[OPTION]...'))
1136 1136 def debuglocks(ui, repo, **opts):
1137 1137 """show or modify state of locks
1138 1138
1139 1139 By default, this command will show which locks are held. This
1140 1140 includes the user and process holding the lock, the amount of time
1141 1141 the lock has been held, and the machine name where the process is
1142 1142 running if it's not local.
1143 1143
1144 1144 Locks protect the integrity of Mercurial's data, so should be
1145 1145 treated with care. System crashes or other interruptions may cause
1146 1146 locks to not be properly released, though Mercurial will usually
1147 1147 detect and remove such stale locks automatically.
1148 1148
1149 1149 However, detecting stale locks may not always be possible (for
1150 1150 instance, on a shared filesystem). Removing locks may also be
1151 1151 blocked by filesystem permissions.
1152 1152
1153 1153 Returns 0 if no locks are held.
1154 1154
1155 1155 """
1156 1156
1157 1157 if opts.get('force_lock'):
1158 1158 repo.svfs.unlink('lock')
1159 1159 if opts.get('force_wlock'):
1160 1160 repo.vfs.unlink('wlock')
1161 1161 if opts.get('force_lock') or opts.get('force_lock'):
1162 1162 return 0
1163 1163
1164 1164 now = time.time()
1165 1165 held = 0
1166 1166
1167 1167 def report(vfs, name, method):
1168 1168 # this causes stale locks to get reaped for more accurate reporting
1169 1169 try:
1170 1170 l = method(False)
1171 1171 except error.LockHeld:
1172 1172 l = None
1173 1173
1174 1174 if l:
1175 1175 l.release()
1176 1176 else:
1177 1177 try:
1178 1178 stat = vfs.lstat(name)
1179 1179 age = now - stat.st_mtime
1180 1180 user = util.username(stat.st_uid)
1181 1181 locker = vfs.readlock(name)
1182 1182 if ":" in locker:
1183 1183 host, pid = locker.split(':')
1184 1184 if host == socket.gethostname():
1185 1185 locker = 'user %s, process %s' % (user, pid)
1186 1186 else:
1187 1187 locker = 'user %s, process %s, host %s' \
1188 1188 % (user, pid, host)
1189 1189 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1190 1190 return 1
1191 1191 except OSError as e:
1192 1192 if e.errno != errno.ENOENT:
1193 1193 raise
1194 1194
1195 1195 ui.write(("%-6s free\n") % (name + ":"))
1196 1196 return 0
1197 1197
1198 1198 held += report(repo.svfs, "lock", repo.lock)
1199 1199 held += report(repo.vfs, "wlock", repo.wlock)
1200 1200
1201 1201 return held
1202 1202
1203 1203 @command('debugmergestate', [], '')
1204 1204 def debugmergestate(ui, repo, *args):
1205 1205 """print merge state
1206 1206
1207 1207 Use --verbose to print out information about whether v1 or v2 merge state
1208 1208 was chosen."""
1209 1209 def _hashornull(h):
1210 1210 if h == nullhex:
1211 1211 return 'null'
1212 1212 else:
1213 1213 return h
1214 1214
1215 1215 def printrecords(version):
1216 1216 ui.write(('* version %s records\n') % version)
1217 1217 if version == 1:
1218 1218 records = v1records
1219 1219 else:
1220 1220 records = v2records
1221 1221
1222 1222 for rtype, record in records:
1223 1223 # pretty print some record types
1224 1224 if rtype == 'L':
1225 1225 ui.write(('local: %s\n') % record)
1226 1226 elif rtype == 'O':
1227 1227 ui.write(('other: %s\n') % record)
1228 1228 elif rtype == 'm':
1229 1229 driver, mdstate = record.split('\0', 1)
1230 1230 ui.write(('merge driver: %s (state "%s")\n')
1231 1231 % (driver, mdstate))
1232 1232 elif rtype in 'FDC':
1233 1233 r = record.split('\0')
1234 1234 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1235 1235 if version == 1:
1236 1236 onode = 'not stored in v1 format'
1237 1237 flags = r[7]
1238 1238 else:
1239 1239 onode, flags = r[7:9]
1240 1240 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1241 1241 % (f, rtype, state, _hashornull(hash)))
1242 1242 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1243 1243 ui.write((' ancestor path: %s (node %s)\n')
1244 1244 % (afile, _hashornull(anode)))
1245 1245 ui.write((' other path: %s (node %s)\n')
1246 1246 % (ofile, _hashornull(onode)))
1247 1247 elif rtype == 'f':
1248 1248 filename, rawextras = record.split('\0', 1)
1249 1249 extras = rawextras.split('\0')
1250 1250 i = 0
1251 1251 extrastrings = []
1252 1252 while i < len(extras):
1253 1253 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1254 1254 i += 2
1255 1255
1256 1256 ui.write(('file extras: %s (%s)\n')
1257 1257 % (filename, ', '.join(extrastrings)))
1258 1258 elif rtype == 'l':
1259 1259 labels = record.split('\0', 2)
1260 1260 labels = [l for l in labels if len(l) > 0]
1261 1261 ui.write(('labels:\n'))
1262 1262 ui.write((' local: %s\n' % labels[0]))
1263 1263 ui.write((' other: %s\n' % labels[1]))
1264 1264 if len(labels) > 2:
1265 1265 ui.write((' base: %s\n' % labels[2]))
1266 1266 else:
1267 1267 ui.write(('unrecognized entry: %s\t%s\n')
1268 1268 % (rtype, record.replace('\0', '\t')))
1269 1269
1270 1270 # Avoid mergestate.read() since it may raise an exception for unsupported
1271 1271 # merge state records. We shouldn't be doing this, but this is OK since this
1272 1272 # command is pretty low-level.
1273 1273 ms = mergemod.mergestate(repo)
1274 1274
1275 1275 # sort so that reasonable information is on top
1276 1276 v1records = ms._readrecordsv1()
1277 1277 v2records = ms._readrecordsv2()
1278 1278 order = 'LOml'
1279 1279 def key(r):
1280 1280 idx = order.find(r[0])
1281 1281 if idx == -1:
1282 1282 return (1, r[1])
1283 1283 else:
1284 1284 return (0, idx)
1285 1285 v1records.sort(key=key)
1286 1286 v2records.sort(key=key)
1287 1287
1288 1288 if not v1records and not v2records:
1289 1289 ui.write(('no merge state found\n'))
1290 1290 elif not v2records:
1291 1291 ui.note(('no version 2 merge state\n'))
1292 1292 printrecords(1)
1293 1293 elif ms._v1v2match(v1records, v2records):
1294 1294 ui.note(('v1 and v2 states match: using v2\n'))
1295 1295 printrecords(2)
1296 1296 else:
1297 1297 ui.note(('v1 and v2 states mismatch: using v1\n'))
1298 1298 printrecords(1)
1299 1299 if ui.verbose:
1300 1300 printrecords(2)
1301 1301
1302 1302 @command('debugnamecomplete', [], _('NAME...'))
1303 1303 def debugnamecomplete(ui, repo, *args):
1304 1304 '''complete "names" - tags, open branch names, bookmark names'''
1305 1305
1306 1306 names = set()
1307 1307 # since we previously only listed open branches, we will handle that
1308 1308 # specially (after this for loop)
1309 1309 for name, ns in repo.names.iteritems():
1310 1310 if name != 'branches':
1311 1311 names.update(ns.listnames(repo))
1312 1312 names.update(tag for (tag, heads, tip, closed)
1313 1313 in repo.branchmap().iterbranches() if not closed)
1314 1314 completions = set()
1315 1315 if not args:
1316 1316 args = ['']
1317 1317 for a in args:
1318 1318 completions.update(n for n in names if n.startswith(a))
1319 1319 ui.write('\n'.join(sorted(completions)))
1320 1320 ui.write('\n')
1321 1321
1322 1322 @command('debugobsolete',
1323 1323 [('', 'flags', 0, _('markers flag')),
1324 1324 ('', 'record-parents', False,
1325 1325 _('record parent information for the precursor')),
1326 1326 ('r', 'rev', [], _('display markers relevant to REV')),
1327 1327 ('', 'exclusive', False, _('restrict display to markers only '
1328 1328 'relevant to REV')),
1329 1329 ('', 'index', False, _('display index of the marker')),
1330 1330 ('', 'delete', [], _('delete markers specified by indices')),
1331 1331 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1332 1332 _('[OBSOLETED [REPLACEMENT ...]]'))
1333 1333 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1334 1334 """create arbitrary obsolete marker
1335 1335
1336 1336 With no arguments, displays the list of obsolescence markers."""
1337 1337
1338 1338 def parsenodeid(s):
1339 1339 try:
1340 1340 # We do not use revsingle/revrange functions here to accept
1341 1341 # arbitrary node identifiers, possibly not present in the
1342 1342 # local repository.
1343 1343 n = bin(s)
1344 1344 if len(n) != len(nullid):
1345 1345 raise TypeError()
1346 1346 return n
1347 1347 except TypeError:
1348 1348 raise error.Abort('changeset references must be full hexadecimal '
1349 1349 'node identifiers')
1350 1350
1351 1351 if opts.get('delete'):
1352 1352 indices = []
1353 1353 for v in opts.get('delete'):
1354 1354 try:
1355 1355 indices.append(int(v))
1356 1356 except ValueError:
1357 1357 raise error.Abort(_('invalid index value: %r') % v,
1358 1358 hint=_('use integers for indices'))
1359 1359
1360 1360 if repo.currenttransaction():
1361 1361 raise error.Abort(_('cannot delete obsmarkers in the middle '
1362 1362 'of transaction.'))
1363 1363
1364 1364 with repo.lock():
1365 1365 n = repair.deleteobsmarkers(repo.obsstore, indices)
1366 1366 ui.write(_('deleted %i obsolescence markers\n') % n)
1367 1367
1368 1368 return
1369 1369
1370 1370 if precursor is not None:
1371 1371 if opts['rev']:
1372 1372 raise error.Abort('cannot select revision when creating marker')
1373 1373 metadata = {}
1374 1374 metadata['user'] = opts['user'] or ui.username()
1375 1375 succs = tuple(parsenodeid(succ) for succ in successors)
1376 1376 l = repo.lock()
1377 1377 try:
1378 1378 tr = repo.transaction('debugobsolete')
1379 1379 try:
1380 1380 date = opts.get('date')
1381 1381 if date:
1382 1382 date = util.parsedate(date)
1383 1383 else:
1384 1384 date = None
1385 1385 prec = parsenodeid(precursor)
1386 1386 parents = None
1387 1387 if opts['record_parents']:
1388 1388 if prec not in repo.unfiltered():
1389 1389 raise error.Abort('cannot used --record-parents on '
1390 1390 'unknown changesets')
1391 1391 parents = repo.unfiltered()[prec].parents()
1392 1392 parents = tuple(p.node() for p in parents)
1393 1393 repo.obsstore.create(tr, prec, succs, opts['flags'],
1394 1394 parents=parents, date=date,
1395 1395 metadata=metadata, ui=ui)
1396 1396 tr.close()
1397 1397 except ValueError as exc:
1398 1398 raise error.Abort(_('bad obsmarker input: %s') % exc)
1399 1399 finally:
1400 1400 tr.release()
1401 1401 finally:
1402 1402 l.release()
1403 1403 else:
1404 1404 if opts['rev']:
1405 1405 revs = scmutil.revrange(repo, opts['rev'])
1406 1406 nodes = [repo[r].node() for r in revs]
1407 1407 markers = list(obsolete.getmarkers(repo, nodes=nodes,
1408 1408 exclusive=opts['exclusive']))
1409 1409 markers.sort(key=lambda x: x._data)
1410 1410 else:
1411 1411 markers = obsolete.getmarkers(repo)
1412 1412
1413 1413 markerstoiter = markers
1414 1414 isrelevant = lambda m: True
1415 1415 if opts.get('rev') and opts.get('index'):
1416 1416 markerstoiter = obsolete.getmarkers(repo)
1417 1417 markerset = set(markers)
1418 1418 isrelevant = lambda m: m in markerset
1419 1419
1420 1420 fm = ui.formatter('debugobsolete', opts)
1421 1421 for i, m in enumerate(markerstoiter):
1422 1422 if not isrelevant(m):
1423 1423 # marker can be irrelevant when we're iterating over a set
1424 1424 # of markers (markerstoiter) which is bigger than the set
1425 1425 # of markers we want to display (markers)
1426 1426 # this can happen if both --index and --rev options are
1427 1427 # provided and thus we need to iterate over all of the markers
1428 1428 # to get the correct indices, but only display the ones that
1429 1429 # are relevant to --rev value
1430 1430 continue
1431 1431 fm.startitem()
1432 1432 ind = i if opts.get('index') else None
1433 1433 cmdutil.showmarker(fm, m, index=ind)
1434 1434 fm.end()
1435 1435
1436 1436 @command('debugpathcomplete',
1437 1437 [('f', 'full', None, _('complete an entire path')),
1438 1438 ('n', 'normal', None, _('show only normal files')),
1439 1439 ('a', 'added', None, _('show only added files')),
1440 1440 ('r', 'removed', None, _('show only removed files'))],
1441 1441 _('FILESPEC...'))
1442 1442 def debugpathcomplete(ui, repo, *specs, **opts):
1443 1443 '''complete part or all of a tracked path
1444 1444
1445 1445 This command supports shells that offer path name completion. It
1446 1446 currently completes only files already known to the dirstate.
1447 1447
1448 1448 Completion extends only to the next path segment unless
1449 1449 --full is specified, in which case entire paths are used.'''
1450 1450
1451 1451 def complete(path, acceptable):
1452 1452 dirstate = repo.dirstate
1453 1453 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1454 1454 rootdir = repo.root + pycompat.ossep
1455 1455 if spec != repo.root and not spec.startswith(rootdir):
1456 1456 return [], []
1457 1457 if os.path.isdir(spec):
1458 1458 spec += '/'
1459 1459 spec = spec[len(rootdir):]
1460 1460 fixpaths = pycompat.ossep != '/'
1461 1461 if fixpaths:
1462 1462 spec = spec.replace(pycompat.ossep, '/')
1463 1463 speclen = len(spec)
1464 1464 fullpaths = opts['full']
1465 1465 files, dirs = set(), set()
1466 1466 adddir, addfile = dirs.add, files.add
1467 1467 for f, st in dirstate.iteritems():
1468 1468 if f.startswith(spec) and st[0] in acceptable:
1469 1469 if fixpaths:
1470 1470 f = f.replace('/', pycompat.ossep)
1471 1471 if fullpaths:
1472 1472 addfile(f)
1473 1473 continue
1474 1474 s = f.find(pycompat.ossep, speclen)
1475 1475 if s >= 0:
1476 1476 adddir(f[:s])
1477 1477 else:
1478 1478 addfile(f)
1479 1479 return files, dirs
1480 1480
1481 1481 acceptable = ''
1482 1482 if opts['normal']:
1483 1483 acceptable += 'nm'
1484 1484 if opts['added']:
1485 1485 acceptable += 'a'
1486 1486 if opts['removed']:
1487 1487 acceptable += 'r'
1488 1488 cwd = repo.getcwd()
1489 1489 if not specs:
1490 1490 specs = ['.']
1491 1491
1492 1492 files, dirs = set(), set()
1493 1493 for spec in specs:
1494 1494 f, d = complete(spec, acceptable or 'nmar')
1495 1495 files.update(f)
1496 1496 dirs.update(d)
1497 1497 files.update(dirs)
1498 1498 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1499 1499 ui.write('\n')
1500 1500
1501 1501 @command('debugpickmergetool',
1502 1502 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1503 1503 ('', 'changedelete', None, _('emulate merging change and delete')),
1504 1504 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1505 1505 _('[PATTERN]...'),
1506 1506 inferrepo=True)
1507 1507 def debugpickmergetool(ui, repo, *pats, **opts):
1508 1508 """examine which merge tool is chosen for specified file
1509 1509
1510 1510 As described in :hg:`help merge-tools`, Mercurial examines
1511 1511 configurations below in this order to decide which merge tool is
1512 1512 chosen for specified file.
1513 1513
1514 1514 1. ``--tool`` option
1515 1515 2. ``HGMERGE`` environment variable
1516 1516 3. configurations in ``merge-patterns`` section
1517 1517 4. configuration of ``ui.merge``
1518 1518 5. configurations in ``merge-tools`` section
1519 1519 6. ``hgmerge`` tool (for historical reason only)
1520 1520 7. default tool for fallback (``:merge`` or ``:prompt``)
1521 1521
1522 1522 This command writes out examination result in the style below::
1523 1523
1524 1524 FILE = MERGETOOL
1525 1525
1526 1526 By default, all files known in the first parent context of the
1527 1527 working directory are examined. Use file patterns and/or -I/-X
1528 1528 options to limit target files. -r/--rev is also useful to examine
1529 1529 files in another context without actual updating to it.
1530 1530
1531 1531 With --debug, this command shows warning messages while matching
1532 1532 against ``merge-patterns`` and so on, too. It is recommended to
1533 1533 use this option with explicit file patterns and/or -I/-X options,
1534 1534 because this option increases amount of output per file according
1535 1535 to configurations in hgrc.
1536 1536
1537 1537 With -v/--verbose, this command shows configurations below at
1538 1538 first (only if specified).
1539 1539
1540 1540 - ``--tool`` option
1541 1541 - ``HGMERGE`` environment variable
1542 1542 - configuration of ``ui.merge``
1543 1543
1544 1544 If merge tool is chosen before matching against
1545 1545 ``merge-patterns``, this command can't show any helpful
1546 1546 information, even with --debug. In such case, information above is
1547 1547 useful to know why a merge tool is chosen.
1548 1548 """
1549 1549 overrides = {}
1550 1550 if opts['tool']:
1551 1551 overrides[('ui', 'forcemerge')] = opts['tool']
1552 1552 ui.note(('with --tool %r\n') % (opts['tool']))
1553 1553
1554 1554 with ui.configoverride(overrides, 'debugmergepatterns'):
1555 1555 hgmerge = encoding.environ.get("HGMERGE")
1556 1556 if hgmerge is not None:
1557 1557 ui.note(('with HGMERGE=%r\n') % (hgmerge))
1558 1558 uimerge = ui.config("ui", "merge")
1559 1559 if uimerge:
1560 1560 ui.note(('with ui.merge=%r\n') % (uimerge))
1561 1561
1562 1562 ctx = scmutil.revsingle(repo, opts.get('rev'))
1563 1563 m = scmutil.match(ctx, pats, opts)
1564 1564 changedelete = opts['changedelete']
1565 1565 for path in ctx.walk(m):
1566 1566 fctx = ctx[path]
1567 1567 try:
1568 1568 if not ui.debugflag:
1569 1569 ui.pushbuffer(error=True)
1570 1570 tool, toolpath = filemerge._picktool(repo, ui, path,
1571 1571 fctx.isbinary(),
1572 1572 'l' in fctx.flags(),
1573 1573 changedelete)
1574 1574 finally:
1575 1575 if not ui.debugflag:
1576 1576 ui.popbuffer()
1577 1577 ui.write(('%s = %s\n') % (path, tool))
1578 1578
1579 1579 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1580 1580 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1581 1581 '''access the pushkey key/value protocol
1582 1582
1583 1583 With two args, list the keys in the given namespace.
1584 1584
1585 1585 With five args, set a key to new if it currently is set to old.
1586 1586 Reports success or failure.
1587 1587 '''
1588 1588
1589 1589 target = hg.peer(ui, {}, repopath)
1590 1590 if keyinfo:
1591 1591 key, old, new = keyinfo
1592 1592 r = target.pushkey(namespace, key, old, new)
1593 1593 ui.status(str(r) + '\n')
1594 1594 return not r
1595 1595 else:
1596 1596 for k, v in sorted(target.listkeys(namespace).iteritems()):
1597 1597 ui.write("%s\t%s\n" % (util.escapestr(k),
1598 1598 util.escapestr(v)))
1599 1599
1600 1600 @command('debugpvec', [], _('A B'))
1601 1601 def debugpvec(ui, repo, a, b=None):
1602 1602 ca = scmutil.revsingle(repo, a)
1603 1603 cb = scmutil.revsingle(repo, b)
1604 1604 pa = pvec.ctxpvec(ca)
1605 1605 pb = pvec.ctxpvec(cb)
1606 1606 if pa == pb:
1607 1607 rel = "="
1608 1608 elif pa > pb:
1609 1609 rel = ">"
1610 1610 elif pa < pb:
1611 1611 rel = "<"
1612 1612 elif pa | pb:
1613 1613 rel = "|"
1614 1614 ui.write(_("a: %s\n") % pa)
1615 1615 ui.write(_("b: %s\n") % pb)
1616 1616 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1617 1617 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1618 1618 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1619 1619 pa.distance(pb), rel))
1620 1620
1621 1621 @command('debugrebuilddirstate|debugrebuildstate',
1622 1622 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1623 1623 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1624 1624 'the working copy parent')),
1625 1625 ],
1626 1626 _('[-r REV]'))
1627 1627 def debugrebuilddirstate(ui, repo, rev, **opts):
1628 1628 """rebuild the dirstate as it would look like for the given revision
1629 1629
1630 1630 If no revision is specified the first current parent will be used.
1631 1631
1632 1632 The dirstate will be set to the files of the given revision.
1633 1633 The actual working directory content or existing dirstate
1634 1634 information such as adds or removes is not considered.
1635 1635
1636 1636 ``minimal`` will only rebuild the dirstate status for files that claim to be
1637 1637 tracked but are not in the parent manifest, or that exist in the parent
1638 1638 manifest but are not in the dirstate. It will not change adds, removes, or
1639 1639 modified files that are in the working copy parent.
1640 1640
1641 1641 One use of this command is to make the next :hg:`status` invocation
1642 1642 check the actual file content.
1643 1643 """
1644 1644 ctx = scmutil.revsingle(repo, rev)
1645 1645 with repo.wlock():
1646 1646 dirstate = repo.dirstate
1647 1647 changedfiles = None
1648 1648 # See command doc for what minimal does.
1649 1649 if opts.get('minimal'):
1650 1650 manifestfiles = set(ctx.manifest().keys())
1651 1651 dirstatefiles = set(dirstate)
1652 1652 manifestonly = manifestfiles - dirstatefiles
1653 1653 dsonly = dirstatefiles - manifestfiles
1654 1654 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1655 1655 changedfiles = manifestonly | dsnotadded
1656 1656
1657 1657 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1658 1658
1659 1659 @command('debugrebuildfncache', [], '')
1660 1660 def debugrebuildfncache(ui, repo):
1661 1661 """rebuild the fncache file"""
1662 1662 repair.rebuildfncache(ui, repo)
1663 1663
1664 1664 @command('debugrename',
1665 1665 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1666 1666 _('[-r REV] FILE'))
1667 1667 def debugrename(ui, repo, file1, *pats, **opts):
1668 1668 """dump rename information"""
1669 1669
1670 1670 ctx = scmutil.revsingle(repo, opts.get('rev'))
1671 1671 m = scmutil.match(ctx, (file1,) + pats, opts)
1672 1672 for abs in ctx.walk(m):
1673 1673 fctx = ctx[abs]
1674 1674 o = fctx.filelog().renamed(fctx.filenode())
1675 1675 rel = m.rel(abs)
1676 1676 if o:
1677 1677 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1678 1678 else:
1679 1679 ui.write(_("%s not renamed\n") % rel)
1680 1680
1681 1681 @command('debugrevlog', cmdutil.debugrevlogopts +
1682 1682 [('d', 'dump', False, _('dump index data'))],
1683 1683 _('-c|-m|FILE'),
1684 1684 optionalrepo=True)
1685 1685 def debugrevlog(ui, repo, file_=None, **opts):
1686 1686 """show data and statistics about a revlog"""
1687 1687 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1688 1688
1689 1689 if opts.get("dump"):
1690 1690 numrevs = len(r)
1691 1691 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1692 1692 " rawsize totalsize compression heads chainlen\n"))
1693 1693 ts = 0
1694 1694 heads = set()
1695 1695
1696 1696 for rev in xrange(numrevs):
1697 1697 dbase = r.deltaparent(rev)
1698 1698 if dbase == -1:
1699 1699 dbase = rev
1700 1700 cbase = r.chainbase(rev)
1701 1701 clen = r.chainlen(rev)
1702 1702 p1, p2 = r.parentrevs(rev)
1703 1703 rs = r.rawsize(rev)
1704 1704 ts = ts + rs
1705 1705 heads -= set(r.parentrevs(rev))
1706 1706 heads.add(rev)
1707 1707 try:
1708 1708 compression = ts / r.end(rev)
1709 1709 except ZeroDivisionError:
1710 1710 compression = 0
1711 1711 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1712 1712 "%11d %5d %8d\n" %
1713 1713 (rev, p1, p2, r.start(rev), r.end(rev),
1714 1714 r.start(dbase), r.start(cbase),
1715 1715 r.start(p1), r.start(p2),
1716 1716 rs, ts, compression, len(heads), clen))
1717 1717 return 0
1718 1718
1719 1719 v = r.version
1720 1720 format = v & 0xFFFF
1721 1721 flags = []
1722 1722 gdelta = False
1723 1723 if v & revlog.FLAG_INLINE_DATA:
1724 1724 flags.append('inline')
1725 1725 if v & revlog.FLAG_GENERALDELTA:
1726 1726 gdelta = True
1727 1727 flags.append('generaldelta')
1728 1728 if not flags:
1729 1729 flags = ['(none)']
1730 1730
1731 1731 nummerges = 0
1732 1732 numfull = 0
1733 1733 numprev = 0
1734 1734 nump1 = 0
1735 1735 nump2 = 0
1736 1736 numother = 0
1737 1737 nump1prev = 0
1738 1738 nump2prev = 0
1739 1739 chainlengths = []
1740 1740
1741 1741 datasize = [None, 0, 0]
1742 1742 fullsize = [None, 0, 0]
1743 1743 deltasize = [None, 0, 0]
1744 1744 chunktypecounts = {}
1745 1745 chunktypesizes = {}
1746 1746
1747 1747 def addsize(size, l):
1748 1748 if l[0] is None or size < l[0]:
1749 1749 l[0] = size
1750 1750 if size > l[1]:
1751 1751 l[1] = size
1752 1752 l[2] += size
1753 1753
1754 1754 numrevs = len(r)
1755 1755 for rev in xrange(numrevs):
1756 1756 p1, p2 = r.parentrevs(rev)
1757 1757 delta = r.deltaparent(rev)
1758 1758 if format > 0:
1759 1759 addsize(r.rawsize(rev), datasize)
1760 1760 if p2 != nullrev:
1761 1761 nummerges += 1
1762 1762 size = r.length(rev)
1763 1763 if delta == nullrev:
1764 1764 chainlengths.append(0)
1765 1765 numfull += 1
1766 1766 addsize(size, fullsize)
1767 1767 else:
1768 1768 chainlengths.append(chainlengths[delta] + 1)
1769 1769 addsize(size, deltasize)
1770 1770 if delta == rev - 1:
1771 1771 numprev += 1
1772 1772 if delta == p1:
1773 1773 nump1prev += 1
1774 1774 elif delta == p2:
1775 1775 nump2prev += 1
1776 1776 elif delta == p1:
1777 1777 nump1 += 1
1778 1778 elif delta == p2:
1779 1779 nump2 += 1
1780 1780 elif delta != nullrev:
1781 1781 numother += 1
1782 1782
1783 1783 # Obtain data on the raw chunks in the revlog.
1784 1784 segment = r._getsegmentforrevs(rev, rev)[1]
1785 1785 if segment:
1786 1786 chunktype = segment[0]
1787 1787 else:
1788 1788 chunktype = 'empty'
1789 1789
1790 1790 if chunktype not in chunktypecounts:
1791 1791 chunktypecounts[chunktype] = 0
1792 1792 chunktypesizes[chunktype] = 0
1793 1793
1794 1794 chunktypecounts[chunktype] += 1
1795 1795 chunktypesizes[chunktype] += size
1796 1796
1797 1797 # Adjust size min value for empty cases
1798 1798 for size in (datasize, fullsize, deltasize):
1799 1799 if size[0] is None:
1800 1800 size[0] = 0
1801 1801
1802 1802 numdeltas = numrevs - numfull
1803 1803 numoprev = numprev - nump1prev - nump2prev
1804 1804 totalrawsize = datasize[2]
1805 1805 datasize[2] /= numrevs
1806 1806 fulltotal = fullsize[2]
1807 1807 fullsize[2] /= numfull
1808 1808 deltatotal = deltasize[2]
1809 1809 if numrevs - numfull > 0:
1810 1810 deltasize[2] /= numrevs - numfull
1811 1811 totalsize = fulltotal + deltatotal
1812 1812 avgchainlen = sum(chainlengths) / numrevs
1813 1813 maxchainlen = max(chainlengths)
1814 1814 compratio = 1
1815 1815 if totalsize:
1816 1816 compratio = totalrawsize / totalsize
1817 1817
1818 1818 basedfmtstr = '%%%dd\n'
1819 1819 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1820 1820
1821 1821 def dfmtstr(max):
1822 1822 return basedfmtstr % len(str(max))
1823 1823 def pcfmtstr(max, padding=0):
1824 1824 return basepcfmtstr % (len(str(max)), ' ' * padding)
1825 1825
1826 1826 def pcfmt(value, total):
1827 1827 if total:
1828 1828 return (value, 100 * float(value) / total)
1829 1829 else:
1830 1830 return value, 100.0
1831 1831
1832 1832 ui.write(('format : %d\n') % format)
1833 1833 ui.write(('flags : %s\n') % ', '.join(flags))
1834 1834
1835 1835 ui.write('\n')
1836 1836 fmt = pcfmtstr(totalsize)
1837 1837 fmt2 = dfmtstr(totalsize)
1838 1838 ui.write(('revisions : ') + fmt2 % numrevs)
1839 1839 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
1840 1840 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
1841 1841 ui.write(('revisions : ') + fmt2 % numrevs)
1842 1842 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
1843 1843 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
1844 1844 ui.write(('revision size : ') + fmt2 % totalsize)
1845 1845 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
1846 1846 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
1847 1847
1848 1848 def fmtchunktype(chunktype):
1849 1849 if chunktype == 'empty':
1850 1850 return ' %s : ' % chunktype
1851 1851 elif chunktype in string.ascii_letters:
1852 1852 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
1853 1853 else:
1854 1854 return ' 0x%s : ' % hex(chunktype)
1855 1855
1856 1856 ui.write('\n')
1857 1857 ui.write(('chunks : ') + fmt2 % numrevs)
1858 1858 for chunktype in sorted(chunktypecounts):
1859 1859 ui.write(fmtchunktype(chunktype))
1860 1860 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
1861 1861 ui.write(('chunks size : ') + fmt2 % totalsize)
1862 1862 for chunktype in sorted(chunktypecounts):
1863 1863 ui.write(fmtchunktype(chunktype))
1864 1864 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
1865 1865
1866 1866 ui.write('\n')
1867 1867 fmt = dfmtstr(max(avgchainlen, compratio))
1868 1868 ui.write(('avg chain length : ') + fmt % avgchainlen)
1869 1869 ui.write(('max chain length : ') + fmt % maxchainlen)
1870 1870 ui.write(('compression ratio : ') + fmt % compratio)
1871 1871
1872 1872 if format > 0:
1873 1873 ui.write('\n')
1874 1874 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
1875 1875 % tuple(datasize))
1876 1876 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
1877 1877 % tuple(fullsize))
1878 1878 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
1879 1879 % tuple(deltasize))
1880 1880
1881 1881 if numdeltas > 0:
1882 1882 ui.write('\n')
1883 1883 fmt = pcfmtstr(numdeltas)
1884 1884 fmt2 = pcfmtstr(numdeltas, 4)
1885 1885 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
1886 1886 if numprev > 0:
1887 1887 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
1888 1888 numprev))
1889 1889 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
1890 1890 numprev))
1891 1891 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
1892 1892 numprev))
1893 1893 if gdelta:
1894 1894 ui.write(('deltas against p1 : ')
1895 1895 + fmt % pcfmt(nump1, numdeltas))
1896 1896 ui.write(('deltas against p2 : ')
1897 1897 + fmt % pcfmt(nump2, numdeltas))
1898 1898 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
1899 1899 numdeltas))
1900 1900
1901 1901 @command('debugrevspec',
1902 1902 [('', 'optimize', None,
1903 1903 _('print parsed tree after optimizing (DEPRECATED)')),
1904 ('', 'show-revs', True, _('print list of result revisions (default)')),
1904 1905 ('s', 'show-set', None, _('print internal representation of result set')),
1905 1906 ('p', 'show-stage', [],
1906 1907 _('print parsed tree at the given stage'), _('NAME')),
1907 1908 ('', 'no-optimized', False, _('evaluate tree without optimization')),
1908 1909 ('', 'verify-optimized', False, _('verify optimized result')),
1909 1910 ],
1910 1911 ('REVSPEC'))
1911 1912 def debugrevspec(ui, repo, expr, **opts):
1912 1913 """parse and apply a revision specification
1913 1914
1914 1915 Use -p/--show-stage option to print the parsed tree at the given stages.
1915 1916 Use -p all to print tree at every stage.
1916 1917
1918 Use --no-show-revs option with -s or -p to print only the set
1919 representation or the parsed tree respectively.
1920
1917 1921 Use --verify-optimized to compare the optimized result with the unoptimized
1918 1922 one. Returns 1 if the optimized result differs.
1919 1923 """
1920 1924 stages = [
1921 1925 ('parsed', lambda tree: tree),
1922 1926 ('expanded', lambda tree: revsetlang.expandaliases(ui, tree)),
1923 1927 ('concatenated', revsetlang.foldconcat),
1924 1928 ('analyzed', revsetlang.analyze),
1925 1929 ('optimized', revsetlang.optimize),
1926 1930 ]
1927 1931 if opts['no_optimized']:
1928 1932 stages = stages[:-1]
1929 1933 if opts['verify_optimized'] and opts['no_optimized']:
1930 1934 raise error.Abort(_('cannot use --verify-optimized with '
1931 1935 '--no-optimized'))
1932 1936 stagenames = set(n for n, f in stages)
1933 1937
1934 1938 showalways = set()
1935 1939 showchanged = set()
1936 1940 if ui.verbose and not opts['show_stage']:
1937 1941 # show parsed tree by --verbose (deprecated)
1938 1942 showalways.add('parsed')
1939 1943 showchanged.update(['expanded', 'concatenated'])
1940 1944 if opts['optimize']:
1941 1945 showalways.add('optimized')
1942 1946 if opts['show_stage'] and opts['optimize']:
1943 1947 raise error.Abort(_('cannot use --optimize with --show-stage'))
1944 1948 if opts['show_stage'] == ['all']:
1945 1949 showalways.update(stagenames)
1946 1950 else:
1947 1951 for n in opts['show_stage']:
1948 1952 if n not in stagenames:
1949 1953 raise error.Abort(_('invalid stage name: %s') % n)
1950 1954 showalways.update(opts['show_stage'])
1951 1955
1952 1956 treebystage = {}
1953 1957 printedtree = None
1954 1958 tree = revsetlang.parse(expr, lookup=repo.__contains__)
1955 1959 for n, f in stages:
1956 1960 treebystage[n] = tree = f(tree)
1957 1961 if n in showalways or (n in showchanged and tree != printedtree):
1958 1962 if opts['show_stage'] or n != 'parsed':
1959 1963 ui.write(("* %s:\n") % n)
1960 1964 ui.write(revsetlang.prettyformat(tree), "\n")
1961 1965 printedtree = tree
1962 1966
1963 1967 if opts['verify_optimized']:
1964 1968 arevs = revset.makematcher(treebystage['analyzed'])(repo)
1965 1969 brevs = revset.makematcher(treebystage['optimized'])(repo)
1966 1970 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
1967 1971 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
1968 1972 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
1969 1973 arevs = list(arevs)
1970 1974 brevs = list(brevs)
1971 1975 if arevs == brevs:
1972 1976 return 0
1973 1977 ui.write(('--- analyzed\n'), label='diff.file_a')
1974 1978 ui.write(('+++ optimized\n'), label='diff.file_b')
1975 1979 sm = difflib.SequenceMatcher(None, arevs, brevs)
1976 1980 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1977 1981 if tag in ('delete', 'replace'):
1978 1982 for c in arevs[alo:ahi]:
1979 1983 ui.write('-%s\n' % c, label='diff.deleted')
1980 1984 if tag in ('insert', 'replace'):
1981 1985 for c in brevs[blo:bhi]:
1982 1986 ui.write('+%s\n' % c, label='diff.inserted')
1983 1987 if tag == 'equal':
1984 1988 for c in arevs[alo:ahi]:
1985 1989 ui.write(' %s\n' % c)
1986 1990 return 1
1987 1991
1988 1992 func = revset.makematcher(tree)
1989 1993 revs = func(repo)
1990 1994 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
1991 1995 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
1996 if not opts['show_revs']:
1997 return
1992 1998 for c in revs:
1993 1999 ui.write("%s\n" % c)
1994 2000
1995 2001 @command('debugsetparents', [], _('REV1 [REV2]'))
1996 2002 def debugsetparents(ui, repo, rev1, rev2=None):
1997 2003 """manually set the parents of the current working directory
1998 2004
1999 2005 This is useful for writing repository conversion tools, but should
2000 2006 be used with care. For example, neither the working directory nor the
2001 2007 dirstate is updated, so file status may be incorrect after running this
2002 2008 command.
2003 2009
2004 2010 Returns 0 on success.
2005 2011 """
2006 2012
2007 2013 r1 = scmutil.revsingle(repo, rev1).node()
2008 2014 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2009 2015
2010 2016 with repo.wlock():
2011 2017 repo.setparents(r1, r2)
2012 2018
2013 2019 @command('debugsub',
2014 2020 [('r', 'rev', '',
2015 2021 _('revision to check'), _('REV'))],
2016 2022 _('[-r REV] [REV]'))
2017 2023 def debugsub(ui, repo, rev=None):
2018 2024 ctx = scmutil.revsingle(repo, rev, None)
2019 2025 for k, v in sorted(ctx.substate.items()):
2020 2026 ui.write(('path %s\n') % k)
2021 2027 ui.write((' source %s\n') % v[0])
2022 2028 ui.write((' revision %s\n') % v[1])
2023 2029
2024 2030 @command('debugsuccessorssets',
2025 2031 [],
2026 2032 _('[REV]'))
2027 2033 def debugsuccessorssets(ui, repo, *revs):
2028 2034 """show set of successors for revision
2029 2035
2030 2036 A successors set of changeset A is a consistent group of revisions that
2031 2037 succeed A. It contains non-obsolete changesets only.
2032 2038
2033 2039 In most cases a changeset A has a single successors set containing a single
2034 2040 successor (changeset A replaced by A').
2035 2041
2036 2042 A changeset that is made obsolete with no successors are called "pruned".
2037 2043 Such changesets have no successors sets at all.
2038 2044
2039 2045 A changeset that has been "split" will have a successors set containing
2040 2046 more than one successor.
2041 2047
2042 2048 A changeset that has been rewritten in multiple different ways is called
2043 2049 "divergent". Such changesets have multiple successor sets (each of which
2044 2050 may also be split, i.e. have multiple successors).
2045 2051
2046 2052 Results are displayed as follows::
2047 2053
2048 2054 <rev1>
2049 2055 <successors-1A>
2050 2056 <rev2>
2051 2057 <successors-2A>
2052 2058 <successors-2B1> <successors-2B2> <successors-2B3>
2053 2059
2054 2060 Here rev2 has two possible (i.e. divergent) successors sets. The first
2055 2061 holds one element, whereas the second holds three (i.e. the changeset has
2056 2062 been split).
2057 2063 """
2058 2064 # passed to successorssets caching computation from one call to another
2059 2065 cache = {}
2060 2066 ctx2str = str
2061 2067 node2str = short
2062 2068 if ui.debug():
2063 2069 def ctx2str(ctx):
2064 2070 return ctx.hex()
2065 2071 node2str = hex
2066 2072 for rev in scmutil.revrange(repo, revs):
2067 2073 ctx = repo[rev]
2068 2074 ui.write('%s\n'% ctx2str(ctx))
2069 2075 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2070 2076 if succsset:
2071 2077 ui.write(' ')
2072 2078 ui.write(node2str(succsset[0]))
2073 2079 for node in succsset[1:]:
2074 2080 ui.write(' ')
2075 2081 ui.write(node2str(node))
2076 2082 ui.write('\n')
2077 2083
2078 2084 @command('debugtemplate',
2079 2085 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2080 2086 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2081 2087 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2082 2088 optionalrepo=True)
2083 2089 def debugtemplate(ui, repo, tmpl, **opts):
2084 2090 """parse and apply a template
2085 2091
2086 2092 If -r/--rev is given, the template is processed as a log template and
2087 2093 applied to the given changesets. Otherwise, it is processed as a generic
2088 2094 template.
2089 2095
2090 2096 Use --verbose to print the parsed tree.
2091 2097 """
2092 2098 revs = None
2093 2099 if opts['rev']:
2094 2100 if repo is None:
2095 2101 raise error.RepoError(_('there is no Mercurial repository here '
2096 2102 '(.hg not found)'))
2097 2103 revs = scmutil.revrange(repo, opts['rev'])
2098 2104
2099 2105 props = {}
2100 2106 for d in opts['define']:
2101 2107 try:
2102 2108 k, v = (e.strip() for e in d.split('=', 1))
2103 2109 if not k or k == 'ui':
2104 2110 raise ValueError
2105 2111 props[k] = v
2106 2112 except ValueError:
2107 2113 raise error.Abort(_('malformed keyword definition: %s') % d)
2108 2114
2109 2115 if ui.verbose:
2110 2116 aliases = ui.configitems('templatealias')
2111 2117 tree = templater.parse(tmpl)
2112 2118 ui.note(templater.prettyformat(tree), '\n')
2113 2119 newtree = templater.expandaliases(tree, aliases)
2114 2120 if newtree != tree:
2115 2121 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2116 2122
2117 2123 mapfile = None
2118 2124 if revs is None:
2119 2125 k = 'debugtemplate'
2120 2126 t = formatter.maketemplater(ui, k, tmpl)
2121 2127 ui.write(templater.stringify(t(k, ui=ui, **props)))
2122 2128 else:
2123 2129 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
2124 2130 mapfile, buffered=False)
2125 2131 for r in revs:
2126 2132 displayer.show(repo[r], **props)
2127 2133 displayer.close()
2128 2134
2129 2135 @command('debugupdatecaches', [])
2130 2136 def debugupdatecaches(ui, repo, *pats, **opts):
2131 2137 """warm all known caches in the repository"""
2132 2138 with repo.wlock():
2133 2139 with repo.lock():
2134 2140 repo.updatecaches()
2135 2141
2136 2142 @command('debugupgraderepo', [
2137 2143 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2138 2144 ('', 'run', False, _('performs an upgrade')),
2139 2145 ])
2140 2146 def debugupgraderepo(ui, repo, run=False, optimize=None):
2141 2147 """upgrade a repository to use different features
2142 2148
2143 2149 If no arguments are specified, the repository is evaluated for upgrade
2144 2150 and a list of problems and potential optimizations is printed.
2145 2151
2146 2152 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2147 2153 can be influenced via additional arguments. More details will be provided
2148 2154 by the command output when run without ``--run``.
2149 2155
2150 2156 During the upgrade, the repository will be locked and no writes will be
2151 2157 allowed.
2152 2158
2153 2159 At the end of the upgrade, the repository may not be readable while new
2154 2160 repository data is swapped in. This window will be as long as it takes to
2155 2161 rename some directories inside the ``.hg`` directory. On most machines, this
2156 2162 should complete almost instantaneously and the chances of a consumer being
2157 2163 unable to access the repository should be low.
2158 2164 """
2159 2165 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2160 2166
2161 2167 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2162 2168 inferrepo=True)
2163 2169 def debugwalk(ui, repo, *pats, **opts):
2164 2170 """show how files match on given patterns"""
2165 2171 m = scmutil.match(repo[None], pats, opts)
2166 2172 ui.write(('matcher: %r\n' % m))
2167 2173 items = list(repo[None].walk(m))
2168 2174 if not items:
2169 2175 return
2170 2176 f = lambda fn: fn
2171 2177 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2172 2178 f = lambda fn: util.normpath(fn)
2173 2179 fmt = 'f %%-%ds %%-%ds %%s' % (
2174 2180 max([len(abs) for abs in items]),
2175 2181 max([len(m.rel(abs)) for abs in items]))
2176 2182 for abs in items:
2177 2183 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2178 2184 ui.write("%s\n" % line.rstrip())
2179 2185
2180 2186 @command('debugwireargs',
2181 2187 [('', 'three', '', 'three'),
2182 2188 ('', 'four', '', 'four'),
2183 2189 ('', 'five', '', 'five'),
2184 2190 ] + cmdutil.remoteopts,
2185 2191 _('REPO [OPTIONS]... [ONE [TWO]]'),
2186 2192 norepo=True)
2187 2193 def debugwireargs(ui, repopath, *vals, **opts):
2188 2194 repo = hg.peer(ui, opts, repopath)
2189 2195 for opt in cmdutil.remoteopts:
2190 2196 del opts[opt[1]]
2191 2197 args = {}
2192 2198 for k, v in opts.iteritems():
2193 2199 if v:
2194 2200 args[k] = v
2195 2201 # run twice to check that we don't mess up the stream for the next command
2196 2202 res1 = repo.debugwireargs(*vals, **args)
2197 2203 res2 = repo.debugwireargs(*vals, **args)
2198 2204 ui.write("%s\n" % res1)
2199 2205 if res1 != res2:
2200 2206 ui.warn("%s\n" % res2)
@@ -1,381 +1,381 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcheckstate
76 76 debugcolor
77 77 debugcommands
78 78 debugcomplete
79 79 debugconfig
80 80 debugcreatestreamclonebundle
81 81 debugdag
82 82 debugdata
83 83 debugdate
84 84 debugdeltachain
85 85 debugdirstate
86 86 debugdiscovery
87 87 debugextensions
88 88 debugfileset
89 89 debugfsinfo
90 90 debuggetbundle
91 91 debugignore
92 92 debugindex
93 93 debugindexdot
94 94 debuginstall
95 95 debugknown
96 96 debuglabelcomplete
97 97 debuglocks
98 98 debugmergestate
99 99 debugnamecomplete
100 100 debugobsolete
101 101 debugpathcomplete
102 102 debugpickmergetool
103 103 debugpushkey
104 104 debugpvec
105 105 debugrebuilddirstate
106 106 debugrebuildfncache
107 107 debugrename
108 108 debugrevlog
109 109 debugrevspec
110 110 debugsetparents
111 111 debugsub
112 112 debugsuccessorssets
113 113 debugtemplate
114 114 debugupdatecaches
115 115 debugupgraderepo
116 116 debugwalk
117 117 debugwireargs
118 118
119 119 Do not show the alias of a debug command if there are other candidates
120 120 (this should hide rawcommit)
121 121 $ hg debugcomplete r
122 122 recover
123 123 remove
124 124 rename
125 125 resolve
126 126 revert
127 127 rollback
128 128 root
129 129 Show the alias of a debug command if there are no other candidates
130 130 $ hg debugcomplete rawc
131 131
132 132
133 133 Show the global options
134 134 $ hg debugcomplete --options | sort
135 135 --color
136 136 --config
137 137 --cwd
138 138 --debug
139 139 --debugger
140 140 --encoding
141 141 --encodingmode
142 142 --help
143 143 --hidden
144 144 --noninteractive
145 145 --pager
146 146 --profile
147 147 --quiet
148 148 --repository
149 149 --time
150 150 --traceback
151 151 --verbose
152 152 --version
153 153 -R
154 154 -h
155 155 -q
156 156 -v
157 157 -y
158 158
159 159 Show the options for the "serve" command
160 160 $ hg debugcomplete --options serve | sort
161 161 --accesslog
162 162 --address
163 163 --certificate
164 164 --cmdserver
165 165 --color
166 166 --config
167 167 --cwd
168 168 --daemon
169 169 --daemon-postexec
170 170 --debug
171 171 --debugger
172 172 --encoding
173 173 --encodingmode
174 174 --errorlog
175 175 --help
176 176 --hidden
177 177 --ipv6
178 178 --name
179 179 --noninteractive
180 180 --pager
181 181 --pid-file
182 182 --port
183 183 --prefix
184 184 --profile
185 185 --quiet
186 186 --repository
187 187 --stdio
188 188 --style
189 189 --subrepos
190 190 --templates
191 191 --time
192 192 --traceback
193 193 --verbose
194 194 --version
195 195 --web-conf
196 196 -6
197 197 -A
198 198 -E
199 199 -R
200 200 -S
201 201 -a
202 202 -d
203 203 -h
204 204 -n
205 205 -p
206 206 -q
207 207 -t
208 208 -v
209 209 -y
210 210
211 211 Show an error if we use --options with an ambiguous abbreviation
212 212 $ hg debugcomplete --options s
213 213 hg: command 's' is ambiguous:
214 214 serve showconfig status summary
215 215 [255]
216 216
217 217 Show all commands + options
218 218 $ hg debugcommands
219 219 add: include, exclude, subrepos, dry-run
220 220 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
221 221 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
222 222 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
223 223 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
224 224 export: output, switch-parent, rev, text, git, binary, nodates
225 225 forget: include, exclude
226 226 init: ssh, remotecmd, insecure
227 227 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
228 228 merge: force, rev, preview, tool
229 229 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
230 230 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
231 231 remove: after, force, subrepos, include, exclude
232 232 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, subrepos
233 233 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
234 234 summary: remote
235 235 update: clean, check, merge, date, rev, tool
236 236 addremove: similarity, subrepos, include, exclude, dry-run
237 237 archive: no-decode, prefix, rev, type, subrepos, include, exclude
238 238 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
239 239 bisect: reset, good, bad, skip, extend, command, noupdate
240 240 bookmarks: force, rev, delete, rename, inactive, template
241 241 branch: force, clean
242 242 branches: active, closed, template
243 243 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
244 244 cat: output, rev, decode, include, exclude, template
245 245 config: untrusted, edit, local, global, template
246 246 copy: after, force, include, exclude, dry-run
247 247 debugancestor:
248 248 debugapplystreamclonebundle:
249 249 debugbuilddag: mergeable-file, overwritten-file, new-file
250 250 debugbundle: all, part-type, spec
251 251 debugcheckstate:
252 252 debugcolor: style
253 253 debugcommands:
254 254 debugcomplete: options
255 255 debugcreatestreamclonebundle:
256 256 debugdag: tags, branches, dots, spaces
257 257 debugdata: changelog, manifest, dir
258 258 debugdate: extended
259 259 debugdeltachain: changelog, manifest, dir, template
260 260 debugdirstate: nodates, datesort
261 261 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
262 262 debugextensions: template
263 263 debugfileset: rev
264 264 debugfsinfo:
265 265 debuggetbundle: head, common, type
266 266 debugignore:
267 267 debugindex: changelog, manifest, dir, format
268 268 debugindexdot: changelog, manifest, dir
269 269 debuginstall: template
270 270 debugknown:
271 271 debuglabelcomplete:
272 272 debuglocks: force-lock, force-wlock
273 273 debugmergestate:
274 274 debugnamecomplete:
275 275 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
276 276 debugpathcomplete: full, normal, added, removed
277 277 debugpickmergetool: rev, changedelete, include, exclude, tool
278 278 debugpushkey:
279 279 debugpvec:
280 280 debugrebuilddirstate: rev, minimal
281 281 debugrebuildfncache:
282 282 debugrename: rev
283 283 debugrevlog: changelog, manifest, dir, dump
284 debugrevspec: optimize, show-set, show-stage, no-optimized, verify-optimized
284 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
285 285 debugsetparents:
286 286 debugsub: rev
287 287 debugsuccessorssets:
288 288 debugtemplate: rev, define
289 289 debugupdatecaches:
290 290 debugupgraderepo: optimize, run
291 291 debugwalk: include, exclude
292 292 debugwireargs: three, four, five, ssh, remotecmd, insecure
293 293 files: rev, print0, include, exclude, template, subrepos
294 294 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
295 295 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, template, include, exclude
296 296 heads: rev, topo, active, closed, style, template
297 297 help: extension, command, keyword, system
298 298 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
299 299 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
300 300 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
301 301 locate: rev, print0, fullpath, include, exclude
302 302 manifest: rev, all, template
303 303 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
304 304 parents: rev, style, template
305 305 paths: template
306 306 phase: public, draft, secret, force, rev
307 307 recover:
308 308 rename: after, force, include, exclude, dry-run
309 309 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
310 310 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
311 311 rollback: dry-run, force
312 312 root:
313 313 tag: force, local, rev, remove, edit, message, date, user
314 314 tags: template
315 315 tip: patch, git, style, template
316 316 unbundle: update
317 317 verify:
318 318 version: template
319 319
320 320 $ hg init a
321 321 $ cd a
322 322 $ echo fee > fee
323 323 $ hg ci -q -Amfee
324 324 $ hg tag fee
325 325 $ mkdir fie
326 326 $ echo dead > fie/dead
327 327 $ echo live > fie/live
328 328 $ hg bookmark fo
329 329 $ hg branch -q fie
330 330 $ hg ci -q -Amfie
331 331 $ echo fo > fo
332 332 $ hg branch -qf default
333 333 $ hg ci -q -Amfo
334 334 $ echo Fum > Fum
335 335 $ hg ci -q -AmFum
336 336 $ hg bookmark Fum
337 337
338 338 Test debugpathcomplete
339 339
340 340 $ hg debugpathcomplete f
341 341 fee
342 342 fie
343 343 fo
344 344 $ hg debugpathcomplete -f f
345 345 fee
346 346 fie/dead
347 347 fie/live
348 348 fo
349 349
350 350 $ hg rm Fum
351 351 $ hg debugpathcomplete -r F
352 352 Fum
353 353
354 354 Test debugnamecomplete
355 355
356 356 $ hg debugnamecomplete
357 357 Fum
358 358 default
359 359 fee
360 360 fie
361 361 fo
362 362 tip
363 363 $ hg debugnamecomplete f
364 364 fee
365 365 fie
366 366 fo
367 367
368 368 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
369 369 used for completions in some shells.
370 370
371 371 $ hg debuglabelcomplete
372 372 Fum
373 373 default
374 374 fee
375 375 fie
376 376 fo
377 377 tip
378 378 $ hg debuglabelcomplete f
379 379 fee
380 380 fie
381 381 fo
General Comments 0
You need to be logged in to leave comments. Login now