##// END OF EJS Templates
tags: add a debug command to display .hg/cache/hgtagsfnodes1...
Valentin Gatien-Baron -
r44772:d8b53385 default
parent child Browse files
Show More
@@ -1,4294 +1,4304 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 codecs
11 11 import collections
12 12 import difflib
13 13 import errno
14 14 import operator
15 15 import os
16 16 import platform
17 17 import random
18 18 import re
19 19 import socket
20 20 import ssl
21 21 import stat
22 22 import string
23 23 import subprocess
24 24 import sys
25 25 import time
26 26
27 27 from .i18n import _
28 28 from .node import (
29 29 bin,
30 30 hex,
31 31 nullhex,
32 32 nullid,
33 33 nullrev,
34 34 short,
35 35 )
36 36 from .pycompat import (
37 37 getattr,
38 38 open,
39 39 )
40 40 from . import (
41 41 bundle2,
42 42 changegroup,
43 43 cmdutil,
44 44 color,
45 45 context,
46 46 copies,
47 47 dagparser,
48 48 encoding,
49 49 error,
50 50 exchange,
51 51 extensions,
52 52 filemerge,
53 53 filesetlang,
54 54 formatter,
55 55 hg,
56 56 httppeer,
57 57 localrepo,
58 58 lock as lockmod,
59 59 logcmdutil,
60 60 merge as mergemod,
61 61 obsolete,
62 62 obsutil,
63 63 pathutil,
64 64 phases,
65 65 policy,
66 66 pvec,
67 67 pycompat,
68 68 registrar,
69 69 repair,
70 70 revlog,
71 71 revset,
72 72 revsetlang,
73 73 scmutil,
74 74 setdiscovery,
75 75 simplemerge,
76 76 sshpeer,
77 77 sslutil,
78 78 streamclone,
79 tags as tagsmod,
79 80 templater,
80 81 treediscovery,
81 82 upgrade,
82 83 url as urlmod,
83 84 util,
84 85 vfs as vfsmod,
85 86 wireprotoframing,
86 87 wireprotoserver,
87 88 wireprotov2peer,
88 89 )
89 90 from .utils import (
90 91 cborutil,
91 92 compression,
92 93 dateutil,
93 94 procutil,
94 95 stringutil,
95 96 )
96 97
97 98 from .revlogutils import deltas as deltautil
98 99
99 100 release = lockmod.release
100 101
101 102 command = registrar.command()
102 103
103 104
104 105 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
105 106 def debugancestor(ui, repo, *args):
106 107 """find the ancestor revision of two revisions in a given index"""
107 108 if len(args) == 3:
108 109 index, rev1, rev2 = args
109 110 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
110 111 lookup = r.lookup
111 112 elif len(args) == 2:
112 113 if not repo:
113 114 raise error.Abort(
114 115 _(b'there is no Mercurial repository here (.hg not found)')
115 116 )
116 117 rev1, rev2 = args
117 118 r = repo.changelog
118 119 lookup = repo.lookup
119 120 else:
120 121 raise error.Abort(_(b'either two or three arguments required'))
121 122 a = r.ancestor(lookup(rev1), lookup(rev2))
122 123 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
123 124
124 125
125 126 @command(b'debugapplystreamclonebundle', [], b'FILE')
126 127 def debugapplystreamclonebundle(ui, repo, fname):
127 128 """apply a stream clone bundle file"""
128 129 f = hg.openpath(ui, fname)
129 130 gen = exchange.readbundle(ui, f, fname)
130 131 gen.apply(repo)
131 132
132 133
133 134 @command(
134 135 b'debugbuilddag',
135 136 [
136 137 (
137 138 b'm',
138 139 b'mergeable-file',
139 140 None,
140 141 _(b'add single file mergeable changes'),
141 142 ),
142 143 (
143 144 b'o',
144 145 b'overwritten-file',
145 146 None,
146 147 _(b'add single file all revs overwrite'),
147 148 ),
148 149 (b'n', b'new-file', None, _(b'add new file at each rev')),
149 150 ],
150 151 _(b'[OPTION]... [TEXT]'),
151 152 )
152 153 def debugbuilddag(
153 154 ui,
154 155 repo,
155 156 text=None,
156 157 mergeable_file=False,
157 158 overwritten_file=False,
158 159 new_file=False,
159 160 ):
160 161 """builds a repo with a given DAG from scratch in the current empty repo
161 162
162 163 The description of the DAG is read from stdin if not given on the
163 164 command line.
164 165
165 166 Elements:
166 167
167 168 - "+n" is a linear run of n nodes based on the current default parent
168 169 - "." is a single node based on the current default parent
169 170 - "$" resets the default parent to null (implied at the start);
170 171 otherwise the default parent is always the last node created
171 172 - "<p" sets the default parent to the backref p
172 173 - "*p" is a fork at parent p, which is a backref
173 174 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
174 175 - "/p2" is a merge of the preceding node and p2
175 176 - ":tag" defines a local tag for the preceding node
176 177 - "@branch" sets the named branch for subsequent nodes
177 178 - "#...\\n" is a comment up to the end of the line
178 179
179 180 Whitespace between the above elements is ignored.
180 181
181 182 A backref is either
182 183
183 184 - a number n, which references the node curr-n, where curr is the current
184 185 node, or
185 186 - the name of a local tag you placed earlier using ":tag", or
186 187 - empty to denote the default parent.
187 188
188 189 All string valued-elements are either strictly alphanumeric, or must
189 190 be enclosed in double quotes ("..."), with "\\" as escape character.
190 191 """
191 192
192 193 if text is None:
193 194 ui.status(_(b"reading DAG from stdin\n"))
194 195 text = ui.fin.read()
195 196
196 197 cl = repo.changelog
197 198 if len(cl) > 0:
198 199 raise error.Abort(_(b'repository is not empty'))
199 200
200 201 # determine number of revs in DAG
201 202 total = 0
202 203 for type, data in dagparser.parsedag(text):
203 204 if type == b'n':
204 205 total += 1
205 206
206 207 if mergeable_file:
207 208 linesperrev = 2
208 209 # make a file with k lines per rev
209 210 initialmergedlines = [
210 211 b'%d' % i for i in pycompat.xrange(0, total * linesperrev)
211 212 ]
212 213 initialmergedlines.append(b"")
213 214
214 215 tags = []
215 216 progress = ui.makeprogress(
216 217 _(b'building'), unit=_(b'revisions'), total=total
217 218 )
218 219 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
219 220 at = -1
220 221 atbranch = b'default'
221 222 nodeids = []
222 223 id = 0
223 224 progress.update(id)
224 225 for type, data in dagparser.parsedag(text):
225 226 if type == b'n':
226 227 ui.note((b'node %s\n' % pycompat.bytestr(data)))
227 228 id, ps = data
228 229
229 230 files = []
230 231 filecontent = {}
231 232
232 233 p2 = None
233 234 if mergeable_file:
234 235 fn = b"mf"
235 236 p1 = repo[ps[0]]
236 237 if len(ps) > 1:
237 238 p2 = repo[ps[1]]
238 239 pa = p1.ancestor(p2)
239 240 base, local, other = [
240 241 x[fn].data() for x in (pa, p1, p2)
241 242 ]
242 243 m3 = simplemerge.Merge3Text(base, local, other)
243 244 ml = [l.strip() for l in m3.merge_lines()]
244 245 ml.append(b"")
245 246 elif at > 0:
246 247 ml = p1[fn].data().split(b"\n")
247 248 else:
248 249 ml = initialmergedlines
249 250 ml[id * linesperrev] += b" r%i" % id
250 251 mergedtext = b"\n".join(ml)
251 252 files.append(fn)
252 253 filecontent[fn] = mergedtext
253 254
254 255 if overwritten_file:
255 256 fn = b"of"
256 257 files.append(fn)
257 258 filecontent[fn] = b"r%i\n" % id
258 259
259 260 if new_file:
260 261 fn = b"nf%i" % id
261 262 files.append(fn)
262 263 filecontent[fn] = b"r%i\n" % id
263 264 if len(ps) > 1:
264 265 if not p2:
265 266 p2 = repo[ps[1]]
266 267 for fn in p2:
267 268 if fn.startswith(b"nf"):
268 269 files.append(fn)
269 270 filecontent[fn] = p2[fn].data()
270 271
271 272 def fctxfn(repo, cx, path):
272 273 if path in filecontent:
273 274 return context.memfilectx(
274 275 repo, cx, path, filecontent[path]
275 276 )
276 277 return None
277 278
278 279 if len(ps) == 0 or ps[0] < 0:
279 280 pars = [None, None]
280 281 elif len(ps) == 1:
281 282 pars = [nodeids[ps[0]], None]
282 283 else:
283 284 pars = [nodeids[p] for p in ps]
284 285 cx = context.memctx(
285 286 repo,
286 287 pars,
287 288 b"r%i" % id,
288 289 files,
289 290 fctxfn,
290 291 date=(id, 0),
291 292 user=b"debugbuilddag",
292 293 extra={b'branch': atbranch},
293 294 )
294 295 nodeid = repo.commitctx(cx)
295 296 nodeids.append(nodeid)
296 297 at = id
297 298 elif type == b'l':
298 299 id, name = data
299 300 ui.note((b'tag %s\n' % name))
300 301 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
301 302 elif type == b'a':
302 303 ui.note((b'branch %s\n' % data))
303 304 atbranch = data
304 305 progress.update(id)
305 306
306 307 if tags:
307 308 repo.vfs.write(b"localtags", b"".join(tags))
308 309
309 310
310 311 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
311 312 indent_string = b' ' * indent
312 313 if all:
313 314 ui.writenoi18n(
314 315 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
315 316 % indent_string
316 317 )
317 318
318 319 def showchunks(named):
319 320 ui.write(b"\n%s%s\n" % (indent_string, named))
320 321 for deltadata in gen.deltaiter():
321 322 node, p1, p2, cs, deltabase, delta, flags = deltadata
322 323 ui.write(
323 324 b"%s%s %s %s %s %s %d\n"
324 325 % (
325 326 indent_string,
326 327 hex(node),
327 328 hex(p1),
328 329 hex(p2),
329 330 hex(cs),
330 331 hex(deltabase),
331 332 len(delta),
332 333 )
333 334 )
334 335
335 336 gen.changelogheader()
336 337 showchunks(b"changelog")
337 338 gen.manifestheader()
338 339 showchunks(b"manifest")
339 340 for chunkdata in iter(gen.filelogheader, {}):
340 341 fname = chunkdata[b'filename']
341 342 showchunks(fname)
342 343 else:
343 344 if isinstance(gen, bundle2.unbundle20):
344 345 raise error.Abort(_(b'use debugbundle2 for this file'))
345 346 gen.changelogheader()
346 347 for deltadata in gen.deltaiter():
347 348 node, p1, p2, cs, deltabase, delta, flags = deltadata
348 349 ui.write(b"%s%s\n" % (indent_string, hex(node)))
349 350
350 351
351 352 def _debugobsmarkers(ui, part, indent=0, **opts):
352 353 """display version and markers contained in 'data'"""
353 354 opts = pycompat.byteskwargs(opts)
354 355 data = part.read()
355 356 indent_string = b' ' * indent
356 357 try:
357 358 version, markers = obsolete._readmarkers(data)
358 359 except error.UnknownVersion as exc:
359 360 msg = b"%sunsupported version: %s (%d bytes)\n"
360 361 msg %= indent_string, exc.version, len(data)
361 362 ui.write(msg)
362 363 else:
363 364 msg = b"%sversion: %d (%d bytes)\n"
364 365 msg %= indent_string, version, len(data)
365 366 ui.write(msg)
366 367 fm = ui.formatter(b'debugobsolete', opts)
367 368 for rawmarker in sorted(markers):
368 369 m = obsutil.marker(None, rawmarker)
369 370 fm.startitem()
370 371 fm.plain(indent_string)
371 372 cmdutil.showmarker(fm, m)
372 373 fm.end()
373 374
374 375
375 376 def _debugphaseheads(ui, data, indent=0):
376 377 """display version and markers contained in 'data'"""
377 378 indent_string = b' ' * indent
378 379 headsbyphase = phases.binarydecode(data)
379 380 for phase in phases.allphases:
380 381 for head in headsbyphase[phase]:
381 382 ui.write(indent_string)
382 383 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
383 384
384 385
385 386 def _quasirepr(thing):
386 387 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
387 388 return b'{%s}' % (
388 389 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
389 390 )
390 391 return pycompat.bytestr(repr(thing))
391 392
392 393
393 394 def _debugbundle2(ui, gen, all=None, **opts):
394 395 """lists the contents of a bundle2"""
395 396 if not isinstance(gen, bundle2.unbundle20):
396 397 raise error.Abort(_(b'not a bundle2 file'))
397 398 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
398 399 parttypes = opts.get('part_type', [])
399 400 for part in gen.iterparts():
400 401 if parttypes and part.type not in parttypes:
401 402 continue
402 403 msg = b'%s -- %s (mandatory: %r)\n'
403 404 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
404 405 if part.type == b'changegroup':
405 406 version = part.params.get(b'version', b'01')
406 407 cg = changegroup.getunbundler(version, part, b'UN')
407 408 if not ui.quiet:
408 409 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
409 410 if part.type == b'obsmarkers':
410 411 if not ui.quiet:
411 412 _debugobsmarkers(ui, part, indent=4, **opts)
412 413 if part.type == b'phase-heads':
413 414 if not ui.quiet:
414 415 _debugphaseheads(ui, part, indent=4)
415 416
416 417
417 418 @command(
418 419 b'debugbundle',
419 420 [
420 421 (b'a', b'all', None, _(b'show all details')),
421 422 (b'', b'part-type', [], _(b'show only the named part type')),
422 423 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
423 424 ],
424 425 _(b'FILE'),
425 426 norepo=True,
426 427 )
427 428 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
428 429 """lists the contents of a bundle"""
429 430 with hg.openpath(ui, bundlepath) as f:
430 431 if spec:
431 432 spec = exchange.getbundlespec(ui, f)
432 433 ui.write(b'%s\n' % spec)
433 434 return
434 435
435 436 gen = exchange.readbundle(ui, f, bundlepath)
436 437 if isinstance(gen, bundle2.unbundle20):
437 438 return _debugbundle2(ui, gen, all=all, **opts)
438 439 _debugchangegroup(ui, gen, all=all, **opts)
439 440
440 441
441 442 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
442 443 def debugcapabilities(ui, path, **opts):
443 444 """lists the capabilities of a remote peer"""
444 445 opts = pycompat.byteskwargs(opts)
445 446 peer = hg.peer(ui, opts, path)
446 447 caps = peer.capabilities()
447 448 ui.writenoi18n(b'Main capabilities:\n')
448 449 for c in sorted(caps):
449 450 ui.write(b' %s\n' % c)
450 451 b2caps = bundle2.bundle2caps(peer)
451 452 if b2caps:
452 453 ui.writenoi18n(b'Bundle2 capabilities:\n')
453 454 for key, values in sorted(pycompat.iteritems(b2caps)):
454 455 ui.write(b' %s\n' % key)
455 456 for v in values:
456 457 ui.write(b' %s\n' % v)
457 458
458 459
459 460 @command(b'debugcheckstate', [], b'')
460 461 def debugcheckstate(ui, repo):
461 462 """validate the correctness of the current dirstate"""
462 463 parent1, parent2 = repo.dirstate.parents()
463 464 m1 = repo[parent1].manifest()
464 465 m2 = repo[parent2].manifest()
465 466 errors = 0
466 467 for f in repo.dirstate:
467 468 state = repo.dirstate[f]
468 469 if state in b"nr" and f not in m1:
469 470 ui.warn(_(b"%s in state %s, but not in manifest1\n") % (f, state))
470 471 errors += 1
471 472 if state in b"a" and f in m1:
472 473 ui.warn(_(b"%s in state %s, but also in manifest1\n") % (f, state))
473 474 errors += 1
474 475 if state in b"m" and f not in m1 and f not in m2:
475 476 ui.warn(
476 477 _(b"%s in state %s, but not in either manifest\n") % (f, state)
477 478 )
478 479 errors += 1
479 480 for f in m1:
480 481 state = repo.dirstate[f]
481 482 if state not in b"nrm":
482 483 ui.warn(_(b"%s in manifest1, but listed as state %s") % (f, state))
483 484 errors += 1
484 485 if errors:
485 486 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
486 487 raise error.Abort(errstr)
487 488
488 489
489 490 @command(
490 491 b'debugcolor',
491 492 [(b'', b'style', None, _(b'show all configured styles'))],
492 493 b'hg debugcolor',
493 494 )
494 495 def debugcolor(ui, repo, **opts):
495 496 """show available color, effects or style"""
496 497 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
497 498 if opts.get('style'):
498 499 return _debugdisplaystyle(ui)
499 500 else:
500 501 return _debugdisplaycolor(ui)
501 502
502 503
503 504 def _debugdisplaycolor(ui):
504 505 ui = ui.copy()
505 506 ui._styles.clear()
506 507 for effect in color._activeeffects(ui).keys():
507 508 ui._styles[effect] = effect
508 509 if ui._terminfoparams:
509 510 for k, v in ui.configitems(b'color'):
510 511 if k.startswith(b'color.'):
511 512 ui._styles[k] = k[6:]
512 513 elif k.startswith(b'terminfo.'):
513 514 ui._styles[k] = k[9:]
514 515 ui.write(_(b'available colors:\n'))
515 516 # sort label with a '_' after the other to group '_background' entry.
516 517 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
517 518 for colorname, label in items:
518 519 ui.write(b'%s\n' % colorname, label=label)
519 520
520 521
521 522 def _debugdisplaystyle(ui):
522 523 ui.write(_(b'available style:\n'))
523 524 if not ui._styles:
524 525 return
525 526 width = max(len(s) for s in ui._styles)
526 527 for label, effects in sorted(ui._styles.items()):
527 528 ui.write(b'%s' % label, label=label)
528 529 if effects:
529 530 # 50
530 531 ui.write(b': ')
531 532 ui.write(b' ' * (max(0, width - len(label))))
532 533 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
533 534 ui.write(b'\n')
534 535
535 536
536 537 @command(b'debugcreatestreamclonebundle', [], b'FILE')
537 538 def debugcreatestreamclonebundle(ui, repo, fname):
538 539 """create a stream clone bundle file
539 540
540 541 Stream bundles are special bundles that are essentially archives of
541 542 revlog files. They are commonly used for cloning very quickly.
542 543 """
543 544 # TODO we may want to turn this into an abort when this functionality
544 545 # is moved into `hg bundle`.
545 546 if phases.hassecret(repo):
546 547 ui.warn(
547 548 _(
548 549 b'(warning: stream clone bundle will contain secret '
549 550 b'revisions)\n'
550 551 )
551 552 )
552 553
553 554 requirements, gen = streamclone.generatebundlev1(repo)
554 555 changegroup.writechunks(ui, gen, fname)
555 556
556 557 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
557 558
558 559
559 560 @command(
560 561 b'debugdag',
561 562 [
562 563 (b't', b'tags', None, _(b'use tags as labels')),
563 564 (b'b', b'branches', None, _(b'annotate with branch names')),
564 565 (b'', b'dots', None, _(b'use dots for runs')),
565 566 (b's', b'spaces', None, _(b'separate elements by spaces')),
566 567 ],
567 568 _(b'[OPTION]... [FILE [REV]...]'),
568 569 optionalrepo=True,
569 570 )
570 571 def debugdag(ui, repo, file_=None, *revs, **opts):
571 572 """format the changelog or an index DAG as a concise textual description
572 573
573 574 If you pass a revlog index, the revlog's DAG is emitted. If you list
574 575 revision numbers, they get labeled in the output as rN.
575 576
576 577 Otherwise, the changelog DAG of the current repo is emitted.
577 578 """
578 579 spaces = opts.get('spaces')
579 580 dots = opts.get('dots')
580 581 if file_:
581 582 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
582 583 revs = set((int(r) for r in revs))
583 584
584 585 def events():
585 586 for r in rlog:
586 587 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
587 588 if r in revs:
588 589 yield b'l', (r, b"r%i" % r)
589 590
590 591 elif repo:
591 592 cl = repo.changelog
592 593 tags = opts.get('tags')
593 594 branches = opts.get('branches')
594 595 if tags:
595 596 labels = {}
596 597 for l, n in repo.tags().items():
597 598 labels.setdefault(cl.rev(n), []).append(l)
598 599
599 600 def events():
600 601 b = b"default"
601 602 for r in cl:
602 603 if branches:
603 604 newb = cl.read(cl.node(r))[5][b'branch']
604 605 if newb != b:
605 606 yield b'a', newb
606 607 b = newb
607 608 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
608 609 if tags:
609 610 ls = labels.get(r)
610 611 if ls:
611 612 for l in ls:
612 613 yield b'l', (r, l)
613 614
614 615 else:
615 616 raise error.Abort(_(b'need repo for changelog dag'))
616 617
617 618 for line in dagparser.dagtextlines(
618 619 events(),
619 620 addspaces=spaces,
620 621 wraplabels=True,
621 622 wrapannotations=True,
622 623 wrapnonlinear=dots,
623 624 usedots=dots,
624 625 maxlinewidth=70,
625 626 ):
626 627 ui.write(line)
627 628 ui.write(b"\n")
628 629
629 630
630 631 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
631 632 def debugdata(ui, repo, file_, rev=None, **opts):
632 633 """dump the contents of a data file revision"""
633 634 opts = pycompat.byteskwargs(opts)
634 635 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
635 636 if rev is not None:
636 637 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
637 638 file_, rev = None, file_
638 639 elif rev is None:
639 640 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
640 641 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
641 642 try:
642 643 ui.write(r.rawdata(r.lookup(rev)))
643 644 except KeyError:
644 645 raise error.Abort(_(b'invalid revision identifier %s') % rev)
645 646
646 647
647 648 @command(
648 649 b'debugdate',
649 650 [(b'e', b'extended', None, _(b'try extended date formats'))],
650 651 _(b'[-e] DATE [RANGE]'),
651 652 norepo=True,
652 653 optionalrepo=True,
653 654 )
654 655 def debugdate(ui, date, range=None, **opts):
655 656 """parse and display a date"""
656 657 if opts["extended"]:
657 658 d = dateutil.parsedate(date, dateutil.extendeddateformats)
658 659 else:
659 660 d = dateutil.parsedate(date)
660 661 ui.writenoi18n(b"internal: %d %d\n" % d)
661 662 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
662 663 if range:
663 664 m = dateutil.matchdate(range)
664 665 ui.writenoi18n(b"match: %s\n" % m(d[0]))
665 666
666 667
667 668 @command(
668 669 b'debugdeltachain',
669 670 cmdutil.debugrevlogopts + cmdutil.formatteropts,
670 671 _(b'-c|-m|FILE'),
671 672 optionalrepo=True,
672 673 )
673 674 def debugdeltachain(ui, repo, file_=None, **opts):
674 675 """dump information about delta chains in a revlog
675 676
676 677 Output can be templatized. Available template keywords are:
677 678
678 679 :``rev``: revision number
679 680 :``chainid``: delta chain identifier (numbered by unique base)
680 681 :``chainlen``: delta chain length to this revision
681 682 :``prevrev``: previous revision in delta chain
682 683 :``deltatype``: role of delta / how it was computed
683 684 :``compsize``: compressed size of revision
684 685 :``uncompsize``: uncompressed size of revision
685 686 :``chainsize``: total size of compressed revisions in chain
686 687 :``chainratio``: total chain size divided by uncompressed revision size
687 688 (new delta chains typically start at ratio 2.00)
688 689 :``lindist``: linear distance from base revision in delta chain to end
689 690 of this revision
690 691 :``extradist``: total size of revisions not part of this delta chain from
691 692 base of delta chain to end of this revision; a measurement
692 693 of how much extra data we need to read/seek across to read
693 694 the delta chain for this revision
694 695 :``extraratio``: extradist divided by chainsize; another representation of
695 696 how much unrelated data is needed to load this delta chain
696 697
697 698 If the repository is configured to use the sparse read, additional keywords
698 699 are available:
699 700
700 701 :``readsize``: total size of data read from the disk for a revision
701 702 (sum of the sizes of all the blocks)
702 703 :``largestblock``: size of the largest block of data read from the disk
703 704 :``readdensity``: density of useful bytes in the data read from the disk
704 705 :``srchunks``: in how many data hunks the whole revision would be read
705 706
706 707 The sparse read can be enabled with experimental.sparse-read = True
707 708 """
708 709 opts = pycompat.byteskwargs(opts)
709 710 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
710 711 index = r.index
711 712 start = r.start
712 713 length = r.length
713 714 generaldelta = r.version & revlog.FLAG_GENERALDELTA
714 715 withsparseread = getattr(r, '_withsparseread', False)
715 716
716 717 def revinfo(rev):
717 718 e = index[rev]
718 719 compsize = e[1]
719 720 uncompsize = e[2]
720 721 chainsize = 0
721 722
722 723 if generaldelta:
723 724 if e[3] == e[5]:
724 725 deltatype = b'p1'
725 726 elif e[3] == e[6]:
726 727 deltatype = b'p2'
727 728 elif e[3] == rev - 1:
728 729 deltatype = b'prev'
729 730 elif e[3] == rev:
730 731 deltatype = b'base'
731 732 else:
732 733 deltatype = b'other'
733 734 else:
734 735 if e[3] == rev:
735 736 deltatype = b'base'
736 737 else:
737 738 deltatype = b'prev'
738 739
739 740 chain = r._deltachain(rev)[0]
740 741 for iterrev in chain:
741 742 e = index[iterrev]
742 743 chainsize += e[1]
743 744
744 745 return compsize, uncompsize, deltatype, chain, chainsize
745 746
746 747 fm = ui.formatter(b'debugdeltachain', opts)
747 748
748 749 fm.plain(
749 750 b' rev chain# chainlen prev delta '
750 751 b'size rawsize chainsize ratio lindist extradist '
751 752 b'extraratio'
752 753 )
753 754 if withsparseread:
754 755 fm.plain(b' readsize largestblk rddensity srchunks')
755 756 fm.plain(b'\n')
756 757
757 758 chainbases = {}
758 759 for rev in r:
759 760 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
760 761 chainbase = chain[0]
761 762 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
762 763 basestart = start(chainbase)
763 764 revstart = start(rev)
764 765 lineardist = revstart + comp - basestart
765 766 extradist = lineardist - chainsize
766 767 try:
767 768 prevrev = chain[-2]
768 769 except IndexError:
769 770 prevrev = -1
770 771
771 772 if uncomp != 0:
772 773 chainratio = float(chainsize) / float(uncomp)
773 774 else:
774 775 chainratio = chainsize
775 776
776 777 if chainsize != 0:
777 778 extraratio = float(extradist) / float(chainsize)
778 779 else:
779 780 extraratio = extradist
780 781
781 782 fm.startitem()
782 783 fm.write(
783 784 b'rev chainid chainlen prevrev deltatype compsize '
784 785 b'uncompsize chainsize chainratio lindist extradist '
785 786 b'extraratio',
786 787 b'%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
787 788 rev,
788 789 chainid,
789 790 len(chain),
790 791 prevrev,
791 792 deltatype,
792 793 comp,
793 794 uncomp,
794 795 chainsize,
795 796 chainratio,
796 797 lineardist,
797 798 extradist,
798 799 extraratio,
799 800 rev=rev,
800 801 chainid=chainid,
801 802 chainlen=len(chain),
802 803 prevrev=prevrev,
803 804 deltatype=deltatype,
804 805 compsize=comp,
805 806 uncompsize=uncomp,
806 807 chainsize=chainsize,
807 808 chainratio=chainratio,
808 809 lindist=lineardist,
809 810 extradist=extradist,
810 811 extraratio=extraratio,
811 812 )
812 813 if withsparseread:
813 814 readsize = 0
814 815 largestblock = 0
815 816 srchunks = 0
816 817
817 818 for revschunk in deltautil.slicechunk(r, chain):
818 819 srchunks += 1
819 820 blkend = start(revschunk[-1]) + length(revschunk[-1])
820 821 blksize = blkend - start(revschunk[0])
821 822
822 823 readsize += blksize
823 824 if largestblock < blksize:
824 825 largestblock = blksize
825 826
826 827 if readsize:
827 828 readdensity = float(chainsize) / float(readsize)
828 829 else:
829 830 readdensity = 1
830 831
831 832 fm.write(
832 833 b'readsize largestblock readdensity srchunks',
833 834 b' %10d %10d %9.5f %8d',
834 835 readsize,
835 836 largestblock,
836 837 readdensity,
837 838 srchunks,
838 839 readsize=readsize,
839 840 largestblock=largestblock,
840 841 readdensity=readdensity,
841 842 srchunks=srchunks,
842 843 )
843 844
844 845 fm.plain(b'\n')
845 846
846 847 fm.end()
847 848
848 849
849 850 @command(
850 851 b'debugdirstate|debugstate',
851 852 [
852 853 (
853 854 b'',
854 855 b'nodates',
855 856 None,
856 857 _(b'do not display the saved mtime (DEPRECATED)'),
857 858 ),
858 859 (b'', b'dates', True, _(b'display the saved mtime')),
859 860 (b'', b'datesort', None, _(b'sort by saved mtime')),
860 861 ],
861 862 _(b'[OPTION]...'),
862 863 )
863 864 def debugstate(ui, repo, **opts):
864 865 """show the contents of the current dirstate"""
865 866
866 867 nodates = not opts['dates']
867 868 if opts.get('nodates') is not None:
868 869 nodates = True
869 870 datesort = opts.get('datesort')
870 871
871 872 if datesort:
872 873 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
873 874 else:
874 875 keyfunc = None # sort by filename
875 876 for file_, ent in sorted(pycompat.iteritems(repo.dirstate), key=keyfunc):
876 877 if ent[3] == -1:
877 878 timestr = b'unset '
878 879 elif nodates:
879 880 timestr = b'set '
880 881 else:
881 882 timestr = time.strftime(
882 883 "%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
883 884 )
884 885 timestr = encoding.strtolocal(timestr)
885 886 if ent[1] & 0o20000:
886 887 mode = b'lnk'
887 888 else:
888 889 mode = b'%3o' % (ent[1] & 0o777 & ~util.umask)
889 890 ui.write(b"%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
890 891 for f in repo.dirstate.copies():
891 892 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
892 893
893 894
894 895 @command(
895 896 b'debugdiscovery',
896 897 [
897 898 (b'', b'old', None, _(b'use old-style discovery')),
898 899 (
899 900 b'',
900 901 b'nonheads',
901 902 None,
902 903 _(b'use old-style discovery with non-heads included'),
903 904 ),
904 905 (b'', b'rev', [], b'restrict discovery to this set of revs'),
905 906 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
906 907 ]
907 908 + cmdutil.remoteopts,
908 909 _(b'[--rev REV] [OTHER]'),
909 910 )
910 911 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
911 912 """runs the changeset discovery protocol in isolation"""
912 913 opts = pycompat.byteskwargs(opts)
913 914 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
914 915 remote = hg.peer(repo, opts, remoteurl)
915 916 ui.status(_(b'comparing with %s\n') % util.hidepassword(remoteurl))
916 917
917 918 # make sure tests are repeatable
918 919 random.seed(int(opts[b'seed']))
919 920
920 921 if opts.get(b'old'):
921 922
922 923 def doit(pushedrevs, remoteheads, remote=remote):
923 924 if not util.safehasattr(remote, b'branches'):
924 925 # enable in-client legacy support
925 926 remote = localrepo.locallegacypeer(remote.local())
926 927 common, _in, hds = treediscovery.findcommonincoming(
927 928 repo, remote, force=True
928 929 )
929 930 common = set(common)
930 931 if not opts.get(b'nonheads'):
931 932 ui.writenoi18n(
932 933 b"unpruned common: %s\n"
933 934 % b" ".join(sorted(short(n) for n in common))
934 935 )
935 936
936 937 clnode = repo.changelog.node
937 938 common = repo.revs(b'heads(::%ln)', common)
938 939 common = {clnode(r) for r in common}
939 940 return common, hds
940 941
941 942 else:
942 943
943 944 def doit(pushedrevs, remoteheads, remote=remote):
944 945 nodes = None
945 946 if pushedrevs:
946 947 revs = scmutil.revrange(repo, pushedrevs)
947 948 nodes = [repo[r].node() for r in revs]
948 949 common, any, hds = setdiscovery.findcommonheads(
949 950 ui, repo, remote, ancestorsof=nodes
950 951 )
951 952 return common, hds
952 953
953 954 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
954 955 localrevs = opts[b'rev']
955 956 with util.timedcm('debug-discovery') as t:
956 957 common, hds = doit(localrevs, remoterevs)
957 958
958 959 # compute all statistics
959 960 common = set(common)
960 961 rheads = set(hds)
961 962 lheads = set(repo.heads())
962 963
963 964 data = {}
964 965 data[b'elapsed'] = t.elapsed
965 966 data[b'nb-common'] = len(common)
966 967 data[b'nb-common-local'] = len(common & lheads)
967 968 data[b'nb-common-remote'] = len(common & rheads)
968 969 data[b'nb-common-both'] = len(common & rheads & lheads)
969 970 data[b'nb-local'] = len(lheads)
970 971 data[b'nb-local-missing'] = data[b'nb-local'] - data[b'nb-common-local']
971 972 data[b'nb-remote'] = len(rheads)
972 973 data[b'nb-remote-unknown'] = data[b'nb-remote'] - data[b'nb-common-remote']
973 974 data[b'nb-revs'] = len(repo.revs(b'all()'))
974 975 data[b'nb-revs-common'] = len(repo.revs(b'::%ln', common))
975 976 data[b'nb-revs-missing'] = data[b'nb-revs'] - data[b'nb-revs-common']
976 977
977 978 # display discovery summary
978 979 ui.writenoi18n(b"elapsed time: %(elapsed)f seconds\n" % data)
979 980 ui.writenoi18n(b"heads summary:\n")
980 981 ui.writenoi18n(b" total common heads: %(nb-common)9d\n" % data)
981 982 ui.writenoi18n(b" also local heads: %(nb-common-local)9d\n" % data)
982 983 ui.writenoi18n(b" also remote heads: %(nb-common-remote)9d\n" % data)
983 984 ui.writenoi18n(b" both: %(nb-common-both)9d\n" % data)
984 985 ui.writenoi18n(b" local heads: %(nb-local)9d\n" % data)
985 986 ui.writenoi18n(b" common: %(nb-common-local)9d\n" % data)
986 987 ui.writenoi18n(b" missing: %(nb-local-missing)9d\n" % data)
987 988 ui.writenoi18n(b" remote heads: %(nb-remote)9d\n" % data)
988 989 ui.writenoi18n(b" common: %(nb-common-remote)9d\n" % data)
989 990 ui.writenoi18n(b" unknown: %(nb-remote-unknown)9d\n" % data)
990 991 ui.writenoi18n(b"local changesets: %(nb-revs)9d\n" % data)
991 992 ui.writenoi18n(b" common: %(nb-revs-common)9d\n" % data)
992 993 ui.writenoi18n(b" missing: %(nb-revs-missing)9d\n" % data)
993 994
994 995 if ui.verbose:
995 996 ui.writenoi18n(
996 997 b"common heads: %s\n" % b" ".join(sorted(short(n) for n in common))
997 998 )
998 999
999 1000
1000 1001 _chunksize = 4 << 10
1001 1002
1002 1003
1003 1004 @command(
1004 1005 b'debugdownload', [(b'o', b'output', b'', _(b'path')),], optionalrepo=True
1005 1006 )
1006 1007 def debugdownload(ui, repo, url, output=None, **opts):
1007 1008 """download a resource using Mercurial logic and config
1008 1009 """
1009 1010 fh = urlmod.open(ui, url, output)
1010 1011
1011 1012 dest = ui
1012 1013 if output:
1013 1014 dest = open(output, b"wb", _chunksize)
1014 1015 try:
1015 1016 data = fh.read(_chunksize)
1016 1017 while data:
1017 1018 dest.write(data)
1018 1019 data = fh.read(_chunksize)
1019 1020 finally:
1020 1021 if output:
1021 1022 dest.close()
1022 1023
1023 1024
1024 1025 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1025 1026 def debugextensions(ui, repo, **opts):
1026 1027 '''show information about active extensions'''
1027 1028 opts = pycompat.byteskwargs(opts)
1028 1029 exts = extensions.extensions(ui)
1029 1030 hgver = util.version()
1030 1031 fm = ui.formatter(b'debugextensions', opts)
1031 1032 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1032 1033 isinternal = extensions.ismoduleinternal(extmod)
1033 1034 extsource = None
1034 1035
1035 1036 if util.safehasattr(extmod, '__file__'):
1036 1037 extsource = pycompat.fsencode(extmod.__file__)
1037 1038 elif getattr(sys, 'oxidized', False):
1038 1039 extsource = pycompat.sysexecutable
1039 1040 if isinternal:
1040 1041 exttestedwith = [] # never expose magic string to users
1041 1042 else:
1042 1043 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1043 1044 extbuglink = getattr(extmod, 'buglink', None)
1044 1045
1045 1046 fm.startitem()
1046 1047
1047 1048 if ui.quiet or ui.verbose:
1048 1049 fm.write(b'name', b'%s\n', extname)
1049 1050 else:
1050 1051 fm.write(b'name', b'%s', extname)
1051 1052 if isinternal or hgver in exttestedwith:
1052 1053 fm.plain(b'\n')
1053 1054 elif not exttestedwith:
1054 1055 fm.plain(_(b' (untested!)\n'))
1055 1056 else:
1056 1057 lasttestedversion = exttestedwith[-1]
1057 1058 fm.plain(b' (%s!)\n' % lasttestedversion)
1058 1059
1059 1060 fm.condwrite(
1060 1061 ui.verbose and extsource,
1061 1062 b'source',
1062 1063 _(b' location: %s\n'),
1063 1064 extsource or b"",
1064 1065 )
1065 1066
1066 1067 if ui.verbose:
1067 1068 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1068 1069 fm.data(bundled=isinternal)
1069 1070
1070 1071 fm.condwrite(
1071 1072 ui.verbose and exttestedwith,
1072 1073 b'testedwith',
1073 1074 _(b' tested with: %s\n'),
1074 1075 fm.formatlist(exttestedwith, name=b'ver'),
1075 1076 )
1076 1077
1077 1078 fm.condwrite(
1078 1079 ui.verbose and extbuglink,
1079 1080 b'buglink',
1080 1081 _(b' bug reporting: %s\n'),
1081 1082 extbuglink or b"",
1082 1083 )
1083 1084
1084 1085 fm.end()
1085 1086
1086 1087
1087 1088 @command(
1088 1089 b'debugfileset',
1089 1090 [
1090 1091 (
1091 1092 b'r',
1092 1093 b'rev',
1093 1094 b'',
1094 1095 _(b'apply the filespec on this revision'),
1095 1096 _(b'REV'),
1096 1097 ),
1097 1098 (
1098 1099 b'',
1099 1100 b'all-files',
1100 1101 False,
1101 1102 _(b'test files from all revisions and working directory'),
1102 1103 ),
1103 1104 (
1104 1105 b's',
1105 1106 b'show-matcher',
1106 1107 None,
1107 1108 _(b'print internal representation of matcher'),
1108 1109 ),
1109 1110 (
1110 1111 b'p',
1111 1112 b'show-stage',
1112 1113 [],
1113 1114 _(b'print parsed tree at the given stage'),
1114 1115 _(b'NAME'),
1115 1116 ),
1116 1117 ],
1117 1118 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1118 1119 )
1119 1120 def debugfileset(ui, repo, expr, **opts):
1120 1121 '''parse and apply a fileset specification'''
1121 1122 from . import fileset
1122 1123
1123 1124 fileset.symbols # force import of fileset so we have predicates to optimize
1124 1125 opts = pycompat.byteskwargs(opts)
1125 1126 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
1126 1127
1127 1128 stages = [
1128 1129 (b'parsed', pycompat.identity),
1129 1130 (b'analyzed', filesetlang.analyze),
1130 1131 (b'optimized', filesetlang.optimize),
1131 1132 ]
1132 1133 stagenames = set(n for n, f in stages)
1133 1134
1134 1135 showalways = set()
1135 1136 if ui.verbose and not opts[b'show_stage']:
1136 1137 # show parsed tree by --verbose (deprecated)
1137 1138 showalways.add(b'parsed')
1138 1139 if opts[b'show_stage'] == [b'all']:
1139 1140 showalways.update(stagenames)
1140 1141 else:
1141 1142 for n in opts[b'show_stage']:
1142 1143 if n not in stagenames:
1143 1144 raise error.Abort(_(b'invalid stage name: %s') % n)
1144 1145 showalways.update(opts[b'show_stage'])
1145 1146
1146 1147 tree = filesetlang.parse(expr)
1147 1148 for n, f in stages:
1148 1149 tree = f(tree)
1149 1150 if n in showalways:
1150 1151 if opts[b'show_stage'] or n != b'parsed':
1151 1152 ui.write(b"* %s:\n" % n)
1152 1153 ui.write(filesetlang.prettyformat(tree), b"\n")
1153 1154
1154 1155 files = set()
1155 1156 if opts[b'all_files']:
1156 1157 for r in repo:
1157 1158 c = repo[r]
1158 1159 files.update(c.files())
1159 1160 files.update(c.substate)
1160 1161 if opts[b'all_files'] or ctx.rev() is None:
1161 1162 wctx = repo[None]
1162 1163 files.update(
1163 1164 repo.dirstate.walk(
1164 1165 scmutil.matchall(repo),
1165 1166 subrepos=list(wctx.substate),
1166 1167 unknown=True,
1167 1168 ignored=True,
1168 1169 )
1169 1170 )
1170 1171 files.update(wctx.substate)
1171 1172 else:
1172 1173 files.update(ctx.files())
1173 1174 files.update(ctx.substate)
1174 1175
1175 1176 m = ctx.matchfileset(repo.getcwd(), expr)
1176 1177 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1177 1178 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1178 1179 for f in sorted(files):
1179 1180 if not m(f):
1180 1181 continue
1181 1182 ui.write(b"%s\n" % f)
1182 1183
1183 1184
1184 1185 @command(b'debugformat', [] + cmdutil.formatteropts)
1185 1186 def debugformat(ui, repo, **opts):
1186 1187 """display format information about the current repository
1187 1188
1188 1189 Use --verbose to get extra information about current config value and
1189 1190 Mercurial default."""
1190 1191 opts = pycompat.byteskwargs(opts)
1191 1192 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1192 1193 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1193 1194
1194 1195 def makeformatname(name):
1195 1196 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1196 1197
1197 1198 fm = ui.formatter(b'debugformat', opts)
1198 1199 if fm.isplain():
1199 1200
1200 1201 def formatvalue(value):
1201 1202 if util.safehasattr(value, b'startswith'):
1202 1203 return value
1203 1204 if value:
1204 1205 return b'yes'
1205 1206 else:
1206 1207 return b'no'
1207 1208
1208 1209 else:
1209 1210 formatvalue = pycompat.identity
1210 1211
1211 1212 fm.plain(b'format-variant')
1212 1213 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1213 1214 fm.plain(b' repo')
1214 1215 if ui.verbose:
1215 1216 fm.plain(b' config default')
1216 1217 fm.plain(b'\n')
1217 1218 for fv in upgrade.allformatvariant:
1218 1219 fm.startitem()
1219 1220 repovalue = fv.fromrepo(repo)
1220 1221 configvalue = fv.fromconfig(repo)
1221 1222
1222 1223 if repovalue != configvalue:
1223 1224 namelabel = b'formatvariant.name.mismatchconfig'
1224 1225 repolabel = b'formatvariant.repo.mismatchconfig'
1225 1226 elif repovalue != fv.default:
1226 1227 namelabel = b'formatvariant.name.mismatchdefault'
1227 1228 repolabel = b'formatvariant.repo.mismatchdefault'
1228 1229 else:
1229 1230 namelabel = b'formatvariant.name.uptodate'
1230 1231 repolabel = b'formatvariant.repo.uptodate'
1231 1232
1232 1233 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1233 1234 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1234 1235 if fv.default != configvalue:
1235 1236 configlabel = b'formatvariant.config.special'
1236 1237 else:
1237 1238 configlabel = b'formatvariant.config.default'
1238 1239 fm.condwrite(
1239 1240 ui.verbose,
1240 1241 b'config',
1241 1242 b' %6s',
1242 1243 formatvalue(configvalue),
1243 1244 label=configlabel,
1244 1245 )
1245 1246 fm.condwrite(
1246 1247 ui.verbose,
1247 1248 b'default',
1248 1249 b' %7s',
1249 1250 formatvalue(fv.default),
1250 1251 label=b'formatvariant.default',
1251 1252 )
1252 1253 fm.plain(b'\n')
1253 1254 fm.end()
1254 1255
1255 1256
1256 1257 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1257 1258 def debugfsinfo(ui, path=b"."):
1258 1259 """show information detected about current filesystem"""
1259 1260 ui.writenoi18n(b'path: %s\n' % path)
1260 1261 ui.writenoi18n(
1261 1262 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1262 1263 )
1263 1264 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1264 1265 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1265 1266 ui.writenoi18n(
1266 1267 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1267 1268 )
1268 1269 ui.writenoi18n(
1269 1270 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1270 1271 )
1271 1272 casesensitive = b'(unknown)'
1272 1273 try:
1273 1274 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1274 1275 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1275 1276 except OSError:
1276 1277 pass
1277 1278 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1278 1279
1279 1280
1280 1281 @command(
1281 1282 b'debuggetbundle',
1282 1283 [
1283 1284 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1284 1285 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1285 1286 (
1286 1287 b't',
1287 1288 b'type',
1288 1289 b'bzip2',
1289 1290 _(b'bundle compression type to use'),
1290 1291 _(b'TYPE'),
1291 1292 ),
1292 1293 ],
1293 1294 _(b'REPO FILE [-H|-C ID]...'),
1294 1295 norepo=True,
1295 1296 )
1296 1297 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1297 1298 """retrieves a bundle from a repo
1298 1299
1299 1300 Every ID must be a full-length hex node id string. Saves the bundle to the
1300 1301 given file.
1301 1302 """
1302 1303 opts = pycompat.byteskwargs(opts)
1303 1304 repo = hg.peer(ui, opts, repopath)
1304 1305 if not repo.capable(b'getbundle'):
1305 1306 raise error.Abort(b"getbundle() not supported by target repository")
1306 1307 args = {}
1307 1308 if common:
1308 1309 args['common'] = [bin(s) for s in common]
1309 1310 if head:
1310 1311 args['heads'] = [bin(s) for s in head]
1311 1312 # TODO: get desired bundlecaps from command line.
1312 1313 args['bundlecaps'] = None
1313 1314 bundle = repo.getbundle(b'debug', **args)
1314 1315
1315 1316 bundletype = opts.get(b'type', b'bzip2').lower()
1316 1317 btypes = {
1317 1318 b'none': b'HG10UN',
1318 1319 b'bzip2': b'HG10BZ',
1319 1320 b'gzip': b'HG10GZ',
1320 1321 b'bundle2': b'HG20',
1321 1322 }
1322 1323 bundletype = btypes.get(bundletype)
1323 1324 if bundletype not in bundle2.bundletypes:
1324 1325 raise error.Abort(_(b'unknown bundle type specified with --type'))
1325 1326 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1326 1327
1327 1328
1328 1329 @command(b'debugignore', [], b'[FILE]')
1329 1330 def debugignore(ui, repo, *files, **opts):
1330 1331 """display the combined ignore pattern and information about ignored files
1331 1332
1332 1333 With no argument display the combined ignore pattern.
1333 1334
1334 1335 Given space separated file names, shows if the given file is ignored and
1335 1336 if so, show the ignore rule (file and line number) that matched it.
1336 1337 """
1337 1338 ignore = repo.dirstate._ignore
1338 1339 if not files:
1339 1340 # Show all the patterns
1340 1341 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1341 1342 else:
1342 1343 m = scmutil.match(repo[None], pats=files)
1343 1344 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1344 1345 for f in m.files():
1345 1346 nf = util.normpath(f)
1346 1347 ignored = None
1347 1348 ignoredata = None
1348 1349 if nf != b'.':
1349 1350 if ignore(nf):
1350 1351 ignored = nf
1351 1352 ignoredata = repo.dirstate._ignorefileandline(nf)
1352 1353 else:
1353 1354 for p in pathutil.finddirs(nf):
1354 1355 if ignore(p):
1355 1356 ignored = p
1356 1357 ignoredata = repo.dirstate._ignorefileandline(p)
1357 1358 break
1358 1359 if ignored:
1359 1360 if ignored == nf:
1360 1361 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1361 1362 else:
1362 1363 ui.write(
1363 1364 _(
1364 1365 b"%s is ignored because of "
1365 1366 b"containing directory %s\n"
1366 1367 )
1367 1368 % (uipathfn(f), ignored)
1368 1369 )
1369 1370 ignorefile, lineno, line = ignoredata
1370 1371 ui.write(
1371 1372 _(b"(ignore rule in %s, line %d: '%s')\n")
1372 1373 % (ignorefile, lineno, line)
1373 1374 )
1374 1375 else:
1375 1376 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1376 1377
1377 1378
1378 1379 @command(
1379 1380 b'debugindex',
1380 1381 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1381 1382 _(b'-c|-m|FILE'),
1382 1383 )
1383 1384 def debugindex(ui, repo, file_=None, **opts):
1384 1385 """dump index data for a storage primitive"""
1385 1386 opts = pycompat.byteskwargs(opts)
1386 1387 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1387 1388
1388 1389 if ui.debugflag:
1389 1390 shortfn = hex
1390 1391 else:
1391 1392 shortfn = short
1392 1393
1393 1394 idlen = 12
1394 1395 for i in store:
1395 1396 idlen = len(shortfn(store.node(i)))
1396 1397 break
1397 1398
1398 1399 fm = ui.formatter(b'debugindex', opts)
1399 1400 fm.plain(
1400 1401 b' rev linkrev %s %s p2\n'
1401 1402 % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
1402 1403 )
1403 1404
1404 1405 for rev in store:
1405 1406 node = store.node(rev)
1406 1407 parents = store.parents(node)
1407 1408
1408 1409 fm.startitem()
1409 1410 fm.write(b'rev', b'%6d ', rev)
1410 1411 fm.write(b'linkrev', b'%7d ', store.linkrev(rev))
1411 1412 fm.write(b'node', b'%s ', shortfn(node))
1412 1413 fm.write(b'p1', b'%s ', shortfn(parents[0]))
1413 1414 fm.write(b'p2', b'%s', shortfn(parents[1]))
1414 1415 fm.plain(b'\n')
1415 1416
1416 1417 fm.end()
1417 1418
1418 1419
1419 1420 @command(
1420 1421 b'debugindexdot',
1421 1422 cmdutil.debugrevlogopts,
1422 1423 _(b'-c|-m|FILE'),
1423 1424 optionalrepo=True,
1424 1425 )
1425 1426 def debugindexdot(ui, repo, file_=None, **opts):
1426 1427 """dump an index DAG as a graphviz dot file"""
1427 1428 opts = pycompat.byteskwargs(opts)
1428 1429 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1429 1430 ui.writenoi18n(b"digraph G {\n")
1430 1431 for i in r:
1431 1432 node = r.node(i)
1432 1433 pp = r.parents(node)
1433 1434 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1434 1435 if pp[1] != nullid:
1435 1436 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1436 1437 ui.write(b"}\n")
1437 1438
1438 1439
1439 1440 @command(b'debugindexstats', [])
1440 1441 def debugindexstats(ui, repo):
1441 1442 """show stats related to the changelog index"""
1442 1443 repo.changelog.shortest(nullid, 1)
1443 1444 index = repo.changelog.index
1444 1445 if not util.safehasattr(index, b'stats'):
1445 1446 raise error.Abort(_(b'debugindexstats only works with native code'))
1446 1447 for k, v in sorted(index.stats().items()):
1447 1448 ui.write(b'%s: %d\n' % (k, v))
1448 1449
1449 1450
1450 1451 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1451 1452 def debuginstall(ui, **opts):
1452 1453 '''test Mercurial installation
1453 1454
1454 1455 Returns 0 on success.
1455 1456 '''
1456 1457 opts = pycompat.byteskwargs(opts)
1457 1458
1458 1459 problems = 0
1459 1460
1460 1461 fm = ui.formatter(b'debuginstall', opts)
1461 1462 fm.startitem()
1462 1463
1463 1464 # encoding
1464 1465 fm.write(b'encoding', _(b"checking encoding (%s)...\n"), encoding.encoding)
1465 1466 err = None
1466 1467 try:
1467 1468 codecs.lookup(pycompat.sysstr(encoding.encoding))
1468 1469 except LookupError as inst:
1469 1470 err = stringutil.forcebytestr(inst)
1470 1471 problems += 1
1471 1472 fm.condwrite(
1472 1473 err,
1473 1474 b'encodingerror',
1474 1475 _(b" %s\n (check that your locale is properly set)\n"),
1475 1476 err,
1476 1477 )
1477 1478
1478 1479 # Python
1479 1480 pythonlib = None
1480 1481 if util.safehasattr(os, '__file__'):
1481 1482 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1482 1483 elif getattr(sys, 'oxidized', False):
1483 1484 pythonlib = pycompat.sysexecutable
1484 1485
1485 1486 fm.write(
1486 1487 b'pythonexe',
1487 1488 _(b"checking Python executable (%s)\n"),
1488 1489 pycompat.sysexecutable or _(b"unknown"),
1489 1490 )
1490 1491 fm.write(
1491 1492 b'pythonimplementation',
1492 1493 _(b"checking Python implementation (%s)\n"),
1493 1494 pycompat.sysbytes(platform.python_implementation()),
1494 1495 )
1495 1496 fm.write(
1496 1497 b'pythonver',
1497 1498 _(b"checking Python version (%s)\n"),
1498 1499 (b"%d.%d.%d" % sys.version_info[:3]),
1499 1500 )
1500 1501 fm.write(
1501 1502 b'pythonlib',
1502 1503 _(b"checking Python lib (%s)...\n"),
1503 1504 pythonlib or _(b"unknown"),
1504 1505 )
1505 1506
1506 1507 security = set(sslutil.supportedprotocols)
1507 1508 if sslutil.hassni:
1508 1509 security.add(b'sni')
1509 1510
1510 1511 fm.write(
1511 1512 b'pythonsecurity',
1512 1513 _(b"checking Python security support (%s)\n"),
1513 1514 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1514 1515 )
1515 1516
1516 1517 # These are warnings, not errors. So don't increment problem count. This
1517 1518 # may change in the future.
1518 1519 if b'tls1.2' not in security:
1519 1520 fm.plain(
1520 1521 _(
1521 1522 b' TLS 1.2 not supported by Python install; '
1522 1523 b'network connections lack modern security\n'
1523 1524 )
1524 1525 )
1525 1526 if b'sni' not in security:
1526 1527 fm.plain(
1527 1528 _(
1528 1529 b' SNI not supported by Python install; may have '
1529 1530 b'connectivity issues with some servers\n'
1530 1531 )
1531 1532 )
1532 1533
1533 1534 # TODO print CA cert info
1534 1535
1535 1536 # hg version
1536 1537 hgver = util.version()
1537 1538 fm.write(
1538 1539 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1539 1540 )
1540 1541 fm.write(
1541 1542 b'hgverextra',
1542 1543 _(b"checking Mercurial custom build (%s)\n"),
1543 1544 b'+'.join(hgver.split(b'+')[1:]),
1544 1545 )
1545 1546
1546 1547 # compiled modules
1547 1548 hgmodules = None
1548 1549 if util.safehasattr(sys.modules[__name__], '__file__'):
1549 1550 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1550 1551 elif getattr(sys, 'oxidized', False):
1551 1552 hgmodules = pycompat.sysexecutable
1552 1553
1553 1554 fm.write(
1554 1555 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1555 1556 )
1556 1557 fm.write(
1557 1558 b'hgmodules',
1558 1559 _(b"checking installed modules (%s)...\n"),
1559 1560 hgmodules or _(b"unknown"),
1560 1561 )
1561 1562
1562 1563 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1563 1564 rustext = rustandc # for now, that's the only case
1564 1565 cext = policy.policy in (b'c', b'allow') or rustandc
1565 1566 nopure = cext or rustext
1566 1567 if nopure:
1567 1568 err = None
1568 1569 try:
1569 1570 if cext:
1570 1571 from .cext import ( # pytype: disable=import-error
1571 1572 base85,
1572 1573 bdiff,
1573 1574 mpatch,
1574 1575 osutil,
1575 1576 )
1576 1577
1577 1578 # quiet pyflakes
1578 1579 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
1579 1580 if rustext:
1580 1581 from .rustext import ( # pytype: disable=import-error
1581 1582 ancestor,
1582 1583 dirstate,
1583 1584 )
1584 1585
1585 1586 dir(ancestor), dir(dirstate) # quiet pyflakes
1586 1587 except Exception as inst:
1587 1588 err = stringutil.forcebytestr(inst)
1588 1589 problems += 1
1589 1590 fm.condwrite(err, b'extensionserror', b" %s\n", err)
1590 1591
1591 1592 compengines = util.compengines._engines.values()
1592 1593 fm.write(
1593 1594 b'compengines',
1594 1595 _(b'checking registered compression engines (%s)\n'),
1595 1596 fm.formatlist(
1596 1597 sorted(e.name() for e in compengines),
1597 1598 name=b'compengine',
1598 1599 fmt=b'%s',
1599 1600 sep=b', ',
1600 1601 ),
1601 1602 )
1602 1603 fm.write(
1603 1604 b'compenginesavail',
1604 1605 _(b'checking available compression engines (%s)\n'),
1605 1606 fm.formatlist(
1606 1607 sorted(e.name() for e in compengines if e.available()),
1607 1608 name=b'compengine',
1608 1609 fmt=b'%s',
1609 1610 sep=b', ',
1610 1611 ),
1611 1612 )
1612 1613 wirecompengines = compression.compengines.supportedwireengines(
1613 1614 compression.SERVERROLE
1614 1615 )
1615 1616 fm.write(
1616 1617 b'compenginesserver',
1617 1618 _(
1618 1619 b'checking available compression engines '
1619 1620 b'for wire protocol (%s)\n'
1620 1621 ),
1621 1622 fm.formatlist(
1622 1623 [e.name() for e in wirecompengines if e.wireprotosupport()],
1623 1624 name=b'compengine',
1624 1625 fmt=b'%s',
1625 1626 sep=b', ',
1626 1627 ),
1627 1628 )
1628 1629 re2 = b'missing'
1629 1630 if util._re2:
1630 1631 re2 = b'available'
1631 1632 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
1632 1633 fm.data(re2=bool(util._re2))
1633 1634
1634 1635 # templates
1635 1636 p = templater.templatepaths()
1636 1637 fm.write(b'templatedirs', b'checking templates (%s)...\n', b' '.join(p))
1637 1638 fm.condwrite(not p, b'', _(b" no template directories found\n"))
1638 1639 if p:
1639 1640 m = templater.templatepath(b"map-cmdline.default")
1640 1641 if m:
1641 1642 # template found, check if it is working
1642 1643 err = None
1643 1644 try:
1644 1645 templater.templater.frommapfile(m)
1645 1646 except Exception as inst:
1646 1647 err = stringutil.forcebytestr(inst)
1647 1648 p = None
1648 1649 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
1649 1650 else:
1650 1651 p = None
1651 1652 fm.condwrite(
1652 1653 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
1653 1654 )
1654 1655 fm.condwrite(
1655 1656 not m,
1656 1657 b'defaulttemplatenotfound',
1657 1658 _(b" template '%s' not found\n"),
1658 1659 b"default",
1659 1660 )
1660 1661 if not p:
1661 1662 problems += 1
1662 1663 fm.condwrite(
1663 1664 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
1664 1665 )
1665 1666
1666 1667 # editor
1667 1668 editor = ui.geteditor()
1668 1669 editor = util.expandpath(editor)
1669 1670 editorbin = procutil.shellsplit(editor)[0]
1670 1671 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
1671 1672 cmdpath = procutil.findexe(editorbin)
1672 1673 fm.condwrite(
1673 1674 not cmdpath and editor == b'vi',
1674 1675 b'vinotfound',
1675 1676 _(
1676 1677 b" No commit editor set and can't find %s in PATH\n"
1677 1678 b" (specify a commit editor in your configuration"
1678 1679 b" file)\n"
1679 1680 ),
1680 1681 not cmdpath and editor == b'vi' and editorbin,
1681 1682 )
1682 1683 fm.condwrite(
1683 1684 not cmdpath and editor != b'vi',
1684 1685 b'editornotfound',
1685 1686 _(
1686 1687 b" Can't find editor '%s' in PATH\n"
1687 1688 b" (specify a commit editor in your configuration"
1688 1689 b" file)\n"
1689 1690 ),
1690 1691 not cmdpath and editorbin,
1691 1692 )
1692 1693 if not cmdpath and editor != b'vi':
1693 1694 problems += 1
1694 1695
1695 1696 # check username
1696 1697 username = None
1697 1698 err = None
1698 1699 try:
1699 1700 username = ui.username()
1700 1701 except error.Abort as e:
1701 1702 err = stringutil.forcebytestr(e)
1702 1703 problems += 1
1703 1704
1704 1705 fm.condwrite(
1705 1706 username, b'username', _(b"checking username (%s)\n"), username
1706 1707 )
1707 1708 fm.condwrite(
1708 1709 err,
1709 1710 b'usernameerror',
1710 1711 _(
1711 1712 b"checking username...\n %s\n"
1712 1713 b" (specify a username in your configuration file)\n"
1713 1714 ),
1714 1715 err,
1715 1716 )
1716 1717
1717 1718 for name, mod in extensions.extensions():
1718 1719 handler = getattr(mod, 'debuginstall', None)
1719 1720 if handler is not None:
1720 1721 problems += handler(ui, fm)
1721 1722
1722 1723 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
1723 1724 if not problems:
1724 1725 fm.data(problems=problems)
1725 1726 fm.condwrite(
1726 1727 problems,
1727 1728 b'problems',
1728 1729 _(b"%d problems detected, please check your install!\n"),
1729 1730 problems,
1730 1731 )
1731 1732 fm.end()
1732 1733
1733 1734 return problems
1734 1735
1735 1736
1736 1737 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
1737 1738 def debugknown(ui, repopath, *ids, **opts):
1738 1739 """test whether node ids are known to a repo
1739 1740
1740 1741 Every ID must be a full-length hex node id string. Returns a list of 0s
1741 1742 and 1s indicating unknown/known.
1742 1743 """
1743 1744 opts = pycompat.byteskwargs(opts)
1744 1745 repo = hg.peer(ui, opts, repopath)
1745 1746 if not repo.capable(b'known'):
1746 1747 raise error.Abort(b"known() not supported by target repository")
1747 1748 flags = repo.known([bin(s) for s in ids])
1748 1749 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
1749 1750
1750 1751
1751 1752 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
1752 1753 def debuglabelcomplete(ui, repo, *args):
1753 1754 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1754 1755 debugnamecomplete(ui, repo, *args)
1755 1756
1756 1757
1757 1758 @command(
1758 1759 b'debuglocks',
1759 1760 [
1760 1761 (b'L', b'force-lock', None, _(b'free the store lock (DANGEROUS)')),
1761 1762 (
1762 1763 b'W',
1763 1764 b'force-wlock',
1764 1765 None,
1765 1766 _(b'free the working state lock (DANGEROUS)'),
1766 1767 ),
1767 1768 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
1768 1769 (
1769 1770 b'S',
1770 1771 b'set-wlock',
1771 1772 None,
1772 1773 _(b'set the working state lock until stopped'),
1773 1774 ),
1774 1775 ],
1775 1776 _(b'[OPTION]...'),
1776 1777 )
1777 1778 def debuglocks(ui, repo, **opts):
1778 1779 """show or modify state of locks
1779 1780
1780 1781 By default, this command will show which locks are held. This
1781 1782 includes the user and process holding the lock, the amount of time
1782 1783 the lock has been held, and the machine name where the process is
1783 1784 running if it's not local.
1784 1785
1785 1786 Locks protect the integrity of Mercurial's data, so should be
1786 1787 treated with care. System crashes or other interruptions may cause
1787 1788 locks to not be properly released, though Mercurial will usually
1788 1789 detect and remove such stale locks automatically.
1789 1790
1790 1791 However, detecting stale locks may not always be possible (for
1791 1792 instance, on a shared filesystem). Removing locks may also be
1792 1793 blocked by filesystem permissions.
1793 1794
1794 1795 Setting a lock will prevent other commands from changing the data.
1795 1796 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1796 1797 The set locks are removed when the command exits.
1797 1798
1798 1799 Returns 0 if no locks are held.
1799 1800
1800 1801 """
1801 1802
1802 1803 if opts.get('force_lock'):
1803 1804 repo.svfs.unlink(b'lock')
1804 1805 if opts.get('force_wlock'):
1805 1806 repo.vfs.unlink(b'wlock')
1806 1807 if opts.get('force_lock') or opts.get('force_wlock'):
1807 1808 return 0
1808 1809
1809 1810 locks = []
1810 1811 try:
1811 1812 if opts.get('set_wlock'):
1812 1813 try:
1813 1814 locks.append(repo.wlock(False))
1814 1815 except error.LockHeld:
1815 1816 raise error.Abort(_(b'wlock is already held'))
1816 1817 if opts.get('set_lock'):
1817 1818 try:
1818 1819 locks.append(repo.lock(False))
1819 1820 except error.LockHeld:
1820 1821 raise error.Abort(_(b'lock is already held'))
1821 1822 if len(locks):
1822 1823 ui.promptchoice(_(b"ready to release the lock (y)? $$ &Yes"))
1823 1824 return 0
1824 1825 finally:
1825 1826 release(*locks)
1826 1827
1827 1828 now = time.time()
1828 1829 held = 0
1829 1830
1830 1831 def report(vfs, name, method):
1831 1832 # this causes stale locks to get reaped for more accurate reporting
1832 1833 try:
1833 1834 l = method(False)
1834 1835 except error.LockHeld:
1835 1836 l = None
1836 1837
1837 1838 if l:
1838 1839 l.release()
1839 1840 else:
1840 1841 try:
1841 1842 st = vfs.lstat(name)
1842 1843 age = now - st[stat.ST_MTIME]
1843 1844 user = util.username(st.st_uid)
1844 1845 locker = vfs.readlock(name)
1845 1846 if b":" in locker:
1846 1847 host, pid = locker.split(b':')
1847 1848 if host == socket.gethostname():
1848 1849 locker = b'user %s, process %s' % (user or b'None', pid)
1849 1850 else:
1850 1851 locker = b'user %s, process %s, host %s' % (
1851 1852 user or b'None',
1852 1853 pid,
1853 1854 host,
1854 1855 )
1855 1856 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
1856 1857 return 1
1857 1858 except OSError as e:
1858 1859 if e.errno != errno.ENOENT:
1859 1860 raise
1860 1861
1861 1862 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
1862 1863 return 0
1863 1864
1864 1865 held += report(repo.svfs, b"lock", repo.lock)
1865 1866 held += report(repo.vfs, b"wlock", repo.wlock)
1866 1867
1867 1868 return held
1868 1869
1869 1870
1870 1871 @command(
1871 1872 b'debugmanifestfulltextcache',
1872 1873 [
1873 1874 (b'', b'clear', False, _(b'clear the cache')),
1874 1875 (
1875 1876 b'a',
1876 1877 b'add',
1877 1878 [],
1878 1879 _(b'add the given manifest nodes to the cache'),
1879 1880 _(b'NODE'),
1880 1881 ),
1881 1882 ],
1882 1883 b'',
1883 1884 )
1884 1885 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
1885 1886 """show, clear or amend the contents of the manifest fulltext cache"""
1886 1887
1887 1888 def getcache():
1888 1889 r = repo.manifestlog.getstorage(b'')
1889 1890 try:
1890 1891 return r._fulltextcache
1891 1892 except AttributeError:
1892 1893 msg = _(
1893 1894 b"Current revlog implementation doesn't appear to have a "
1894 1895 b"manifest fulltext cache\n"
1895 1896 )
1896 1897 raise error.Abort(msg)
1897 1898
1898 1899 if opts.get('clear'):
1899 1900 with repo.wlock():
1900 1901 cache = getcache()
1901 1902 cache.clear(clear_persisted_data=True)
1902 1903 return
1903 1904
1904 1905 if add:
1905 1906 with repo.wlock():
1906 1907 m = repo.manifestlog
1907 1908 store = m.getstorage(b'')
1908 1909 for n in add:
1909 1910 try:
1910 1911 manifest = m[store.lookup(n)]
1911 1912 except error.LookupError as e:
1912 1913 raise error.Abort(e, hint=b"Check your manifest node id")
1913 1914 manifest.read() # stores revisision in cache too
1914 1915 return
1915 1916
1916 1917 cache = getcache()
1917 1918 if not len(cache):
1918 1919 ui.write(_(b'cache empty\n'))
1919 1920 else:
1920 1921 ui.write(
1921 1922 _(
1922 1923 b'cache contains %d manifest entries, in order of most to '
1923 1924 b'least recent:\n'
1924 1925 )
1925 1926 % (len(cache),)
1926 1927 )
1927 1928 totalsize = 0
1928 1929 for nodeid in cache:
1929 1930 # Use cache.get to not update the LRU order
1930 1931 data = cache.peek(nodeid)
1931 1932 size = len(data)
1932 1933 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1933 1934 ui.write(
1934 1935 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
1935 1936 )
1936 1937 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
1937 1938 ui.write(
1938 1939 _(b'total cache data size %s, on-disk %s\n')
1939 1940 % (util.bytecount(totalsize), util.bytecount(ondisk))
1940 1941 )
1941 1942
1942 1943
1943 1944 @command(b'debugmergestate', [], b'')
1944 1945 def debugmergestate(ui, repo, *args):
1945 1946 """print merge state
1946 1947
1947 1948 Use --verbose to print out information about whether v1 or v2 merge state
1948 1949 was chosen."""
1949 1950
1950 1951 def _hashornull(h):
1951 1952 if h == nullhex:
1952 1953 return b'null'
1953 1954 else:
1954 1955 return h
1955 1956
1956 1957 def printrecords(version):
1957 1958 ui.writenoi18n(b'* version %d records\n' % version)
1958 1959 if version == 1:
1959 1960 records = v1records
1960 1961 else:
1961 1962 records = v2records
1962 1963
1963 1964 for rtype, record in records:
1964 1965 # pretty print some record types
1965 1966 if rtype == b'L':
1966 1967 ui.writenoi18n(b'local: %s\n' % record)
1967 1968 elif rtype == b'O':
1968 1969 ui.writenoi18n(b'other: %s\n' % record)
1969 1970 elif rtype == b'm':
1970 1971 driver, mdstate = record.split(b'\0', 1)
1971 1972 ui.writenoi18n(
1972 1973 b'merge driver: %s (state "%s")\n' % (driver, mdstate)
1973 1974 )
1974 1975 elif rtype in b'FDC':
1975 1976 r = record.split(b'\0')
1976 1977 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1977 1978 if version == 1:
1978 1979 onode = b'not stored in v1 format'
1979 1980 flags = r[7]
1980 1981 else:
1981 1982 onode, flags = r[7:9]
1982 1983 ui.writenoi18n(
1983 1984 b'file: %s (record type "%s", state "%s", hash %s)\n'
1984 1985 % (f, rtype, state, _hashornull(hash))
1985 1986 )
1986 1987 ui.writenoi18n(
1987 1988 b' local path: %s (flags "%s")\n' % (lfile, flags)
1988 1989 )
1989 1990 ui.writenoi18n(
1990 1991 b' ancestor path: %s (node %s)\n'
1991 1992 % (afile, _hashornull(anode))
1992 1993 )
1993 1994 ui.writenoi18n(
1994 1995 b' other path: %s (node %s)\n'
1995 1996 % (ofile, _hashornull(onode))
1996 1997 )
1997 1998 elif rtype == b'f':
1998 1999 filename, rawextras = record.split(b'\0', 1)
1999 2000 extras = rawextras.split(b'\0')
2000 2001 i = 0
2001 2002 extrastrings = []
2002 2003 while i < len(extras):
2003 2004 extrastrings.append(b'%s = %s' % (extras[i], extras[i + 1]))
2004 2005 i += 2
2005 2006
2006 2007 ui.writenoi18n(
2007 2008 b'file extras: %s (%s)\n'
2008 2009 % (filename, b', '.join(extrastrings))
2009 2010 )
2010 2011 elif rtype == b'l':
2011 2012 labels = record.split(b'\0', 2)
2012 2013 labels = [l for l in labels if len(l) > 0]
2013 2014 ui.writenoi18n(b'labels:\n')
2014 2015 ui.write((b' local: %s\n' % labels[0]))
2015 2016 ui.write((b' other: %s\n' % labels[1]))
2016 2017 if len(labels) > 2:
2017 2018 ui.write((b' base: %s\n' % labels[2]))
2018 2019 else:
2019 2020 ui.writenoi18n(
2020 2021 b'unrecognized entry: %s\t%s\n'
2021 2022 % (rtype, record.replace(b'\0', b'\t'))
2022 2023 )
2023 2024
2024 2025 # Avoid mergestate.read() since it may raise an exception for unsupported
2025 2026 # merge state records. We shouldn't be doing this, but this is OK since this
2026 2027 # command is pretty low-level.
2027 2028 ms = mergemod.mergestate(repo)
2028 2029
2029 2030 # sort so that reasonable information is on top
2030 2031 v1records = ms._readrecordsv1()
2031 2032 v2records = ms._readrecordsv2()
2032 2033 order = b'LOml'
2033 2034
2034 2035 def key(r):
2035 2036 idx = order.find(r[0])
2036 2037 if idx == -1:
2037 2038 return (1, r[1])
2038 2039 else:
2039 2040 return (0, idx)
2040 2041
2041 2042 v1records.sort(key=key)
2042 2043 v2records.sort(key=key)
2043 2044
2044 2045 if not v1records and not v2records:
2045 2046 ui.writenoi18n(b'no merge state found\n')
2046 2047 elif not v2records:
2047 2048 ui.notenoi18n(b'no version 2 merge state\n')
2048 2049 printrecords(1)
2049 2050 elif ms._v1v2match(v1records, v2records):
2050 2051 ui.notenoi18n(b'v1 and v2 states match: using v2\n')
2051 2052 printrecords(2)
2052 2053 else:
2053 2054 ui.notenoi18n(b'v1 and v2 states mismatch: using v1\n')
2054 2055 printrecords(1)
2055 2056 if ui.verbose:
2056 2057 printrecords(2)
2057 2058
2058 2059
2059 2060 @command(b'debugnamecomplete', [], _(b'NAME...'))
2060 2061 def debugnamecomplete(ui, repo, *args):
2061 2062 '''complete "names" - tags, open branch names, bookmark names'''
2062 2063
2063 2064 names = set()
2064 2065 # since we previously only listed open branches, we will handle that
2065 2066 # specially (after this for loop)
2066 2067 for name, ns in pycompat.iteritems(repo.names):
2067 2068 if name != b'branches':
2068 2069 names.update(ns.listnames(repo))
2069 2070 names.update(
2070 2071 tag
2071 2072 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2072 2073 if not closed
2073 2074 )
2074 2075 completions = set()
2075 2076 if not args:
2076 2077 args = [b'']
2077 2078 for a in args:
2078 2079 completions.update(n for n in names if n.startswith(a))
2079 2080 ui.write(b'\n'.join(sorted(completions)))
2080 2081 ui.write(b'\n')
2081 2082
2082 2083
2083 2084 @command(
2084 2085 b'debugobsolete',
2085 2086 [
2086 2087 (b'', b'flags', 0, _(b'markers flag')),
2087 2088 (
2088 2089 b'',
2089 2090 b'record-parents',
2090 2091 False,
2091 2092 _(b'record parent information for the precursor'),
2092 2093 ),
2093 2094 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2094 2095 (
2095 2096 b'',
2096 2097 b'exclusive',
2097 2098 False,
2098 2099 _(b'restrict display to markers only relevant to REV'),
2099 2100 ),
2100 2101 (b'', b'index', False, _(b'display index of the marker')),
2101 2102 (b'', b'delete', [], _(b'delete markers specified by indices')),
2102 2103 ]
2103 2104 + cmdutil.commitopts2
2104 2105 + cmdutil.formatteropts,
2105 2106 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2106 2107 )
2107 2108 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2108 2109 """create arbitrary obsolete marker
2109 2110
2110 2111 With no arguments, displays the list of obsolescence markers."""
2111 2112
2112 2113 opts = pycompat.byteskwargs(opts)
2113 2114
2114 2115 def parsenodeid(s):
2115 2116 try:
2116 2117 # We do not use revsingle/revrange functions here to accept
2117 2118 # arbitrary node identifiers, possibly not present in the
2118 2119 # local repository.
2119 2120 n = bin(s)
2120 2121 if len(n) != len(nullid):
2121 2122 raise TypeError()
2122 2123 return n
2123 2124 except TypeError:
2124 2125 raise error.Abort(
2125 2126 b'changeset references must be full hexadecimal '
2126 2127 b'node identifiers'
2127 2128 )
2128 2129
2129 2130 if opts.get(b'delete'):
2130 2131 indices = []
2131 2132 for v in opts.get(b'delete'):
2132 2133 try:
2133 2134 indices.append(int(v))
2134 2135 except ValueError:
2135 2136 raise error.Abort(
2136 2137 _(b'invalid index value: %r') % v,
2137 2138 hint=_(b'use integers for indices'),
2138 2139 )
2139 2140
2140 2141 if repo.currenttransaction():
2141 2142 raise error.Abort(
2142 2143 _(b'cannot delete obsmarkers in the middle of transaction.')
2143 2144 )
2144 2145
2145 2146 with repo.lock():
2146 2147 n = repair.deleteobsmarkers(repo.obsstore, indices)
2147 2148 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2148 2149
2149 2150 return
2150 2151
2151 2152 if precursor is not None:
2152 2153 if opts[b'rev']:
2153 2154 raise error.Abort(b'cannot select revision when creating marker')
2154 2155 metadata = {}
2155 2156 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2156 2157 succs = tuple(parsenodeid(succ) for succ in successors)
2157 2158 l = repo.lock()
2158 2159 try:
2159 2160 tr = repo.transaction(b'debugobsolete')
2160 2161 try:
2161 2162 date = opts.get(b'date')
2162 2163 if date:
2163 2164 date = dateutil.parsedate(date)
2164 2165 else:
2165 2166 date = None
2166 2167 prec = parsenodeid(precursor)
2167 2168 parents = None
2168 2169 if opts[b'record_parents']:
2169 2170 if prec not in repo.unfiltered():
2170 2171 raise error.Abort(
2171 2172 b'cannot used --record-parents on '
2172 2173 b'unknown changesets'
2173 2174 )
2174 2175 parents = repo.unfiltered()[prec].parents()
2175 2176 parents = tuple(p.node() for p in parents)
2176 2177 repo.obsstore.create(
2177 2178 tr,
2178 2179 prec,
2179 2180 succs,
2180 2181 opts[b'flags'],
2181 2182 parents=parents,
2182 2183 date=date,
2183 2184 metadata=metadata,
2184 2185 ui=ui,
2185 2186 )
2186 2187 tr.close()
2187 2188 except ValueError as exc:
2188 2189 raise error.Abort(
2189 2190 _(b'bad obsmarker input: %s') % pycompat.bytestr(exc)
2190 2191 )
2191 2192 finally:
2192 2193 tr.release()
2193 2194 finally:
2194 2195 l.release()
2195 2196 else:
2196 2197 if opts[b'rev']:
2197 2198 revs = scmutil.revrange(repo, opts[b'rev'])
2198 2199 nodes = [repo[r].node() for r in revs]
2199 2200 markers = list(
2200 2201 obsutil.getmarkers(
2201 2202 repo, nodes=nodes, exclusive=opts[b'exclusive']
2202 2203 )
2203 2204 )
2204 2205 markers.sort(key=lambda x: x._data)
2205 2206 else:
2206 2207 markers = obsutil.getmarkers(repo)
2207 2208
2208 2209 markerstoiter = markers
2209 2210 isrelevant = lambda m: True
2210 2211 if opts.get(b'rev') and opts.get(b'index'):
2211 2212 markerstoiter = obsutil.getmarkers(repo)
2212 2213 markerset = set(markers)
2213 2214 isrelevant = lambda m: m in markerset
2214 2215
2215 2216 fm = ui.formatter(b'debugobsolete', opts)
2216 2217 for i, m in enumerate(markerstoiter):
2217 2218 if not isrelevant(m):
2218 2219 # marker can be irrelevant when we're iterating over a set
2219 2220 # of markers (markerstoiter) which is bigger than the set
2220 2221 # of markers we want to display (markers)
2221 2222 # this can happen if both --index and --rev options are
2222 2223 # provided and thus we need to iterate over all of the markers
2223 2224 # to get the correct indices, but only display the ones that
2224 2225 # are relevant to --rev value
2225 2226 continue
2226 2227 fm.startitem()
2227 2228 ind = i if opts.get(b'index') else None
2228 2229 cmdutil.showmarker(fm, m, index=ind)
2229 2230 fm.end()
2230 2231
2231 2232
2232 2233 @command(
2233 2234 b'debugp1copies',
2234 2235 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2235 2236 _(b'[-r REV]'),
2236 2237 )
2237 2238 def debugp1copies(ui, repo, **opts):
2238 2239 """dump copy information compared to p1"""
2239 2240
2240 2241 opts = pycompat.byteskwargs(opts)
2241 2242 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2242 2243 for dst, src in ctx.p1copies().items():
2243 2244 ui.write(b'%s -> %s\n' % (src, dst))
2244 2245
2245 2246
2246 2247 @command(
2247 2248 b'debugp2copies',
2248 2249 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2249 2250 _(b'[-r REV]'),
2250 2251 )
2251 2252 def debugp1copies(ui, repo, **opts):
2252 2253 """dump copy information compared to p2"""
2253 2254
2254 2255 opts = pycompat.byteskwargs(opts)
2255 2256 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2256 2257 for dst, src in ctx.p2copies().items():
2257 2258 ui.write(b'%s -> %s\n' % (src, dst))
2258 2259
2259 2260
2260 2261 @command(
2261 2262 b'debugpathcomplete',
2262 2263 [
2263 2264 (b'f', b'full', None, _(b'complete an entire path')),
2264 2265 (b'n', b'normal', None, _(b'show only normal files')),
2265 2266 (b'a', b'added', None, _(b'show only added files')),
2266 2267 (b'r', b'removed', None, _(b'show only removed files')),
2267 2268 ],
2268 2269 _(b'FILESPEC...'),
2269 2270 )
2270 2271 def debugpathcomplete(ui, repo, *specs, **opts):
2271 2272 '''complete part or all of a tracked path
2272 2273
2273 2274 This command supports shells that offer path name completion. It
2274 2275 currently completes only files already known to the dirstate.
2275 2276
2276 2277 Completion extends only to the next path segment unless
2277 2278 --full is specified, in which case entire paths are used.'''
2278 2279
2279 2280 def complete(path, acceptable):
2280 2281 dirstate = repo.dirstate
2281 2282 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2282 2283 rootdir = repo.root + pycompat.ossep
2283 2284 if spec != repo.root and not spec.startswith(rootdir):
2284 2285 return [], []
2285 2286 if os.path.isdir(spec):
2286 2287 spec += b'/'
2287 2288 spec = spec[len(rootdir) :]
2288 2289 fixpaths = pycompat.ossep != b'/'
2289 2290 if fixpaths:
2290 2291 spec = spec.replace(pycompat.ossep, b'/')
2291 2292 speclen = len(spec)
2292 2293 fullpaths = opts['full']
2293 2294 files, dirs = set(), set()
2294 2295 adddir, addfile = dirs.add, files.add
2295 2296 for f, st in pycompat.iteritems(dirstate):
2296 2297 if f.startswith(spec) and st[0] in acceptable:
2297 2298 if fixpaths:
2298 2299 f = f.replace(b'/', pycompat.ossep)
2299 2300 if fullpaths:
2300 2301 addfile(f)
2301 2302 continue
2302 2303 s = f.find(pycompat.ossep, speclen)
2303 2304 if s >= 0:
2304 2305 adddir(f[:s])
2305 2306 else:
2306 2307 addfile(f)
2307 2308 return files, dirs
2308 2309
2309 2310 acceptable = b''
2310 2311 if opts['normal']:
2311 2312 acceptable += b'nm'
2312 2313 if opts['added']:
2313 2314 acceptable += b'a'
2314 2315 if opts['removed']:
2315 2316 acceptable += b'r'
2316 2317 cwd = repo.getcwd()
2317 2318 if not specs:
2318 2319 specs = [b'.']
2319 2320
2320 2321 files, dirs = set(), set()
2321 2322 for spec in specs:
2322 2323 f, d = complete(spec, acceptable or b'nmar')
2323 2324 files.update(f)
2324 2325 dirs.update(d)
2325 2326 files.update(dirs)
2326 2327 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2327 2328 ui.write(b'\n')
2328 2329
2329 2330
2330 2331 @command(
2331 2332 b'debugpathcopies',
2332 2333 cmdutil.walkopts,
2333 2334 b'hg debugpathcopies REV1 REV2 [FILE]',
2334 2335 inferrepo=True,
2335 2336 )
2336 2337 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2337 2338 """show copies between two revisions"""
2338 2339 ctx1 = scmutil.revsingle(repo, rev1)
2339 2340 ctx2 = scmutil.revsingle(repo, rev2)
2340 2341 m = scmutil.match(ctx1, pats, opts)
2341 2342 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2342 2343 ui.write(b'%s -> %s\n' % (src, dst))
2343 2344
2344 2345
2345 2346 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2346 2347 def debugpeer(ui, path):
2347 2348 """establish a connection to a peer repository"""
2348 2349 # Always enable peer request logging. Requires --debug to display
2349 2350 # though.
2350 2351 overrides = {
2351 2352 (b'devel', b'debug.peer-request'): True,
2352 2353 }
2353 2354
2354 2355 with ui.configoverride(overrides):
2355 2356 peer = hg.peer(ui, {}, path)
2356 2357
2357 2358 local = peer.local() is not None
2358 2359 canpush = peer.canpush()
2359 2360
2360 2361 ui.write(_(b'url: %s\n') % peer.url())
2361 2362 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2362 2363 ui.write(_(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no')))
2363 2364
2364 2365
2365 2366 @command(
2366 2367 b'debugpickmergetool',
2367 2368 [
2368 2369 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2369 2370 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2370 2371 ]
2371 2372 + cmdutil.walkopts
2372 2373 + cmdutil.mergetoolopts,
2373 2374 _(b'[PATTERN]...'),
2374 2375 inferrepo=True,
2375 2376 )
2376 2377 def debugpickmergetool(ui, repo, *pats, **opts):
2377 2378 """examine which merge tool is chosen for specified file
2378 2379
2379 2380 As described in :hg:`help merge-tools`, Mercurial examines
2380 2381 configurations below in this order to decide which merge tool is
2381 2382 chosen for specified file.
2382 2383
2383 2384 1. ``--tool`` option
2384 2385 2. ``HGMERGE`` environment variable
2385 2386 3. configurations in ``merge-patterns`` section
2386 2387 4. configuration of ``ui.merge``
2387 2388 5. configurations in ``merge-tools`` section
2388 2389 6. ``hgmerge`` tool (for historical reason only)
2389 2390 7. default tool for fallback (``:merge`` or ``:prompt``)
2390 2391
2391 2392 This command writes out examination result in the style below::
2392 2393
2393 2394 FILE = MERGETOOL
2394 2395
2395 2396 By default, all files known in the first parent context of the
2396 2397 working directory are examined. Use file patterns and/or -I/-X
2397 2398 options to limit target files. -r/--rev is also useful to examine
2398 2399 files in another context without actual updating to it.
2399 2400
2400 2401 With --debug, this command shows warning messages while matching
2401 2402 against ``merge-patterns`` and so on, too. It is recommended to
2402 2403 use this option with explicit file patterns and/or -I/-X options,
2403 2404 because this option increases amount of output per file according
2404 2405 to configurations in hgrc.
2405 2406
2406 2407 With -v/--verbose, this command shows configurations below at
2407 2408 first (only if specified).
2408 2409
2409 2410 - ``--tool`` option
2410 2411 - ``HGMERGE`` environment variable
2411 2412 - configuration of ``ui.merge``
2412 2413
2413 2414 If merge tool is chosen before matching against
2414 2415 ``merge-patterns``, this command can't show any helpful
2415 2416 information, even with --debug. In such case, information above is
2416 2417 useful to know why a merge tool is chosen.
2417 2418 """
2418 2419 opts = pycompat.byteskwargs(opts)
2419 2420 overrides = {}
2420 2421 if opts[b'tool']:
2421 2422 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
2422 2423 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
2423 2424
2424 2425 with ui.configoverride(overrides, b'debugmergepatterns'):
2425 2426 hgmerge = encoding.environ.get(b"HGMERGE")
2426 2427 if hgmerge is not None:
2427 2428 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2428 2429 uimerge = ui.config(b"ui", b"merge")
2429 2430 if uimerge:
2430 2431 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2431 2432
2432 2433 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2433 2434 m = scmutil.match(ctx, pats, opts)
2434 2435 changedelete = opts[b'changedelete']
2435 2436 for path in ctx.walk(m):
2436 2437 fctx = ctx[path]
2437 2438 try:
2438 2439 if not ui.debugflag:
2439 2440 ui.pushbuffer(error=True)
2440 2441 tool, toolpath = filemerge._picktool(
2441 2442 repo,
2442 2443 ui,
2443 2444 path,
2444 2445 fctx.isbinary(),
2445 2446 b'l' in fctx.flags(),
2446 2447 changedelete,
2447 2448 )
2448 2449 finally:
2449 2450 if not ui.debugflag:
2450 2451 ui.popbuffer()
2451 2452 ui.write(b'%s = %s\n' % (path, tool))
2452 2453
2453 2454
2454 2455 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2455 2456 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2456 2457 '''access the pushkey key/value protocol
2457 2458
2458 2459 With two args, list the keys in the given namespace.
2459 2460
2460 2461 With five args, set a key to new if it currently is set to old.
2461 2462 Reports success or failure.
2462 2463 '''
2463 2464
2464 2465 target = hg.peer(ui, {}, repopath)
2465 2466 if keyinfo:
2466 2467 key, old, new = keyinfo
2467 2468 with target.commandexecutor() as e:
2468 2469 r = e.callcommand(
2469 2470 b'pushkey',
2470 2471 {
2471 2472 b'namespace': namespace,
2472 2473 b'key': key,
2473 2474 b'old': old,
2474 2475 b'new': new,
2475 2476 },
2476 2477 ).result()
2477 2478
2478 2479 ui.status(pycompat.bytestr(r) + b'\n')
2479 2480 return not r
2480 2481 else:
2481 2482 for k, v in sorted(pycompat.iteritems(target.listkeys(namespace))):
2482 2483 ui.write(
2483 2484 b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
2484 2485 )
2485 2486
2486 2487
2487 2488 @command(b'debugpvec', [], _(b'A B'))
2488 2489 def debugpvec(ui, repo, a, b=None):
2489 2490 ca = scmutil.revsingle(repo, a)
2490 2491 cb = scmutil.revsingle(repo, b)
2491 2492 pa = pvec.ctxpvec(ca)
2492 2493 pb = pvec.ctxpvec(cb)
2493 2494 if pa == pb:
2494 2495 rel = b"="
2495 2496 elif pa > pb:
2496 2497 rel = b">"
2497 2498 elif pa < pb:
2498 2499 rel = b"<"
2499 2500 elif pa | pb:
2500 2501 rel = b"|"
2501 2502 ui.write(_(b"a: %s\n") % pa)
2502 2503 ui.write(_(b"b: %s\n") % pb)
2503 2504 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2504 2505 ui.write(
2505 2506 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
2506 2507 % (
2507 2508 abs(pa._depth - pb._depth),
2508 2509 pvec._hamming(pa._vec, pb._vec),
2509 2510 pa.distance(pb),
2510 2511 rel,
2511 2512 )
2512 2513 )
2513 2514
2514 2515
2515 2516 @command(
2516 2517 b'debugrebuilddirstate|debugrebuildstate',
2517 2518 [
2518 2519 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
2519 2520 (
2520 2521 b'',
2521 2522 b'minimal',
2522 2523 None,
2523 2524 _(
2524 2525 b'only rebuild files that are inconsistent with '
2525 2526 b'the working copy parent'
2526 2527 ),
2527 2528 ),
2528 2529 ],
2529 2530 _(b'[-r REV]'),
2530 2531 )
2531 2532 def debugrebuilddirstate(ui, repo, rev, **opts):
2532 2533 """rebuild the dirstate as it would look like for the given revision
2533 2534
2534 2535 If no revision is specified the first current parent will be used.
2535 2536
2536 2537 The dirstate will be set to the files of the given revision.
2537 2538 The actual working directory content or existing dirstate
2538 2539 information such as adds or removes is not considered.
2539 2540
2540 2541 ``minimal`` will only rebuild the dirstate status for files that claim to be
2541 2542 tracked but are not in the parent manifest, or that exist in the parent
2542 2543 manifest but are not in the dirstate. It will not change adds, removes, or
2543 2544 modified files that are in the working copy parent.
2544 2545
2545 2546 One use of this command is to make the next :hg:`status` invocation
2546 2547 check the actual file content.
2547 2548 """
2548 2549 ctx = scmutil.revsingle(repo, rev)
2549 2550 with repo.wlock():
2550 2551 dirstate = repo.dirstate
2551 2552 changedfiles = None
2552 2553 # See command doc for what minimal does.
2553 2554 if opts.get('minimal'):
2554 2555 manifestfiles = set(ctx.manifest().keys())
2555 2556 dirstatefiles = set(dirstate)
2556 2557 manifestonly = manifestfiles - dirstatefiles
2557 2558 dsonly = dirstatefiles - manifestfiles
2558 2559 dsnotadded = set(f for f in dsonly if dirstate[f] != b'a')
2559 2560 changedfiles = manifestonly | dsnotadded
2560 2561
2561 2562 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2562 2563
2563 2564
2564 2565 @command(b'debugrebuildfncache', [], b'')
2565 2566 def debugrebuildfncache(ui, repo):
2566 2567 """rebuild the fncache file"""
2567 2568 repair.rebuildfncache(ui, repo)
2568 2569
2569 2570
2570 2571 @command(
2571 2572 b'debugrename',
2572 2573 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2573 2574 _(b'[-r REV] [FILE]...'),
2574 2575 )
2575 2576 def debugrename(ui, repo, *pats, **opts):
2576 2577 """dump rename information"""
2577 2578
2578 2579 opts = pycompat.byteskwargs(opts)
2579 2580 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
2580 2581 m = scmutil.match(ctx, pats, opts)
2581 2582 for abs in ctx.walk(m):
2582 2583 fctx = ctx[abs]
2583 2584 o = fctx.filelog().renamed(fctx.filenode())
2584 2585 rel = repo.pathto(abs)
2585 2586 if o:
2586 2587 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2587 2588 else:
2588 2589 ui.write(_(b"%s not renamed\n") % rel)
2589 2590
2590 2591
2591 2592 @command(
2592 2593 b'debugrevlog',
2593 2594 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
2594 2595 _(b'-c|-m|FILE'),
2595 2596 optionalrepo=True,
2596 2597 )
2597 2598 def debugrevlog(ui, repo, file_=None, **opts):
2598 2599 """show data and statistics about a revlog"""
2599 2600 opts = pycompat.byteskwargs(opts)
2600 2601 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
2601 2602
2602 2603 if opts.get(b"dump"):
2603 2604 numrevs = len(r)
2604 2605 ui.write(
2605 2606 (
2606 2607 b"# rev p1rev p2rev start end deltastart base p1 p2"
2607 2608 b" rawsize totalsize compression heads chainlen\n"
2608 2609 )
2609 2610 )
2610 2611 ts = 0
2611 2612 heads = set()
2612 2613
2613 2614 for rev in pycompat.xrange(numrevs):
2614 2615 dbase = r.deltaparent(rev)
2615 2616 if dbase == -1:
2616 2617 dbase = rev
2617 2618 cbase = r.chainbase(rev)
2618 2619 clen = r.chainlen(rev)
2619 2620 p1, p2 = r.parentrevs(rev)
2620 2621 rs = r.rawsize(rev)
2621 2622 ts = ts + rs
2622 2623 heads -= set(r.parentrevs(rev))
2623 2624 heads.add(rev)
2624 2625 try:
2625 2626 compression = ts / r.end(rev)
2626 2627 except ZeroDivisionError:
2627 2628 compression = 0
2628 2629 ui.write(
2629 2630 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2630 2631 b"%11d %5d %8d\n"
2631 2632 % (
2632 2633 rev,
2633 2634 p1,
2634 2635 p2,
2635 2636 r.start(rev),
2636 2637 r.end(rev),
2637 2638 r.start(dbase),
2638 2639 r.start(cbase),
2639 2640 r.start(p1),
2640 2641 r.start(p2),
2641 2642 rs,
2642 2643 ts,
2643 2644 compression,
2644 2645 len(heads),
2645 2646 clen,
2646 2647 )
2647 2648 )
2648 2649 return 0
2649 2650
2650 2651 v = r.version
2651 2652 format = v & 0xFFFF
2652 2653 flags = []
2653 2654 gdelta = False
2654 2655 if v & revlog.FLAG_INLINE_DATA:
2655 2656 flags.append(b'inline')
2656 2657 if v & revlog.FLAG_GENERALDELTA:
2657 2658 gdelta = True
2658 2659 flags.append(b'generaldelta')
2659 2660 if not flags:
2660 2661 flags = [b'(none)']
2661 2662
2662 2663 ### tracks merge vs single parent
2663 2664 nummerges = 0
2664 2665
2665 2666 ### tracks ways the "delta" are build
2666 2667 # nodelta
2667 2668 numempty = 0
2668 2669 numemptytext = 0
2669 2670 numemptydelta = 0
2670 2671 # full file content
2671 2672 numfull = 0
2672 2673 # intermediate snapshot against a prior snapshot
2673 2674 numsemi = 0
2674 2675 # snapshot count per depth
2675 2676 numsnapdepth = collections.defaultdict(lambda: 0)
2676 2677 # delta against previous revision
2677 2678 numprev = 0
2678 2679 # delta against first or second parent (not prev)
2679 2680 nump1 = 0
2680 2681 nump2 = 0
2681 2682 # delta against neither prev nor parents
2682 2683 numother = 0
2683 2684 # delta against prev that are also first or second parent
2684 2685 # (details of `numprev`)
2685 2686 nump1prev = 0
2686 2687 nump2prev = 0
2687 2688
2688 2689 # data about delta chain of each revs
2689 2690 chainlengths = []
2690 2691 chainbases = []
2691 2692 chainspans = []
2692 2693
2693 2694 # data about each revision
2694 2695 datasize = [None, 0, 0]
2695 2696 fullsize = [None, 0, 0]
2696 2697 semisize = [None, 0, 0]
2697 2698 # snapshot count per depth
2698 2699 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2699 2700 deltasize = [None, 0, 0]
2700 2701 chunktypecounts = {}
2701 2702 chunktypesizes = {}
2702 2703
2703 2704 def addsize(size, l):
2704 2705 if l[0] is None or size < l[0]:
2705 2706 l[0] = size
2706 2707 if size > l[1]:
2707 2708 l[1] = size
2708 2709 l[2] += size
2709 2710
2710 2711 numrevs = len(r)
2711 2712 for rev in pycompat.xrange(numrevs):
2712 2713 p1, p2 = r.parentrevs(rev)
2713 2714 delta = r.deltaparent(rev)
2714 2715 if format > 0:
2715 2716 addsize(r.rawsize(rev), datasize)
2716 2717 if p2 != nullrev:
2717 2718 nummerges += 1
2718 2719 size = r.length(rev)
2719 2720 if delta == nullrev:
2720 2721 chainlengths.append(0)
2721 2722 chainbases.append(r.start(rev))
2722 2723 chainspans.append(size)
2723 2724 if size == 0:
2724 2725 numempty += 1
2725 2726 numemptytext += 1
2726 2727 else:
2727 2728 numfull += 1
2728 2729 numsnapdepth[0] += 1
2729 2730 addsize(size, fullsize)
2730 2731 addsize(size, snapsizedepth[0])
2731 2732 else:
2732 2733 chainlengths.append(chainlengths[delta] + 1)
2733 2734 baseaddr = chainbases[delta]
2734 2735 revaddr = r.start(rev)
2735 2736 chainbases.append(baseaddr)
2736 2737 chainspans.append((revaddr - baseaddr) + size)
2737 2738 if size == 0:
2738 2739 numempty += 1
2739 2740 numemptydelta += 1
2740 2741 elif r.issnapshot(rev):
2741 2742 addsize(size, semisize)
2742 2743 numsemi += 1
2743 2744 depth = r.snapshotdepth(rev)
2744 2745 numsnapdepth[depth] += 1
2745 2746 addsize(size, snapsizedepth[depth])
2746 2747 else:
2747 2748 addsize(size, deltasize)
2748 2749 if delta == rev - 1:
2749 2750 numprev += 1
2750 2751 if delta == p1:
2751 2752 nump1prev += 1
2752 2753 elif delta == p2:
2753 2754 nump2prev += 1
2754 2755 elif delta == p1:
2755 2756 nump1 += 1
2756 2757 elif delta == p2:
2757 2758 nump2 += 1
2758 2759 elif delta != nullrev:
2759 2760 numother += 1
2760 2761
2761 2762 # Obtain data on the raw chunks in the revlog.
2762 2763 if util.safehasattr(r, b'_getsegmentforrevs'):
2763 2764 segment = r._getsegmentforrevs(rev, rev)[1]
2764 2765 else:
2765 2766 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
2766 2767 if segment:
2767 2768 chunktype = bytes(segment[0:1])
2768 2769 else:
2769 2770 chunktype = b'empty'
2770 2771
2771 2772 if chunktype not in chunktypecounts:
2772 2773 chunktypecounts[chunktype] = 0
2773 2774 chunktypesizes[chunktype] = 0
2774 2775
2775 2776 chunktypecounts[chunktype] += 1
2776 2777 chunktypesizes[chunktype] += size
2777 2778
2778 2779 # Adjust size min value for empty cases
2779 2780 for size in (datasize, fullsize, semisize, deltasize):
2780 2781 if size[0] is None:
2781 2782 size[0] = 0
2782 2783
2783 2784 numdeltas = numrevs - numfull - numempty - numsemi
2784 2785 numoprev = numprev - nump1prev - nump2prev
2785 2786 totalrawsize = datasize[2]
2786 2787 datasize[2] /= numrevs
2787 2788 fulltotal = fullsize[2]
2788 2789 if numfull == 0:
2789 2790 fullsize[2] = 0
2790 2791 else:
2791 2792 fullsize[2] /= numfull
2792 2793 semitotal = semisize[2]
2793 2794 snaptotal = {}
2794 2795 if numsemi > 0:
2795 2796 semisize[2] /= numsemi
2796 2797 for depth in snapsizedepth:
2797 2798 snaptotal[depth] = snapsizedepth[depth][2]
2798 2799 snapsizedepth[depth][2] /= numsnapdepth[depth]
2799 2800
2800 2801 deltatotal = deltasize[2]
2801 2802 if numdeltas > 0:
2802 2803 deltasize[2] /= numdeltas
2803 2804 totalsize = fulltotal + semitotal + deltatotal
2804 2805 avgchainlen = sum(chainlengths) / numrevs
2805 2806 maxchainlen = max(chainlengths)
2806 2807 maxchainspan = max(chainspans)
2807 2808 compratio = 1
2808 2809 if totalsize:
2809 2810 compratio = totalrawsize / totalsize
2810 2811
2811 2812 basedfmtstr = b'%%%dd\n'
2812 2813 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
2813 2814
2814 2815 def dfmtstr(max):
2815 2816 return basedfmtstr % len(str(max))
2816 2817
2817 2818 def pcfmtstr(max, padding=0):
2818 2819 return basepcfmtstr % (len(str(max)), b' ' * padding)
2819 2820
2820 2821 def pcfmt(value, total):
2821 2822 if total:
2822 2823 return (value, 100 * float(value) / total)
2823 2824 else:
2824 2825 return value, 100.0
2825 2826
2826 2827 ui.writenoi18n(b'format : %d\n' % format)
2827 2828 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
2828 2829
2829 2830 ui.write(b'\n')
2830 2831 fmt = pcfmtstr(totalsize)
2831 2832 fmt2 = dfmtstr(totalsize)
2832 2833 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
2833 2834 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
2834 2835 ui.writenoi18n(
2835 2836 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
2836 2837 )
2837 2838 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
2838 2839 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
2839 2840 ui.writenoi18n(
2840 2841 b' text : '
2841 2842 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
2842 2843 )
2843 2844 ui.writenoi18n(
2844 2845 b' delta : '
2845 2846 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
2846 2847 )
2847 2848 ui.writenoi18n(
2848 2849 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
2849 2850 )
2850 2851 for depth in sorted(numsnapdepth):
2851 2852 ui.write(
2852 2853 (b' lvl-%-3d : ' % depth)
2853 2854 + fmt % pcfmt(numsnapdepth[depth], numrevs)
2854 2855 )
2855 2856 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2856 2857 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
2857 2858 ui.writenoi18n(
2858 2859 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
2859 2860 )
2860 2861 for depth in sorted(numsnapdepth):
2861 2862 ui.write(
2862 2863 (b' lvl-%-3d : ' % depth)
2863 2864 + fmt % pcfmt(snaptotal[depth], totalsize)
2864 2865 )
2865 2866 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2866 2867
2867 2868 def fmtchunktype(chunktype):
2868 2869 if chunktype == b'empty':
2869 2870 return b' %s : ' % chunktype
2870 2871 elif chunktype in pycompat.bytestr(string.ascii_letters):
2871 2872 return b' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2872 2873 else:
2873 2874 return b' 0x%s : ' % hex(chunktype)
2874 2875
2875 2876 ui.write(b'\n')
2876 2877 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
2877 2878 for chunktype in sorted(chunktypecounts):
2878 2879 ui.write(fmtchunktype(chunktype))
2879 2880 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2880 2881 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
2881 2882 for chunktype in sorted(chunktypecounts):
2882 2883 ui.write(fmtchunktype(chunktype))
2883 2884 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2884 2885
2885 2886 ui.write(b'\n')
2886 2887 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2887 2888 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
2888 2889 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
2889 2890 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
2890 2891 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
2891 2892
2892 2893 if format > 0:
2893 2894 ui.write(b'\n')
2894 2895 ui.writenoi18n(
2895 2896 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
2896 2897 % tuple(datasize)
2897 2898 )
2898 2899 ui.writenoi18n(
2899 2900 b'full revision size (min/max/avg) : %d / %d / %d\n'
2900 2901 % tuple(fullsize)
2901 2902 )
2902 2903 ui.writenoi18n(
2903 2904 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
2904 2905 % tuple(semisize)
2905 2906 )
2906 2907 for depth in sorted(snapsizedepth):
2907 2908 if depth == 0:
2908 2909 continue
2909 2910 ui.writenoi18n(
2910 2911 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
2911 2912 % ((depth,) + tuple(snapsizedepth[depth]))
2912 2913 )
2913 2914 ui.writenoi18n(
2914 2915 b'delta size (min/max/avg) : %d / %d / %d\n'
2915 2916 % tuple(deltasize)
2916 2917 )
2917 2918
2918 2919 if numdeltas > 0:
2919 2920 ui.write(b'\n')
2920 2921 fmt = pcfmtstr(numdeltas)
2921 2922 fmt2 = pcfmtstr(numdeltas, 4)
2922 2923 ui.writenoi18n(
2923 2924 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
2924 2925 )
2925 2926 if numprev > 0:
2926 2927 ui.writenoi18n(
2927 2928 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
2928 2929 )
2929 2930 ui.writenoi18n(
2930 2931 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
2931 2932 )
2932 2933 ui.writenoi18n(
2933 2934 b' other : ' + fmt2 % pcfmt(numoprev, numprev)
2934 2935 )
2935 2936 if gdelta:
2936 2937 ui.writenoi18n(
2937 2938 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
2938 2939 )
2939 2940 ui.writenoi18n(
2940 2941 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
2941 2942 )
2942 2943 ui.writenoi18n(
2943 2944 b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
2944 2945 )
2945 2946
2946 2947
2947 2948 @command(
2948 2949 b'debugrevlogindex',
2949 2950 cmdutil.debugrevlogopts
2950 2951 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
2951 2952 _(b'[-f FORMAT] -c|-m|FILE'),
2952 2953 optionalrepo=True,
2953 2954 )
2954 2955 def debugrevlogindex(ui, repo, file_=None, **opts):
2955 2956 """dump the contents of a revlog index"""
2956 2957 opts = pycompat.byteskwargs(opts)
2957 2958 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
2958 2959 format = opts.get(b'format', 0)
2959 2960 if format not in (0, 1):
2960 2961 raise error.Abort(_(b"unknown format %d") % format)
2961 2962
2962 2963 if ui.debugflag:
2963 2964 shortfn = hex
2964 2965 else:
2965 2966 shortfn = short
2966 2967
2967 2968 # There might not be anything in r, so have a sane default
2968 2969 idlen = 12
2969 2970 for i in r:
2970 2971 idlen = len(shortfn(r.node(i)))
2971 2972 break
2972 2973
2973 2974 if format == 0:
2974 2975 if ui.verbose:
2975 2976 ui.writenoi18n(
2976 2977 b" rev offset length linkrev %s %s p2\n"
2977 2978 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
2978 2979 )
2979 2980 else:
2980 2981 ui.writenoi18n(
2981 2982 b" rev linkrev %s %s p2\n"
2982 2983 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
2983 2984 )
2984 2985 elif format == 1:
2985 2986 if ui.verbose:
2986 2987 ui.writenoi18n(
2987 2988 (
2988 2989 b" rev flag offset length size link p1"
2989 2990 b" p2 %s\n"
2990 2991 )
2991 2992 % b"nodeid".rjust(idlen)
2992 2993 )
2993 2994 else:
2994 2995 ui.writenoi18n(
2995 2996 b" rev flag size link p1 p2 %s\n"
2996 2997 % b"nodeid".rjust(idlen)
2997 2998 )
2998 2999
2999 3000 for i in r:
3000 3001 node = r.node(i)
3001 3002 if format == 0:
3002 3003 try:
3003 3004 pp = r.parents(node)
3004 3005 except Exception:
3005 3006 pp = [nullid, nullid]
3006 3007 if ui.verbose:
3007 3008 ui.write(
3008 3009 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3009 3010 % (
3010 3011 i,
3011 3012 r.start(i),
3012 3013 r.length(i),
3013 3014 r.linkrev(i),
3014 3015 shortfn(node),
3015 3016 shortfn(pp[0]),
3016 3017 shortfn(pp[1]),
3017 3018 )
3018 3019 )
3019 3020 else:
3020 3021 ui.write(
3021 3022 b"% 6d % 7d %s %s %s\n"
3022 3023 % (
3023 3024 i,
3024 3025 r.linkrev(i),
3025 3026 shortfn(node),
3026 3027 shortfn(pp[0]),
3027 3028 shortfn(pp[1]),
3028 3029 )
3029 3030 )
3030 3031 elif format == 1:
3031 3032 pr = r.parentrevs(i)
3032 3033 if ui.verbose:
3033 3034 ui.write(
3034 3035 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3035 3036 % (
3036 3037 i,
3037 3038 r.flags(i),
3038 3039 r.start(i),
3039 3040 r.length(i),
3040 3041 r.rawsize(i),
3041 3042 r.linkrev(i),
3042 3043 pr[0],
3043 3044 pr[1],
3044 3045 shortfn(node),
3045 3046 )
3046 3047 )
3047 3048 else:
3048 3049 ui.write(
3049 3050 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3050 3051 % (
3051 3052 i,
3052 3053 r.flags(i),
3053 3054 r.rawsize(i),
3054 3055 r.linkrev(i),
3055 3056 pr[0],
3056 3057 pr[1],
3057 3058 shortfn(node),
3058 3059 )
3059 3060 )
3060 3061
3061 3062
3062 3063 @command(
3063 3064 b'debugrevspec',
3064 3065 [
3065 3066 (
3066 3067 b'',
3067 3068 b'optimize',
3068 3069 None,
3069 3070 _(b'print parsed tree after optimizing (DEPRECATED)'),
3070 3071 ),
3071 3072 (
3072 3073 b'',
3073 3074 b'show-revs',
3074 3075 True,
3075 3076 _(b'print list of result revisions (default)'),
3076 3077 ),
3077 3078 (
3078 3079 b's',
3079 3080 b'show-set',
3080 3081 None,
3081 3082 _(b'print internal representation of result set'),
3082 3083 ),
3083 3084 (
3084 3085 b'p',
3085 3086 b'show-stage',
3086 3087 [],
3087 3088 _(b'print parsed tree at the given stage'),
3088 3089 _(b'NAME'),
3089 3090 ),
3090 3091 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3091 3092 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3092 3093 ],
3093 3094 b'REVSPEC',
3094 3095 )
3095 3096 def debugrevspec(ui, repo, expr, **opts):
3096 3097 """parse and apply a revision specification
3097 3098
3098 3099 Use -p/--show-stage option to print the parsed tree at the given stages.
3099 3100 Use -p all to print tree at every stage.
3100 3101
3101 3102 Use --no-show-revs option with -s or -p to print only the set
3102 3103 representation or the parsed tree respectively.
3103 3104
3104 3105 Use --verify-optimized to compare the optimized result with the unoptimized
3105 3106 one. Returns 1 if the optimized result differs.
3106 3107 """
3107 3108 opts = pycompat.byteskwargs(opts)
3108 3109 aliases = ui.configitems(b'revsetalias')
3109 3110 stages = [
3110 3111 (b'parsed', lambda tree: tree),
3111 3112 (
3112 3113 b'expanded',
3113 3114 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3114 3115 ),
3115 3116 (b'concatenated', revsetlang.foldconcat),
3116 3117 (b'analyzed', revsetlang.analyze),
3117 3118 (b'optimized', revsetlang.optimize),
3118 3119 ]
3119 3120 if opts[b'no_optimized']:
3120 3121 stages = stages[:-1]
3121 3122 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3122 3123 raise error.Abort(
3123 3124 _(b'cannot use --verify-optimized with --no-optimized')
3124 3125 )
3125 3126 stagenames = set(n for n, f in stages)
3126 3127
3127 3128 showalways = set()
3128 3129 showchanged = set()
3129 3130 if ui.verbose and not opts[b'show_stage']:
3130 3131 # show parsed tree by --verbose (deprecated)
3131 3132 showalways.add(b'parsed')
3132 3133 showchanged.update([b'expanded', b'concatenated'])
3133 3134 if opts[b'optimize']:
3134 3135 showalways.add(b'optimized')
3135 3136 if opts[b'show_stage'] and opts[b'optimize']:
3136 3137 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3137 3138 if opts[b'show_stage'] == [b'all']:
3138 3139 showalways.update(stagenames)
3139 3140 else:
3140 3141 for n in opts[b'show_stage']:
3141 3142 if n not in stagenames:
3142 3143 raise error.Abort(_(b'invalid stage name: %s') % n)
3143 3144 showalways.update(opts[b'show_stage'])
3144 3145
3145 3146 treebystage = {}
3146 3147 printedtree = None
3147 3148 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3148 3149 for n, f in stages:
3149 3150 treebystage[n] = tree = f(tree)
3150 3151 if n in showalways or (n in showchanged and tree != printedtree):
3151 3152 if opts[b'show_stage'] or n != b'parsed':
3152 3153 ui.write(b"* %s:\n" % n)
3153 3154 ui.write(revsetlang.prettyformat(tree), b"\n")
3154 3155 printedtree = tree
3155 3156
3156 3157 if opts[b'verify_optimized']:
3157 3158 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3158 3159 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3159 3160 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3160 3161 ui.writenoi18n(
3161 3162 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3162 3163 )
3163 3164 ui.writenoi18n(
3164 3165 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3165 3166 )
3166 3167 arevs = list(arevs)
3167 3168 brevs = list(brevs)
3168 3169 if arevs == brevs:
3169 3170 return 0
3170 3171 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3171 3172 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3172 3173 sm = difflib.SequenceMatcher(None, arevs, brevs)
3173 3174 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3174 3175 if tag in ('delete', 'replace'):
3175 3176 for c in arevs[alo:ahi]:
3176 3177 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3177 3178 if tag in ('insert', 'replace'):
3178 3179 for c in brevs[blo:bhi]:
3179 3180 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3180 3181 if tag == 'equal':
3181 3182 for c in arevs[alo:ahi]:
3182 3183 ui.write(b' %d\n' % c)
3183 3184 return 1
3184 3185
3185 3186 func = revset.makematcher(tree)
3186 3187 revs = func(repo)
3187 3188 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3188 3189 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3189 3190 if not opts[b'show_revs']:
3190 3191 return
3191 3192 for c in revs:
3192 3193 ui.write(b"%d\n" % c)
3193 3194
3194 3195
3195 3196 @command(
3196 3197 b'debugserve',
3197 3198 [
3198 3199 (
3199 3200 b'',
3200 3201 b'sshstdio',
3201 3202 False,
3202 3203 _(b'run an SSH server bound to process handles'),
3203 3204 ),
3204 3205 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3205 3206 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3206 3207 ],
3207 3208 b'',
3208 3209 )
3209 3210 def debugserve(ui, repo, **opts):
3210 3211 """run a server with advanced settings
3211 3212
3212 3213 This command is similar to :hg:`serve`. It exists partially as a
3213 3214 workaround to the fact that ``hg serve --stdio`` must have specific
3214 3215 arguments for security reasons.
3215 3216 """
3216 3217 opts = pycompat.byteskwargs(opts)
3217 3218
3218 3219 if not opts[b'sshstdio']:
3219 3220 raise error.Abort(_(b'only --sshstdio is currently supported'))
3220 3221
3221 3222 logfh = None
3222 3223
3223 3224 if opts[b'logiofd'] and opts[b'logiofile']:
3224 3225 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3225 3226
3226 3227 if opts[b'logiofd']:
3227 3228 # Ideally we would be line buffered. But line buffering in binary
3228 3229 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3229 3230 # buffering could have performance impacts. But since this isn't
3230 3231 # performance critical code, it should be fine.
3231 3232 try:
3232 3233 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3233 3234 except OSError as e:
3234 3235 if e.errno != errno.ESPIPE:
3235 3236 raise
3236 3237 # can't seek a pipe, so `ab` mode fails on py3
3237 3238 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3238 3239 elif opts[b'logiofile']:
3239 3240 logfh = open(opts[b'logiofile'], b'ab', 0)
3240 3241
3241 3242 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3242 3243 s.serve_forever()
3243 3244
3244 3245
3245 3246 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3246 3247 def debugsetparents(ui, repo, rev1, rev2=None):
3247 3248 """manually set the parents of the current working directory
3248 3249
3249 3250 This is useful for writing repository conversion tools, but should
3250 3251 be used with care. For example, neither the working directory nor the
3251 3252 dirstate is updated, so file status may be incorrect after running this
3252 3253 command.
3253 3254
3254 3255 Returns 0 on success.
3255 3256 """
3256 3257
3257 3258 node1 = scmutil.revsingle(repo, rev1).node()
3258 3259 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3259 3260
3260 3261 with repo.wlock():
3261 3262 repo.setparents(node1, node2)
3262 3263
3263 3264
3264 3265 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3265 3266 def debugsidedata(ui, repo, file_, rev=None, **opts):
3266 3267 """dump the side data for a cl/manifest/file revision
3267 3268
3268 3269 Use --verbose to dump the sidedata content."""
3269 3270 opts = pycompat.byteskwargs(opts)
3270 3271 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3271 3272 if rev is not None:
3272 3273 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3273 3274 file_, rev = None, file_
3274 3275 elif rev is None:
3275 3276 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3276 3277 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3277 3278 r = getattr(r, '_revlog', r)
3278 3279 try:
3279 3280 sidedata = r.sidedata(r.lookup(rev))
3280 3281 except KeyError:
3281 3282 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3282 3283 if sidedata:
3283 3284 sidedata = list(sidedata.items())
3284 3285 sidedata.sort()
3285 3286 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3286 3287 for key, value in sidedata:
3287 3288 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3288 3289 if ui.verbose:
3289 3290 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3290 3291
3291 3292
3292 3293 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3293 3294 def debugssl(ui, repo, source=None, **opts):
3294 3295 '''test a secure connection to a server
3295 3296
3296 3297 This builds the certificate chain for the server on Windows, installing the
3297 3298 missing intermediates and trusted root via Windows Update if necessary. It
3298 3299 does nothing on other platforms.
3299 3300
3300 3301 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3301 3302 that server is used. See :hg:`help urls` for more information.
3302 3303
3303 3304 If the update succeeds, retry the original operation. Otherwise, the cause
3304 3305 of the SSL error is likely another issue.
3305 3306 '''
3306 3307 if not pycompat.iswindows:
3307 3308 raise error.Abort(
3308 3309 _(b'certificate chain building is only possible on Windows')
3309 3310 )
3310 3311
3311 3312 if not source:
3312 3313 if not repo:
3313 3314 raise error.Abort(
3314 3315 _(
3315 3316 b"there is no Mercurial repository here, and no "
3316 3317 b"server specified"
3317 3318 )
3318 3319 )
3319 3320 source = b"default"
3320 3321
3321 3322 source, branches = hg.parseurl(ui.expandpath(source))
3322 3323 url = util.url(source)
3323 3324
3324 3325 defaultport = {b'https': 443, b'ssh': 22}
3325 3326 if url.scheme in defaultport:
3326 3327 try:
3327 3328 addr = (url.host, int(url.port or defaultport[url.scheme]))
3328 3329 except ValueError:
3329 3330 raise error.Abort(_(b"malformed port number in URL"))
3330 3331 else:
3331 3332 raise error.Abort(_(b"only https and ssh connections are supported"))
3332 3333
3333 3334 from . import win32
3334 3335
3335 3336 s = ssl.wrap_socket(
3336 3337 socket.socket(),
3337 3338 ssl_version=ssl.PROTOCOL_TLS,
3338 3339 cert_reqs=ssl.CERT_NONE,
3339 3340 ca_certs=None,
3340 3341 )
3341 3342
3342 3343 try:
3343 3344 s.connect(addr)
3344 3345 cert = s.getpeercert(True)
3345 3346
3346 3347 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3347 3348
3348 3349 complete = win32.checkcertificatechain(cert, build=False)
3349 3350
3350 3351 if not complete:
3351 3352 ui.status(_(b'certificate chain is incomplete, updating... '))
3352 3353
3353 3354 if not win32.checkcertificatechain(cert):
3354 3355 ui.status(_(b'failed.\n'))
3355 3356 else:
3356 3357 ui.status(_(b'done.\n'))
3357 3358 else:
3358 3359 ui.status(_(b'full certificate chain is available\n'))
3359 3360 finally:
3360 3361 s.close()
3361 3362
3362 3363
3363 3364 @command(
3364 3365 b'debugsub',
3365 3366 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3366 3367 _(b'[-r REV] [REV]'),
3367 3368 )
3368 3369 def debugsub(ui, repo, rev=None):
3369 3370 ctx = scmutil.revsingle(repo, rev, None)
3370 3371 for k, v in sorted(ctx.substate.items()):
3371 3372 ui.writenoi18n(b'path %s\n' % k)
3372 3373 ui.writenoi18n(b' source %s\n' % v[0])
3373 3374 ui.writenoi18n(b' revision %s\n' % v[1])
3374 3375
3375 3376
3376 3377 @command(
3377 3378 b'debugsuccessorssets',
3378 3379 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3379 3380 _(b'[REV]'),
3380 3381 )
3381 3382 def debugsuccessorssets(ui, repo, *revs, **opts):
3382 3383 """show set of successors for revision
3383 3384
3384 3385 A successors set of changeset A is a consistent group of revisions that
3385 3386 succeed A. It contains non-obsolete changesets only unless closests
3386 3387 successors set is set.
3387 3388
3388 3389 In most cases a changeset A has a single successors set containing a single
3389 3390 successor (changeset A replaced by A').
3390 3391
3391 3392 A changeset that is made obsolete with no successors are called "pruned".
3392 3393 Such changesets have no successors sets at all.
3393 3394
3394 3395 A changeset that has been "split" will have a successors set containing
3395 3396 more than one successor.
3396 3397
3397 3398 A changeset that has been rewritten in multiple different ways is called
3398 3399 "divergent". Such changesets have multiple successor sets (each of which
3399 3400 may also be split, i.e. have multiple successors).
3400 3401
3401 3402 Results are displayed as follows::
3402 3403
3403 3404 <rev1>
3404 3405 <successors-1A>
3405 3406 <rev2>
3406 3407 <successors-2A>
3407 3408 <successors-2B1> <successors-2B2> <successors-2B3>
3408 3409
3409 3410 Here rev2 has two possible (i.e. divergent) successors sets. The first
3410 3411 holds one element, whereas the second holds three (i.e. the changeset has
3411 3412 been split).
3412 3413 """
3413 3414 # passed to successorssets caching computation from one call to another
3414 3415 cache = {}
3415 3416 ctx2str = bytes
3416 3417 node2str = short
3417 3418 for rev in scmutil.revrange(repo, revs):
3418 3419 ctx = repo[rev]
3419 3420 ui.write(b'%s\n' % ctx2str(ctx))
3420 3421 for succsset in obsutil.successorssets(
3421 3422 repo, ctx.node(), closest=opts['closest'], cache=cache
3422 3423 ):
3423 3424 if succsset:
3424 3425 ui.write(b' ')
3425 3426 ui.write(node2str(succsset[0]))
3426 3427 for node in succsset[1:]:
3427 3428 ui.write(b' ')
3428 3429 ui.write(node2str(node))
3429 3430 ui.write(b'\n')
3430 3431
3432 @command(b'debugtagscache', [])
3433 def debugtagscache(ui, repo):
3434 """display the contents of .hg/cache/hgtagsfnodes1"""
3435 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3436 for r in repo:
3437 node = repo[r].node()
3438 tagsnode = cache.getfnode(node, computemissing=False)
3439 tagsnodedisplay = hex(tagsnode) if tagsnode else 'missing/invalid'
3440 ui.write(b'%s %s %s\n' % (r, hex(node), tagsnodedisplay))
3431 3441
3432 3442 @command(
3433 3443 b'debugtemplate',
3434 3444 [
3435 3445 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3436 3446 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3437 3447 ],
3438 3448 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3439 3449 optionalrepo=True,
3440 3450 )
3441 3451 def debugtemplate(ui, repo, tmpl, **opts):
3442 3452 """parse and apply a template
3443 3453
3444 3454 If -r/--rev is given, the template is processed as a log template and
3445 3455 applied to the given changesets. Otherwise, it is processed as a generic
3446 3456 template.
3447 3457
3448 3458 Use --verbose to print the parsed tree.
3449 3459 """
3450 3460 revs = None
3451 3461 if opts['rev']:
3452 3462 if repo is None:
3453 3463 raise error.RepoError(
3454 3464 _(b'there is no Mercurial repository here (.hg not found)')
3455 3465 )
3456 3466 revs = scmutil.revrange(repo, opts['rev'])
3457 3467
3458 3468 props = {}
3459 3469 for d in opts['define']:
3460 3470 try:
3461 3471 k, v = (e.strip() for e in d.split(b'=', 1))
3462 3472 if not k or k == b'ui':
3463 3473 raise ValueError
3464 3474 props[k] = v
3465 3475 except ValueError:
3466 3476 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3467 3477
3468 3478 if ui.verbose:
3469 3479 aliases = ui.configitems(b'templatealias')
3470 3480 tree = templater.parse(tmpl)
3471 3481 ui.note(templater.prettyformat(tree), b'\n')
3472 3482 newtree = templater.expandaliases(tree, aliases)
3473 3483 if newtree != tree:
3474 3484 ui.notenoi18n(
3475 3485 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3476 3486 )
3477 3487
3478 3488 if revs is None:
3479 3489 tres = formatter.templateresources(ui, repo)
3480 3490 t = formatter.maketemplater(ui, tmpl, resources=tres)
3481 3491 if ui.verbose:
3482 3492 kwds, funcs = t.symbolsuseddefault()
3483 3493 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3484 3494 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3485 3495 ui.write(t.renderdefault(props))
3486 3496 else:
3487 3497 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3488 3498 if ui.verbose:
3489 3499 kwds, funcs = displayer.t.symbolsuseddefault()
3490 3500 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3491 3501 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3492 3502 for r in revs:
3493 3503 displayer.show(repo[r], **pycompat.strkwargs(props))
3494 3504 displayer.close()
3495 3505
3496 3506
3497 3507 @command(
3498 3508 b'debuguigetpass',
3499 3509 [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),],
3500 3510 _(b'[-p TEXT]'),
3501 3511 norepo=True,
3502 3512 )
3503 3513 def debuguigetpass(ui, prompt=b''):
3504 3514 """show prompt to type password"""
3505 3515 r = ui.getpass(prompt)
3506 3516 ui.writenoi18n(b'respose: %s\n' % r)
3507 3517
3508 3518
3509 3519 @command(
3510 3520 b'debuguiprompt',
3511 3521 [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),],
3512 3522 _(b'[-p TEXT]'),
3513 3523 norepo=True,
3514 3524 )
3515 3525 def debuguiprompt(ui, prompt=b''):
3516 3526 """show plain prompt"""
3517 3527 r = ui.prompt(prompt)
3518 3528 ui.writenoi18n(b'response: %s\n' % r)
3519 3529
3520 3530
3521 3531 @command(b'debugupdatecaches', [])
3522 3532 def debugupdatecaches(ui, repo, *pats, **opts):
3523 3533 """warm all known caches in the repository"""
3524 3534 with repo.wlock(), repo.lock():
3525 3535 repo.updatecaches(full=True)
3526 3536
3527 3537
3528 3538 @command(
3529 3539 b'debugupgraderepo',
3530 3540 [
3531 3541 (
3532 3542 b'o',
3533 3543 b'optimize',
3534 3544 [],
3535 3545 _(b'extra optimization to perform'),
3536 3546 _(b'NAME'),
3537 3547 ),
3538 3548 (b'', b'run', False, _(b'performs an upgrade')),
3539 3549 (b'', b'backup', True, _(b'keep the old repository content around')),
3540 3550 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
3541 3551 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
3542 3552 ],
3543 3553 )
3544 3554 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
3545 3555 """upgrade a repository to use different features
3546 3556
3547 3557 If no arguments are specified, the repository is evaluated for upgrade
3548 3558 and a list of problems and potential optimizations is printed.
3549 3559
3550 3560 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
3551 3561 can be influenced via additional arguments. More details will be provided
3552 3562 by the command output when run without ``--run``.
3553 3563
3554 3564 During the upgrade, the repository will be locked and no writes will be
3555 3565 allowed.
3556 3566
3557 3567 At the end of the upgrade, the repository may not be readable while new
3558 3568 repository data is swapped in. This window will be as long as it takes to
3559 3569 rename some directories inside the ``.hg`` directory. On most machines, this
3560 3570 should complete almost instantaneously and the chances of a consumer being
3561 3571 unable to access the repository should be low.
3562 3572
3563 3573 By default, all revlog will be upgraded. You can restrict this using flag
3564 3574 such as `--manifest`:
3565 3575
3566 3576 * `--manifest`: only optimize the manifest
3567 3577 * `--no-manifest`: optimize all revlog but the manifest
3568 3578 * `--changelog`: optimize the changelog only
3569 3579 * `--no-changelog --no-manifest`: optimize filelogs only
3570 3580 """
3571 3581 return upgrade.upgraderepo(
3572 3582 ui, repo, run=run, optimize=optimize, backup=backup, **opts
3573 3583 )
3574 3584
3575 3585
3576 3586 @command(
3577 3587 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
3578 3588 )
3579 3589 def debugwalk(ui, repo, *pats, **opts):
3580 3590 """show how files match on given patterns"""
3581 3591 opts = pycompat.byteskwargs(opts)
3582 3592 m = scmutil.match(repo[None], pats, opts)
3583 3593 if ui.verbose:
3584 3594 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
3585 3595 items = list(repo[None].walk(m))
3586 3596 if not items:
3587 3597 return
3588 3598 f = lambda fn: fn
3589 3599 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
3590 3600 f = lambda fn: util.normpath(fn)
3591 3601 fmt = b'f %%-%ds %%-%ds %%s' % (
3592 3602 max([len(abs) for abs in items]),
3593 3603 max([len(repo.pathto(abs)) for abs in items]),
3594 3604 )
3595 3605 for abs in items:
3596 3606 line = fmt % (
3597 3607 abs,
3598 3608 f(repo.pathto(abs)),
3599 3609 m.exact(abs) and b'exact' or b'',
3600 3610 )
3601 3611 ui.write(b"%s\n" % line.rstrip())
3602 3612
3603 3613
3604 3614 @command(b'debugwhyunstable', [], _(b'REV'))
3605 3615 def debugwhyunstable(ui, repo, rev):
3606 3616 """explain instabilities of a changeset"""
3607 3617 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
3608 3618 dnodes = b''
3609 3619 if entry.get(b'divergentnodes'):
3610 3620 dnodes = (
3611 3621 b' '.join(
3612 3622 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
3613 3623 for ctx in entry[b'divergentnodes']
3614 3624 )
3615 3625 + b' '
3616 3626 )
3617 3627 ui.write(
3618 3628 b'%s: %s%s %s\n'
3619 3629 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
3620 3630 )
3621 3631
3622 3632
3623 3633 @command(
3624 3634 b'debugwireargs',
3625 3635 [
3626 3636 (b'', b'three', b'', b'three'),
3627 3637 (b'', b'four', b'', b'four'),
3628 3638 (b'', b'five', b'', b'five'),
3629 3639 ]
3630 3640 + cmdutil.remoteopts,
3631 3641 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
3632 3642 norepo=True,
3633 3643 )
3634 3644 def debugwireargs(ui, repopath, *vals, **opts):
3635 3645 opts = pycompat.byteskwargs(opts)
3636 3646 repo = hg.peer(ui, opts, repopath)
3637 3647 for opt in cmdutil.remoteopts:
3638 3648 del opts[opt[1]]
3639 3649 args = {}
3640 3650 for k, v in pycompat.iteritems(opts):
3641 3651 if v:
3642 3652 args[k] = v
3643 3653 args = pycompat.strkwargs(args)
3644 3654 # run twice to check that we don't mess up the stream for the next command
3645 3655 res1 = repo.debugwireargs(*vals, **args)
3646 3656 res2 = repo.debugwireargs(*vals, **args)
3647 3657 ui.write(b"%s\n" % res1)
3648 3658 if res1 != res2:
3649 3659 ui.warn(b"%s\n" % res2)
3650 3660
3651 3661
3652 3662 def _parsewirelangblocks(fh):
3653 3663 activeaction = None
3654 3664 blocklines = []
3655 3665 lastindent = 0
3656 3666
3657 3667 for line in fh:
3658 3668 line = line.rstrip()
3659 3669 if not line:
3660 3670 continue
3661 3671
3662 3672 if line.startswith(b'#'):
3663 3673 continue
3664 3674
3665 3675 if not line.startswith(b' '):
3666 3676 # New block. Flush previous one.
3667 3677 if activeaction:
3668 3678 yield activeaction, blocklines
3669 3679
3670 3680 activeaction = line
3671 3681 blocklines = []
3672 3682 lastindent = 0
3673 3683 continue
3674 3684
3675 3685 # Else we start with an indent.
3676 3686
3677 3687 if not activeaction:
3678 3688 raise error.Abort(_(b'indented line outside of block'))
3679 3689
3680 3690 indent = len(line) - len(line.lstrip())
3681 3691
3682 3692 # If this line is indented more than the last line, concatenate it.
3683 3693 if indent > lastindent and blocklines:
3684 3694 blocklines[-1] += line.lstrip()
3685 3695 else:
3686 3696 blocklines.append(line)
3687 3697 lastindent = indent
3688 3698
3689 3699 # Flush last block.
3690 3700 if activeaction:
3691 3701 yield activeaction, blocklines
3692 3702
3693 3703
3694 3704 @command(
3695 3705 b'debugwireproto',
3696 3706 [
3697 3707 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
3698 3708 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
3699 3709 (
3700 3710 b'',
3701 3711 b'noreadstderr',
3702 3712 False,
3703 3713 _(b'do not read from stderr of the remote'),
3704 3714 ),
3705 3715 (
3706 3716 b'',
3707 3717 b'nologhandshake',
3708 3718 False,
3709 3719 _(b'do not log I/O related to the peer handshake'),
3710 3720 ),
3711 3721 ]
3712 3722 + cmdutil.remoteopts,
3713 3723 _(b'[PATH]'),
3714 3724 optionalrepo=True,
3715 3725 )
3716 3726 def debugwireproto(ui, repo, path=None, **opts):
3717 3727 """send wire protocol commands to a server
3718 3728
3719 3729 This command can be used to issue wire protocol commands to remote
3720 3730 peers and to debug the raw data being exchanged.
3721 3731
3722 3732 ``--localssh`` will start an SSH server against the current repository
3723 3733 and connect to that. By default, the connection will perform a handshake
3724 3734 and establish an appropriate peer instance.
3725 3735
3726 3736 ``--peer`` can be used to bypass the handshake protocol and construct a
3727 3737 peer instance using the specified class type. Valid values are ``raw``,
3728 3738 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
3729 3739 raw data payloads and don't support higher-level command actions.
3730 3740
3731 3741 ``--noreadstderr`` can be used to disable automatic reading from stderr
3732 3742 of the peer (for SSH connections only). Disabling automatic reading of
3733 3743 stderr is useful for making output more deterministic.
3734 3744
3735 3745 Commands are issued via a mini language which is specified via stdin.
3736 3746 The language consists of individual actions to perform. An action is
3737 3747 defined by a block. A block is defined as a line with no leading
3738 3748 space followed by 0 or more lines with leading space. Blocks are
3739 3749 effectively a high-level command with additional metadata.
3740 3750
3741 3751 Lines beginning with ``#`` are ignored.
3742 3752
3743 3753 The following sections denote available actions.
3744 3754
3745 3755 raw
3746 3756 ---
3747 3757
3748 3758 Send raw data to the server.
3749 3759
3750 3760 The block payload contains the raw data to send as one atomic send
3751 3761 operation. The data may not actually be delivered in a single system
3752 3762 call: it depends on the abilities of the transport being used.
3753 3763
3754 3764 Each line in the block is de-indented and concatenated. Then, that
3755 3765 value is evaluated as a Python b'' literal. This allows the use of
3756 3766 backslash escaping, etc.
3757 3767
3758 3768 raw+
3759 3769 ----
3760 3770
3761 3771 Behaves like ``raw`` except flushes output afterwards.
3762 3772
3763 3773 command <X>
3764 3774 -----------
3765 3775
3766 3776 Send a request to run a named command, whose name follows the ``command``
3767 3777 string.
3768 3778
3769 3779 Arguments to the command are defined as lines in this block. The format of
3770 3780 each line is ``<key> <value>``. e.g.::
3771 3781
3772 3782 command listkeys
3773 3783 namespace bookmarks
3774 3784
3775 3785 If the value begins with ``eval:``, it will be interpreted as a Python
3776 3786 literal expression. Otherwise values are interpreted as Python b'' literals.
3777 3787 This allows sending complex types and encoding special byte sequences via
3778 3788 backslash escaping.
3779 3789
3780 3790 The following arguments have special meaning:
3781 3791
3782 3792 ``PUSHFILE``
3783 3793 When defined, the *push* mechanism of the peer will be used instead
3784 3794 of the static request-response mechanism and the content of the
3785 3795 file specified in the value of this argument will be sent as the
3786 3796 command payload.
3787 3797
3788 3798 This can be used to submit a local bundle file to the remote.
3789 3799
3790 3800 batchbegin
3791 3801 ----------
3792 3802
3793 3803 Instruct the peer to begin a batched send.
3794 3804
3795 3805 All ``command`` blocks are queued for execution until the next
3796 3806 ``batchsubmit`` block.
3797 3807
3798 3808 batchsubmit
3799 3809 -----------
3800 3810
3801 3811 Submit previously queued ``command`` blocks as a batch request.
3802 3812
3803 3813 This action MUST be paired with a ``batchbegin`` action.
3804 3814
3805 3815 httprequest <method> <path>
3806 3816 ---------------------------
3807 3817
3808 3818 (HTTP peer only)
3809 3819
3810 3820 Send an HTTP request to the peer.
3811 3821
3812 3822 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
3813 3823
3814 3824 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
3815 3825 headers to add to the request. e.g. ``Accept: foo``.
3816 3826
3817 3827 The following arguments are special:
3818 3828
3819 3829 ``BODYFILE``
3820 3830 The content of the file defined as the value to this argument will be
3821 3831 transferred verbatim as the HTTP request body.
3822 3832
3823 3833 ``frame <type> <flags> <payload>``
3824 3834 Send a unified protocol frame as part of the request body.
3825 3835
3826 3836 All frames will be collected and sent as the body to the HTTP
3827 3837 request.
3828 3838
3829 3839 close
3830 3840 -----
3831 3841
3832 3842 Close the connection to the server.
3833 3843
3834 3844 flush
3835 3845 -----
3836 3846
3837 3847 Flush data written to the server.
3838 3848
3839 3849 readavailable
3840 3850 -------------
3841 3851
3842 3852 Close the write end of the connection and read all available data from
3843 3853 the server.
3844 3854
3845 3855 If the connection to the server encompasses multiple pipes, we poll both
3846 3856 pipes and read available data.
3847 3857
3848 3858 readline
3849 3859 --------
3850 3860
3851 3861 Read a line of output from the server. If there are multiple output
3852 3862 pipes, reads only the main pipe.
3853 3863
3854 3864 ereadline
3855 3865 ---------
3856 3866
3857 3867 Like ``readline``, but read from the stderr pipe, if available.
3858 3868
3859 3869 read <X>
3860 3870 --------
3861 3871
3862 3872 ``read()`` N bytes from the server's main output pipe.
3863 3873
3864 3874 eread <X>
3865 3875 ---------
3866 3876
3867 3877 ``read()`` N bytes from the server's stderr pipe, if available.
3868 3878
3869 3879 Specifying Unified Frame-Based Protocol Frames
3870 3880 ----------------------------------------------
3871 3881
3872 3882 It is possible to emit a *Unified Frame-Based Protocol* by using special
3873 3883 syntax.
3874 3884
3875 3885 A frame is composed as a type, flags, and payload. These can be parsed
3876 3886 from a string of the form:
3877 3887
3878 3888 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
3879 3889
3880 3890 ``request-id`` and ``stream-id`` are integers defining the request and
3881 3891 stream identifiers.
3882 3892
3883 3893 ``type`` can be an integer value for the frame type or the string name
3884 3894 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
3885 3895 ``command-name``.
3886 3896
3887 3897 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
3888 3898 components. Each component (and there can be just one) can be an integer
3889 3899 or a flag name for stream flags or frame flags, respectively. Values are
3890 3900 resolved to integers and then bitwise OR'd together.
3891 3901
3892 3902 ``payload`` represents the raw frame payload. If it begins with
3893 3903 ``cbor:``, the following string is evaluated as Python code and the
3894 3904 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
3895 3905 as a Python byte string literal.
3896 3906 """
3897 3907 opts = pycompat.byteskwargs(opts)
3898 3908
3899 3909 if opts[b'localssh'] and not repo:
3900 3910 raise error.Abort(_(b'--localssh requires a repository'))
3901 3911
3902 3912 if opts[b'peer'] and opts[b'peer'] not in (
3903 3913 b'raw',
3904 3914 b'http2',
3905 3915 b'ssh1',
3906 3916 b'ssh2',
3907 3917 ):
3908 3918 raise error.Abort(
3909 3919 _(b'invalid value for --peer'),
3910 3920 hint=_(b'valid values are "raw", "ssh1", and "ssh2"'),
3911 3921 )
3912 3922
3913 3923 if path and opts[b'localssh']:
3914 3924 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
3915 3925
3916 3926 if ui.interactive():
3917 3927 ui.write(_(b'(waiting for commands on stdin)\n'))
3918 3928
3919 3929 blocks = list(_parsewirelangblocks(ui.fin))
3920 3930
3921 3931 proc = None
3922 3932 stdin = None
3923 3933 stdout = None
3924 3934 stderr = None
3925 3935 opener = None
3926 3936
3927 3937 if opts[b'localssh']:
3928 3938 # We start the SSH server in its own process so there is process
3929 3939 # separation. This prevents a whole class of potential bugs around
3930 3940 # shared state from interfering with server operation.
3931 3941 args = procutil.hgcmd() + [
3932 3942 b'-R',
3933 3943 repo.root,
3934 3944 b'debugserve',
3935 3945 b'--sshstdio',
3936 3946 ]
3937 3947 proc = subprocess.Popen(
3938 3948 pycompat.rapply(procutil.tonativestr, args),
3939 3949 stdin=subprocess.PIPE,
3940 3950 stdout=subprocess.PIPE,
3941 3951 stderr=subprocess.PIPE,
3942 3952 bufsize=0,
3943 3953 )
3944 3954
3945 3955 stdin = proc.stdin
3946 3956 stdout = proc.stdout
3947 3957 stderr = proc.stderr
3948 3958
3949 3959 # We turn the pipes into observers so we can log I/O.
3950 3960 if ui.verbose or opts[b'peer'] == b'raw':
3951 3961 stdin = util.makeloggingfileobject(
3952 3962 ui, proc.stdin, b'i', logdata=True
3953 3963 )
3954 3964 stdout = util.makeloggingfileobject(
3955 3965 ui, proc.stdout, b'o', logdata=True
3956 3966 )
3957 3967 stderr = util.makeloggingfileobject(
3958 3968 ui, proc.stderr, b'e', logdata=True
3959 3969 )
3960 3970
3961 3971 # --localssh also implies the peer connection settings.
3962 3972
3963 3973 url = b'ssh://localserver'
3964 3974 autoreadstderr = not opts[b'noreadstderr']
3965 3975
3966 3976 if opts[b'peer'] == b'ssh1':
3967 3977 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
3968 3978 peer = sshpeer.sshv1peer(
3969 3979 ui,
3970 3980 url,
3971 3981 proc,
3972 3982 stdin,
3973 3983 stdout,
3974 3984 stderr,
3975 3985 None,
3976 3986 autoreadstderr=autoreadstderr,
3977 3987 )
3978 3988 elif opts[b'peer'] == b'ssh2':
3979 3989 ui.write(_(b'creating ssh peer for wire protocol version 2\n'))
3980 3990 peer = sshpeer.sshv2peer(
3981 3991 ui,
3982 3992 url,
3983 3993 proc,
3984 3994 stdin,
3985 3995 stdout,
3986 3996 stderr,
3987 3997 None,
3988 3998 autoreadstderr=autoreadstderr,
3989 3999 )
3990 4000 elif opts[b'peer'] == b'raw':
3991 4001 ui.write(_(b'using raw connection to peer\n'))
3992 4002 peer = None
3993 4003 else:
3994 4004 ui.write(_(b'creating ssh peer from handshake results\n'))
3995 4005 peer = sshpeer.makepeer(
3996 4006 ui,
3997 4007 url,
3998 4008 proc,
3999 4009 stdin,
4000 4010 stdout,
4001 4011 stderr,
4002 4012 autoreadstderr=autoreadstderr,
4003 4013 )
4004 4014
4005 4015 elif path:
4006 4016 # We bypass hg.peer() so we can proxy the sockets.
4007 4017 # TODO consider not doing this because we skip
4008 4018 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4009 4019 u = util.url(path)
4010 4020 if u.scheme != b'http':
4011 4021 raise error.Abort(_(b'only http:// paths are currently supported'))
4012 4022
4013 4023 url, authinfo = u.authinfo()
4014 4024 openerargs = {
4015 4025 'useragent': b'Mercurial debugwireproto',
4016 4026 }
4017 4027
4018 4028 # Turn pipes/sockets into observers so we can log I/O.
4019 4029 if ui.verbose:
4020 4030 openerargs.update(
4021 4031 {
4022 4032 'loggingfh': ui,
4023 4033 'loggingname': b's',
4024 4034 'loggingopts': {'logdata': True, 'logdataapis': False,},
4025 4035 }
4026 4036 )
4027 4037
4028 4038 if ui.debugflag:
4029 4039 openerargs['loggingopts']['logdataapis'] = True
4030 4040
4031 4041 # Don't send default headers when in raw mode. This allows us to
4032 4042 # bypass most of the behavior of our URL handling code so we can
4033 4043 # have near complete control over what's sent on the wire.
4034 4044 if opts[b'peer'] == b'raw':
4035 4045 openerargs['sendaccept'] = False
4036 4046
4037 4047 opener = urlmod.opener(ui, authinfo, **openerargs)
4038 4048
4039 4049 if opts[b'peer'] == b'http2':
4040 4050 ui.write(_(b'creating http peer for wire protocol version 2\n'))
4041 4051 # We go through makepeer() because we need an API descriptor for
4042 4052 # the peer instance to be useful.
4043 4053 with ui.configoverride(
4044 4054 {(b'experimental', b'httppeer.advertise-v2'): True}
4045 4055 ):
4046 4056 if opts[b'nologhandshake']:
4047 4057 ui.pushbuffer()
4048 4058
4049 4059 peer = httppeer.makepeer(ui, path, opener=opener)
4050 4060
4051 4061 if opts[b'nologhandshake']:
4052 4062 ui.popbuffer()
4053 4063
4054 4064 if not isinstance(peer, httppeer.httpv2peer):
4055 4065 raise error.Abort(
4056 4066 _(
4057 4067 b'could not instantiate HTTP peer for '
4058 4068 b'wire protocol version 2'
4059 4069 ),
4060 4070 hint=_(
4061 4071 b'the server may not have the feature '
4062 4072 b'enabled or is not allowing this '
4063 4073 b'client version'
4064 4074 ),
4065 4075 )
4066 4076
4067 4077 elif opts[b'peer'] == b'raw':
4068 4078 ui.write(_(b'using raw connection to peer\n'))
4069 4079 peer = None
4070 4080 elif opts[b'peer']:
4071 4081 raise error.Abort(
4072 4082 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4073 4083 )
4074 4084 else:
4075 4085 peer = httppeer.makepeer(ui, path, opener=opener)
4076 4086
4077 4087 # We /could/ populate stdin/stdout with sock.makefile()...
4078 4088 else:
4079 4089 raise error.Abort(_(b'unsupported connection configuration'))
4080 4090
4081 4091 batchedcommands = None
4082 4092
4083 4093 # Now perform actions based on the parsed wire language instructions.
4084 4094 for action, lines in blocks:
4085 4095 if action in (b'raw', b'raw+'):
4086 4096 if not stdin:
4087 4097 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4088 4098
4089 4099 # Concatenate the data together.
4090 4100 data = b''.join(l.lstrip() for l in lines)
4091 4101 data = stringutil.unescapestr(data)
4092 4102 stdin.write(data)
4093 4103
4094 4104 if action == b'raw+':
4095 4105 stdin.flush()
4096 4106 elif action == b'flush':
4097 4107 if not stdin:
4098 4108 raise error.Abort(_(b'cannot call flush on this peer'))
4099 4109 stdin.flush()
4100 4110 elif action.startswith(b'command'):
4101 4111 if not peer:
4102 4112 raise error.Abort(
4103 4113 _(
4104 4114 b'cannot send commands unless peer instance '
4105 4115 b'is available'
4106 4116 )
4107 4117 )
4108 4118
4109 4119 command = action.split(b' ', 1)[1]
4110 4120
4111 4121 args = {}
4112 4122 for line in lines:
4113 4123 # We need to allow empty values.
4114 4124 fields = line.lstrip().split(b' ', 1)
4115 4125 if len(fields) == 1:
4116 4126 key = fields[0]
4117 4127 value = b''
4118 4128 else:
4119 4129 key, value = fields
4120 4130
4121 4131 if value.startswith(b'eval:'):
4122 4132 value = stringutil.evalpythonliteral(value[5:])
4123 4133 else:
4124 4134 value = stringutil.unescapestr(value)
4125 4135
4126 4136 args[key] = value
4127 4137
4128 4138 if batchedcommands is not None:
4129 4139 batchedcommands.append((command, args))
4130 4140 continue
4131 4141
4132 4142 ui.status(_(b'sending %s command\n') % command)
4133 4143
4134 4144 if b'PUSHFILE' in args:
4135 4145 with open(args[b'PUSHFILE'], 'rb') as fh:
4136 4146 del args[b'PUSHFILE']
4137 4147 res, output = peer._callpush(
4138 4148 command, fh, **pycompat.strkwargs(args)
4139 4149 )
4140 4150 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4141 4151 ui.status(
4142 4152 _(b'remote output: %s\n') % stringutil.escapestr(output)
4143 4153 )
4144 4154 else:
4145 4155 with peer.commandexecutor() as e:
4146 4156 res = e.callcommand(command, args).result()
4147 4157
4148 4158 if isinstance(res, wireprotov2peer.commandresponse):
4149 4159 val = res.objects()
4150 4160 ui.status(
4151 4161 _(b'response: %s\n')
4152 4162 % stringutil.pprint(val, bprefix=True, indent=2)
4153 4163 )
4154 4164 else:
4155 4165 ui.status(
4156 4166 _(b'response: %s\n')
4157 4167 % stringutil.pprint(res, bprefix=True, indent=2)
4158 4168 )
4159 4169
4160 4170 elif action == b'batchbegin':
4161 4171 if batchedcommands is not None:
4162 4172 raise error.Abort(_(b'nested batchbegin not allowed'))
4163 4173
4164 4174 batchedcommands = []
4165 4175 elif action == b'batchsubmit':
4166 4176 # There is a batching API we could go through. But it would be
4167 4177 # difficult to normalize requests into function calls. It is easier
4168 4178 # to bypass this layer and normalize to commands + args.
4169 4179 ui.status(
4170 4180 _(b'sending batch with %d sub-commands\n')
4171 4181 % len(batchedcommands)
4172 4182 )
4173 4183 assert peer is not None
4174 4184 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4175 4185 ui.status(
4176 4186 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4177 4187 )
4178 4188
4179 4189 batchedcommands = None
4180 4190
4181 4191 elif action.startswith(b'httprequest '):
4182 4192 if not opener:
4183 4193 raise error.Abort(
4184 4194 _(b'cannot use httprequest without an HTTP peer')
4185 4195 )
4186 4196
4187 4197 request = action.split(b' ', 2)
4188 4198 if len(request) != 3:
4189 4199 raise error.Abort(
4190 4200 _(
4191 4201 b'invalid httprequest: expected format is '
4192 4202 b'"httprequest <method> <path>'
4193 4203 )
4194 4204 )
4195 4205
4196 4206 method, httppath = request[1:]
4197 4207 headers = {}
4198 4208 body = None
4199 4209 frames = []
4200 4210 for line in lines:
4201 4211 line = line.lstrip()
4202 4212 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4203 4213 if m:
4204 4214 # Headers need to use native strings.
4205 4215 key = pycompat.strurl(m.group(1))
4206 4216 value = pycompat.strurl(m.group(2))
4207 4217 headers[key] = value
4208 4218 continue
4209 4219
4210 4220 if line.startswith(b'BODYFILE '):
4211 4221 with open(line.split(b' ', 1), b'rb') as fh:
4212 4222 body = fh.read()
4213 4223 elif line.startswith(b'frame '):
4214 4224 frame = wireprotoframing.makeframefromhumanstring(
4215 4225 line[len(b'frame ') :]
4216 4226 )
4217 4227
4218 4228 frames.append(frame)
4219 4229 else:
4220 4230 raise error.Abort(
4221 4231 _(b'unknown argument to httprequest: %s') % line
4222 4232 )
4223 4233
4224 4234 url = path + httppath
4225 4235
4226 4236 if frames:
4227 4237 body = b''.join(bytes(f) for f in frames)
4228 4238
4229 4239 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4230 4240
4231 4241 # urllib.Request insists on using has_data() as a proxy for
4232 4242 # determining the request method. Override that to use our
4233 4243 # explicitly requested method.
4234 4244 req.get_method = lambda: pycompat.sysstr(method)
4235 4245
4236 4246 try:
4237 4247 res = opener.open(req)
4238 4248 body = res.read()
4239 4249 except util.urlerr.urlerror as e:
4240 4250 # read() method must be called, but only exists in Python 2
4241 4251 getattr(e, 'read', lambda: None)()
4242 4252 continue
4243 4253
4244 4254 ct = res.headers.get('Content-Type')
4245 4255 if ct == 'application/mercurial-cbor':
4246 4256 ui.write(
4247 4257 _(b'cbor> %s\n')
4248 4258 % stringutil.pprint(
4249 4259 cborutil.decodeall(body), bprefix=True, indent=2
4250 4260 )
4251 4261 )
4252 4262
4253 4263 elif action == b'close':
4254 4264 assert peer is not None
4255 4265 peer.close()
4256 4266 elif action == b'readavailable':
4257 4267 if not stdout or not stderr:
4258 4268 raise error.Abort(
4259 4269 _(b'readavailable not available on this peer')
4260 4270 )
4261 4271
4262 4272 stdin.close()
4263 4273 stdout.read()
4264 4274 stderr.read()
4265 4275
4266 4276 elif action == b'readline':
4267 4277 if not stdout:
4268 4278 raise error.Abort(_(b'readline not available on this peer'))
4269 4279 stdout.readline()
4270 4280 elif action == b'ereadline':
4271 4281 if not stderr:
4272 4282 raise error.Abort(_(b'ereadline not available on this peer'))
4273 4283 stderr.readline()
4274 4284 elif action.startswith(b'read '):
4275 4285 count = int(action.split(b' ', 1)[1])
4276 4286 if not stdout:
4277 4287 raise error.Abort(_(b'read not available on this peer'))
4278 4288 stdout.read(count)
4279 4289 elif action.startswith(b'eread '):
4280 4290 count = int(action.split(b' ', 1)[1])
4281 4291 if not stderr:
4282 4292 raise error.Abort(_(b'eread not available on this peer'))
4283 4293 stderr.read(count)
4284 4294 else:
4285 4295 raise error.Abort(_(b'unknown action: %s') % action)
4286 4296
4287 4297 if batchedcommands is not None:
4288 4298 raise error.Abort(_(b'unclosed "batchbegin" request'))
4289 4299
4290 4300 if peer:
4291 4301 peer.close()
4292 4302
4293 4303 if proc:
4294 4304 proc.kill()
@@ -1,425 +1,427 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 abort
4 4 add
5 5 addremove
6 6 annotate
7 7 archive
8 8 backout
9 9 bisect
10 10 bookmarks
11 11 branch
12 12 branches
13 13 bundle
14 14 cat
15 15 clone
16 16 commit
17 17 config
18 18 continue
19 19 copy
20 20 diff
21 21 export
22 22 files
23 23 forget
24 24 graft
25 25 grep
26 26 heads
27 27 help
28 28 identify
29 29 import
30 30 incoming
31 31 init
32 32 locate
33 33 log
34 34 manifest
35 35 merge
36 36 outgoing
37 37 parents
38 38 paths
39 39 phase
40 40 pull
41 41 push
42 42 recover
43 43 remove
44 44 rename
45 45 resolve
46 46 revert
47 47 rollback
48 48 root
49 49 serve
50 50 shelve
51 51 status
52 52 summary
53 53 tag
54 54 tags
55 55 tip
56 56 unbundle
57 57 unshelve
58 58 update
59 59 verify
60 60 version
61 61
62 62 Show all commands that start with "a"
63 63 $ hg debugcomplete a
64 64 abort
65 65 add
66 66 addremove
67 67 annotate
68 68 archive
69 69
70 70 Do not show debug commands if there are other candidates
71 71 $ hg debugcomplete d
72 72 diff
73 73
74 74 Show debug commands if there are no other candidates
75 75 $ hg debugcomplete debug
76 76 debugancestor
77 77 debugapplystreamclonebundle
78 78 debugbuilddag
79 79 debugbundle
80 80 debugcapabilities
81 81 debugcheckstate
82 82 debugcolor
83 83 debugcommands
84 84 debugcomplete
85 85 debugconfig
86 86 debugcreatestreamclonebundle
87 87 debugdag
88 88 debugdata
89 89 debugdate
90 90 debugdeltachain
91 91 debugdirstate
92 92 debugdiscovery
93 93 debugdownload
94 94 debugextensions
95 95 debugfileset
96 96 debugformat
97 97 debugfsinfo
98 98 debuggetbundle
99 99 debugignore
100 100 debugindex
101 101 debugindexdot
102 102 debugindexstats
103 103 debuginstall
104 104 debugknown
105 105 debuglabelcomplete
106 106 debuglocks
107 107 debugmanifestfulltextcache
108 108 debugmergestate
109 109 debugnamecomplete
110 110 debugobsolete
111 111 debugp1copies
112 112 debugp2copies
113 113 debugpathcomplete
114 114 debugpathcopies
115 115 debugpeer
116 116 debugpickmergetool
117 117 debugpushkey
118 118 debugpvec
119 119 debugrebuilddirstate
120 120 debugrebuildfncache
121 121 debugrename
122 122 debugrevlog
123 123 debugrevlogindex
124 124 debugrevspec
125 125 debugserve
126 126 debugsetparents
127 127 debugsidedata
128 128 debugssl
129 129 debugsub
130 130 debugsuccessorssets
131 debugtagscache
131 132 debugtemplate
132 133 debuguigetpass
133 134 debuguiprompt
134 135 debugupdatecaches
135 136 debugupgraderepo
136 137 debugwalk
137 138 debugwhyunstable
138 139 debugwireargs
139 140 debugwireproto
140 141
141 142 Do not show the alias of a debug command if there are other candidates
142 143 (this should hide rawcommit)
143 144 $ hg debugcomplete r
144 145 recover
145 146 remove
146 147 rename
147 148 resolve
148 149 revert
149 150 rollback
150 151 root
151 152 Show the alias of a debug command if there are no other candidates
152 153 $ hg debugcomplete rawc
153 154
154 155
155 156 Show the global options
156 157 $ hg debugcomplete --options | sort
157 158 --color
158 159 --config
159 160 --cwd
160 161 --debug
161 162 --debugger
162 163 --encoding
163 164 --encodingmode
164 165 --help
165 166 --hidden
166 167 --noninteractive
167 168 --pager
168 169 --profile
169 170 --quiet
170 171 --repository
171 172 --time
172 173 --traceback
173 174 --verbose
174 175 --version
175 176 -R
176 177 -h
177 178 -q
178 179 -v
179 180 -y
180 181
181 182 Show the options for the "serve" command
182 183 $ hg debugcomplete --options serve | sort
183 184 --accesslog
184 185 --address
185 186 --certificate
186 187 --cmdserver
187 188 --color
188 189 --config
189 190 --cwd
190 191 --daemon
191 192 --daemon-postexec
192 193 --debug
193 194 --debugger
194 195 --encoding
195 196 --encodingmode
196 197 --errorlog
197 198 --help
198 199 --hidden
199 200 --ipv6
200 201 --name
201 202 --noninteractive
202 203 --pager
203 204 --pid-file
204 205 --port
205 206 --prefix
206 207 --print-url
207 208 --profile
208 209 --quiet
209 210 --repository
210 211 --stdio
211 212 --style
212 213 --subrepos
213 214 --templates
214 215 --time
215 216 --traceback
216 217 --verbose
217 218 --version
218 219 --web-conf
219 220 -6
220 221 -A
221 222 -E
222 223 -R
223 224 -S
224 225 -a
225 226 -d
226 227 -h
227 228 -n
228 229 -p
229 230 -q
230 231 -t
231 232 -v
232 233 -y
233 234
234 235 Show an error if we use --options with an ambiguous abbreviation
235 236 $ hg debugcomplete --options s
236 237 hg: command 's' is ambiguous:
237 238 serve shelve showconfig status summary
238 239 [255]
239 240
240 241 Show all commands + options
241 242 $ hg debugcommands
242 243 abort: dry-run
243 244 add: include, exclude, subrepos, dry-run
244 245 addremove: similarity, subrepos, include, exclude, dry-run
245 246 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
246 247 archive: no-decode, prefix, rev, type, subrepos, include, exclude
247 248 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
248 249 bisect: reset, good, bad, skip, extend, command, noupdate
249 250 bookmarks: force, rev, delete, rename, inactive, list, template
250 251 branch: force, clean, rev
251 252 branches: active, closed, rev, template
252 253 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
253 254 cat: output, rev, decode, include, exclude, template
254 255 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
255 256 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
256 257 config: untrusted, edit, local, global, template
257 258 continue: dry-run
258 259 copy: after, force, include, exclude, dry-run
259 260 debugancestor:
260 261 debugapplystreamclonebundle:
261 262 debugbuilddag: mergeable-file, overwritten-file, new-file
262 263 debugbundle: all, part-type, spec
263 264 debugcapabilities:
264 265 debugcheckstate:
265 266 debugcolor: style
266 267 debugcommands:
267 268 debugcomplete: options
268 269 debugcreatestreamclonebundle:
269 270 debugdag: tags, branches, dots, spaces
270 271 debugdata: changelog, manifest, dir
271 272 debugdate: extended
272 273 debugdeltachain: changelog, manifest, dir, template
273 274 debugdirstate: nodates, dates, datesort
274 275 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
275 276 debugdownload: output
276 277 debugextensions: template
277 278 debugfileset: rev, all-files, show-matcher, show-stage
278 279 debugformat: template
279 280 debugfsinfo:
280 281 debuggetbundle: head, common, type
281 282 debugignore:
282 283 debugindex: changelog, manifest, dir, template
283 284 debugindexdot: changelog, manifest, dir
284 285 debugindexstats:
285 286 debuginstall: template
286 287 debugknown:
287 288 debuglabelcomplete:
288 289 debuglocks: force-lock, force-wlock, set-lock, set-wlock
289 290 debugmanifestfulltextcache: clear, add
290 291 debugmergestate:
291 292 debugnamecomplete:
292 293 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
293 294 debugp1copies: rev
294 295 debugp2copies: rev
295 296 debugpathcomplete: full, normal, added, removed
296 297 debugpathcopies: include, exclude
297 298 debugpeer:
298 299 debugpickmergetool: rev, changedelete, include, exclude, tool
299 300 debugpushkey:
300 301 debugpvec:
301 302 debugrebuilddirstate: rev, minimal
302 303 debugrebuildfncache:
303 304 debugrename: rev
304 305 debugrevlog: changelog, manifest, dir, dump
305 306 debugrevlogindex: changelog, manifest, dir, format
306 307 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
307 308 debugserve: sshstdio, logiofd, logiofile
308 309 debugsetparents:
309 310 debugsidedata: changelog, manifest, dir
310 311 debugssl:
311 312 debugsub: rev
312 313 debugsuccessorssets: closest
314 debugtagscache:
313 315 debugtemplate: rev, define
314 316 debuguigetpass: prompt
315 317 debuguiprompt: prompt
316 318 debugupdatecaches:
317 319 debugupgraderepo: optimize, run, backup, changelog, manifest
318 320 debugwalk: include, exclude
319 321 debugwhyunstable:
320 322 debugwireargs: three, four, five, ssh, remotecmd, insecure
321 323 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
322 324 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
323 325 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
324 326 files: rev, print0, include, exclude, template, subrepos
325 327 forget: interactive, include, exclude, dry-run
326 328 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
327 329 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
328 330 heads: rev, topo, active, closed, style, template
329 331 help: extension, command, keyword, system
330 332 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
331 333 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
332 334 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
333 335 init: ssh, remotecmd, insecure
334 336 locate: rev, print0, fullpath, include, exclude
335 337 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
336 338 manifest: rev, all, template
337 339 merge: force, rev, preview, abort, tool
338 340 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
339 341 parents: rev, style, template
340 342 paths: template
341 343 phase: public, draft, secret, force, rev
342 344 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
343 345 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
344 346 recover: verify
345 347 remove: after, force, subrepos, include, exclude, dry-run
346 348 rename: after, force, include, exclude, dry-run
347 349 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
348 350 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
349 351 rollback: dry-run, force
350 352 root: template
351 353 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
352 354 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
353 355 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
354 356 summary: remote
355 357 tag: force, local, rev, remove, edit, message, date, user
356 358 tags: template
357 359 tip: patch, git, style, template
358 360 unbundle: update
359 361 unshelve: abort, continue, interactive, keep, name, tool, date
360 362 update: clean, check, merge, date, rev, tool
361 363 verify: full
362 364 version: template
363 365
364 366 $ hg init a
365 367 $ cd a
366 368 $ echo fee > fee
367 369 $ hg ci -q -Amfee
368 370 $ hg tag fee
369 371 $ mkdir fie
370 372 $ echo dead > fie/dead
371 373 $ echo live > fie/live
372 374 $ hg bookmark fo
373 375 $ hg branch -q fie
374 376 $ hg ci -q -Amfie
375 377 $ echo fo > fo
376 378 $ hg branch -qf default
377 379 $ hg ci -q -Amfo
378 380 $ echo Fum > Fum
379 381 $ hg ci -q -AmFum
380 382 $ hg bookmark Fum
381 383
382 384 Test debugpathcomplete
383 385
384 386 $ hg debugpathcomplete f
385 387 fee
386 388 fie
387 389 fo
388 390 $ hg debugpathcomplete -f f
389 391 fee
390 392 fie/dead
391 393 fie/live
392 394 fo
393 395
394 396 $ hg rm Fum
395 397 $ hg debugpathcomplete -r F
396 398 Fum
397 399
398 400 Test debugnamecomplete
399 401
400 402 $ hg debugnamecomplete
401 403 Fum
402 404 default
403 405 fee
404 406 fie
405 407 fo
406 408 tip
407 409 $ hg debugnamecomplete f
408 410 fee
409 411 fie
410 412 fo
411 413
412 414 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
413 415 used for completions in some shells.
414 416
415 417 $ hg debuglabelcomplete
416 418 Fum
417 419 default
418 420 fee
419 421 fie
420 422 fo
421 423 tip
422 424 $ hg debuglabelcomplete f
423 425 fee
424 426 fie
425 427 fo
@@ -1,3894 +1,3896 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 Extra extensions will be printed in help output in a non-reliable order since
48 48 the extension is unknown.
49 49 #if no-extraextensions
50 50
51 51 $ hg help
52 52 Mercurial Distributed SCM
53 53
54 54 list of commands:
55 55
56 56 Repository creation:
57 57
58 58 clone make a copy of an existing repository
59 59 init create a new repository in the given directory
60 60
61 61 Remote repository management:
62 62
63 63 incoming show new changesets found in source
64 64 outgoing show changesets not found in the destination
65 65 paths show aliases for remote repositories
66 66 pull pull changes from the specified source
67 67 push push changes to the specified destination
68 68 serve start stand-alone webserver
69 69
70 70 Change creation:
71 71
72 72 commit commit the specified files or all outstanding changes
73 73
74 74 Change manipulation:
75 75
76 76 backout reverse effect of earlier changeset
77 77 graft copy changes from other branches onto the current branch
78 78 merge merge another revision into working directory
79 79
80 80 Change organization:
81 81
82 82 bookmarks create a new bookmark or list existing bookmarks
83 83 branch set or show the current branch name
84 84 branches list repository named branches
85 85 phase set or show the current phase name
86 86 tag add one or more tags for the current or given revision
87 87 tags list repository tags
88 88
89 89 File content management:
90 90
91 91 annotate show changeset information by line for each file
92 92 cat output the current or given revision of files
93 93 copy mark files as copied for the next commit
94 94 diff diff repository (or selected files)
95 95 grep search for a pattern in specified files
96 96
97 97 Change navigation:
98 98
99 99 bisect subdivision search of changesets
100 100 heads show branch heads
101 101 identify identify the working directory or specified revision
102 102 log show revision history of entire repository or files
103 103
104 104 Working directory management:
105 105
106 106 add add the specified files on the next commit
107 107 addremove add all new files, delete all missing files
108 108 files list tracked files
109 109 forget forget the specified files on the next commit
110 110 remove remove the specified files on the next commit
111 111 rename rename files; equivalent of copy + remove
112 112 resolve redo merges or set/view the merge status of files
113 113 revert restore files to their checkout state
114 114 root print the root (top) of the current working directory
115 115 shelve save and set aside changes from the working directory
116 116 status show changed files in the working directory
117 117 summary summarize working directory state
118 118 unshelve restore a shelved change to the working directory
119 119 update update working directory (or switch revisions)
120 120
121 121 Change import/export:
122 122
123 123 archive create an unversioned archive of a repository revision
124 124 bundle create a bundle file
125 125 export dump the header and diffs for one or more changesets
126 126 import import an ordered set of patches
127 127 unbundle apply one or more bundle files
128 128
129 129 Repository maintenance:
130 130
131 131 manifest output the current or given revision of the project manifest
132 132 recover roll back an interrupted transaction
133 133 verify verify the integrity of the repository
134 134
135 135 Help:
136 136
137 137 config show combined config settings from all hgrc files
138 138 help show help for a given topic or a help overview
139 139 version output version and copyright information
140 140
141 141 additional help topics:
142 142
143 143 Mercurial identifiers:
144 144
145 145 filesets Specifying File Sets
146 146 hgignore Syntax for Mercurial Ignore Files
147 147 patterns File Name Patterns
148 148 revisions Specifying Revisions
149 149 urls URL Paths
150 150
151 151 Mercurial output:
152 152
153 153 color Colorizing Outputs
154 154 dates Date Formats
155 155 diffs Diff Formats
156 156 templating Template Usage
157 157
158 158 Mercurial configuration:
159 159
160 160 config Configuration Files
161 161 environment Environment Variables
162 162 extensions Using Additional Features
163 163 flags Command-line flags
164 164 hgweb Configuring hgweb
165 165 merge-tools Merge Tools
166 166 pager Pager Support
167 167
168 168 Concepts:
169 169
170 170 bundlespec Bundle File Formats
171 171 glossary Glossary
172 172 phases Working with Phases
173 173 subrepos Subrepositories
174 174
175 175 Miscellaneous:
176 176
177 177 deprecated Deprecated Features
178 178 internals Technical implementation topics
179 179 scripting Using Mercurial from scripts and automation
180 180
181 181 (use 'hg help -v' to show built-in aliases and global options)
182 182
183 183 $ hg -q help
184 184 Repository creation:
185 185
186 186 clone make a copy of an existing repository
187 187 init create a new repository in the given directory
188 188
189 189 Remote repository management:
190 190
191 191 incoming show new changesets found in source
192 192 outgoing show changesets not found in the destination
193 193 paths show aliases for remote repositories
194 194 pull pull changes from the specified source
195 195 push push changes to the specified destination
196 196 serve start stand-alone webserver
197 197
198 198 Change creation:
199 199
200 200 commit commit the specified files or all outstanding changes
201 201
202 202 Change manipulation:
203 203
204 204 backout reverse effect of earlier changeset
205 205 graft copy changes from other branches onto the current branch
206 206 merge merge another revision into working directory
207 207
208 208 Change organization:
209 209
210 210 bookmarks create a new bookmark or list existing bookmarks
211 211 branch set or show the current branch name
212 212 branches list repository named branches
213 213 phase set or show the current phase name
214 214 tag add one or more tags for the current or given revision
215 215 tags list repository tags
216 216
217 217 File content management:
218 218
219 219 annotate show changeset information by line for each file
220 220 cat output the current or given revision of files
221 221 copy mark files as copied for the next commit
222 222 diff diff repository (or selected files)
223 223 grep search for a pattern in specified files
224 224
225 225 Change navigation:
226 226
227 227 bisect subdivision search of changesets
228 228 heads show branch heads
229 229 identify identify the working directory or specified revision
230 230 log show revision history of entire repository or files
231 231
232 232 Working directory management:
233 233
234 234 add add the specified files on the next commit
235 235 addremove add all new files, delete all missing files
236 236 files list tracked files
237 237 forget forget the specified files on the next commit
238 238 remove remove the specified files on the next commit
239 239 rename rename files; equivalent of copy + remove
240 240 resolve redo merges or set/view the merge status of files
241 241 revert restore files to their checkout state
242 242 root print the root (top) of the current working directory
243 243 shelve save and set aside changes from the working directory
244 244 status show changed files in the working directory
245 245 summary summarize working directory state
246 246 unshelve restore a shelved change to the working directory
247 247 update update working directory (or switch revisions)
248 248
249 249 Change import/export:
250 250
251 251 archive create an unversioned archive of a repository revision
252 252 bundle create a bundle file
253 253 export dump the header and diffs for one or more changesets
254 254 import import an ordered set of patches
255 255 unbundle apply one or more bundle files
256 256
257 257 Repository maintenance:
258 258
259 259 manifest output the current or given revision of the project manifest
260 260 recover roll back an interrupted transaction
261 261 verify verify the integrity of the repository
262 262
263 263 Help:
264 264
265 265 config show combined config settings from all hgrc files
266 266 help show help for a given topic or a help overview
267 267 version output version and copyright information
268 268
269 269 additional help topics:
270 270
271 271 Mercurial identifiers:
272 272
273 273 filesets Specifying File Sets
274 274 hgignore Syntax for Mercurial Ignore Files
275 275 patterns File Name Patterns
276 276 revisions Specifying Revisions
277 277 urls URL Paths
278 278
279 279 Mercurial output:
280 280
281 281 color Colorizing Outputs
282 282 dates Date Formats
283 283 diffs Diff Formats
284 284 templating Template Usage
285 285
286 286 Mercurial configuration:
287 287
288 288 config Configuration Files
289 289 environment Environment Variables
290 290 extensions Using Additional Features
291 291 flags Command-line flags
292 292 hgweb Configuring hgweb
293 293 merge-tools Merge Tools
294 294 pager Pager Support
295 295
296 296 Concepts:
297 297
298 298 bundlespec Bundle File Formats
299 299 glossary Glossary
300 300 phases Working with Phases
301 301 subrepos Subrepositories
302 302
303 303 Miscellaneous:
304 304
305 305 deprecated Deprecated Features
306 306 internals Technical implementation topics
307 307 scripting Using Mercurial from scripts and automation
308 308
309 309 Test extension help:
310 310 $ hg help extensions --config extensions.rebase= --config extensions.children=
311 311 Using Additional Features
312 312 """""""""""""""""""""""""
313 313
314 314 Mercurial has the ability to add new features through the use of
315 315 extensions. Extensions may add new commands, add options to existing
316 316 commands, change the default behavior of commands, or implement hooks.
317 317
318 318 To enable the "foo" extension, either shipped with Mercurial or in the
319 319 Python search path, create an entry for it in your configuration file,
320 320 like this:
321 321
322 322 [extensions]
323 323 foo =
324 324
325 325 You may also specify the full path to an extension:
326 326
327 327 [extensions]
328 328 myfeature = ~/.hgext/myfeature.py
329 329
330 330 See 'hg help config' for more information on configuration files.
331 331
332 332 Extensions are not loaded by default for a variety of reasons: they can
333 333 increase startup overhead; they may be meant for advanced usage only; they
334 334 may provide potentially dangerous abilities (such as letting you destroy
335 335 or modify history); they might not be ready for prime time; or they may
336 336 alter some usual behaviors of stock Mercurial. It is thus up to the user
337 337 to activate extensions as needed.
338 338
339 339 To explicitly disable an extension enabled in a configuration file of
340 340 broader scope, prepend its path with !:
341 341
342 342 [extensions]
343 343 # disabling extension bar residing in /path/to/extension/bar.py
344 344 bar = !/path/to/extension/bar.py
345 345 # ditto, but no path was supplied for extension baz
346 346 baz = !
347 347
348 348 enabled extensions:
349 349
350 350 children command to display child changesets (DEPRECATED)
351 351 rebase command to move sets of revisions to a different ancestor
352 352
353 353 disabled extensions:
354 354
355 355 acl hooks for controlling repository access
356 356 blackbox log repository events to a blackbox for debugging
357 357 bugzilla hooks for integrating with the Bugzilla bug tracker
358 358 censor erase file content at a given revision
359 359 churn command to display statistics about repository history
360 360 clonebundles advertise pre-generated bundles to seed clones
361 361 closehead close arbitrary heads without checking them out first
362 362 convert import revisions from foreign VCS repositories into
363 363 Mercurial
364 364 eol automatically manage newlines in repository files
365 365 extdiff command to allow external programs to compare revisions
366 366 factotum http authentication with factotum
367 367 fastexport export repositories as git fast-import stream
368 368 githelp try mapping git commands to Mercurial commands
369 369 gpg commands to sign and verify changesets
370 370 hgk browse the repository in a graphical way
371 371 highlight syntax highlighting for hgweb (requires Pygments)
372 372 histedit interactive history editing
373 373 keyword expand keywords in tracked files
374 374 largefiles track large binary files
375 375 mq manage a stack of patches
376 376 notify hooks for sending email push notifications
377 377 patchbomb command to send changesets as (a series of) patch emails
378 378 purge command to delete untracked files from the working
379 379 directory
380 380 relink recreates hardlinks between repository clones
381 381 schemes extend schemes with shortcuts to repository swarms
382 382 share share a common history between several working directories
383 383 strip strip changesets and their descendants from history
384 384 transplant command to transplant changesets from another branch
385 385 win32mbcs allow the use of MBCS paths with problematic encodings
386 386 zeroconf discover and advertise repositories on the local network
387 387
388 388 #endif
389 389
390 390 Verify that deprecated extensions are included if --verbose:
391 391
392 392 $ hg -v help extensions | grep children
393 393 children command to display child changesets (DEPRECATED)
394 394
395 395 Verify that extension keywords appear in help templates
396 396
397 397 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
398 398
399 399 Test short command list with verbose option
400 400
401 401 $ hg -v help shortlist
402 402 Mercurial Distributed SCM
403 403
404 404 basic commands:
405 405
406 406 abort abort an unfinished operation (EXPERIMENTAL)
407 407 add add the specified files on the next commit
408 408 annotate, blame
409 409 show changeset information by line for each file
410 410 clone make a copy of an existing repository
411 411 commit, ci commit the specified files or all outstanding changes
412 412 continue resumes an interrupted operation (EXPERIMENTAL)
413 413 diff diff repository (or selected files)
414 414 export dump the header and diffs for one or more changesets
415 415 forget forget the specified files on the next commit
416 416 init create a new repository in the given directory
417 417 log, history show revision history of entire repository or files
418 418 merge merge another revision into working directory
419 419 pull pull changes from the specified source
420 420 push push changes to the specified destination
421 421 remove, rm remove the specified files on the next commit
422 422 serve start stand-alone webserver
423 423 status, st show changed files in the working directory
424 424 summary, sum summarize working directory state
425 425 update, up, checkout, co
426 426 update working directory (or switch revisions)
427 427
428 428 global options ([+] can be repeated):
429 429
430 430 -R --repository REPO repository root directory or name of overlay bundle
431 431 file
432 432 --cwd DIR change working directory
433 433 -y --noninteractive do not prompt, automatically pick the first choice for
434 434 all prompts
435 435 -q --quiet suppress output
436 436 -v --verbose enable additional output
437 437 --color TYPE when to colorize (boolean, always, auto, never, or
438 438 debug)
439 439 --config CONFIG [+] set/override config option (use 'section.name=value')
440 440 --debug enable debugging output
441 441 --debugger start debugger
442 442 --encoding ENCODE set the charset encoding (default: ascii)
443 443 --encodingmode MODE set the charset encoding mode (default: strict)
444 444 --traceback always print a traceback on exception
445 445 --time time how long the command takes
446 446 --profile print command execution profile
447 447 --version output version information and exit
448 448 -h --help display help and exit
449 449 --hidden consider hidden changesets
450 450 --pager TYPE when to paginate (boolean, always, auto, or never)
451 451 (default: auto)
452 452
453 453 (use 'hg help' for the full list of commands)
454 454
455 455 $ hg add -h
456 456 hg add [OPTION]... [FILE]...
457 457
458 458 add the specified files on the next commit
459 459
460 460 Schedule files to be version controlled and added to the repository.
461 461
462 462 The files will be added to the repository at the next commit. To undo an
463 463 add before that, see 'hg forget'.
464 464
465 465 If no names are given, add all files to the repository (except files
466 466 matching ".hgignore").
467 467
468 468 Returns 0 if all files are successfully added.
469 469
470 470 options ([+] can be repeated):
471 471
472 472 -I --include PATTERN [+] include names matching the given patterns
473 473 -X --exclude PATTERN [+] exclude names matching the given patterns
474 474 -S --subrepos recurse into subrepositories
475 475 -n --dry-run do not perform actions, just print output
476 476
477 477 (some details hidden, use --verbose to show complete help)
478 478
479 479 Verbose help for add
480 480
481 481 $ hg add -hv
482 482 hg add [OPTION]... [FILE]...
483 483
484 484 add the specified files on the next commit
485 485
486 486 Schedule files to be version controlled and added to the repository.
487 487
488 488 The files will be added to the repository at the next commit. To undo an
489 489 add before that, see 'hg forget'.
490 490
491 491 If no names are given, add all files to the repository (except files
492 492 matching ".hgignore").
493 493
494 494 Examples:
495 495
496 496 - New (unknown) files are added automatically by 'hg add':
497 497
498 498 $ ls
499 499 foo.c
500 500 $ hg status
501 501 ? foo.c
502 502 $ hg add
503 503 adding foo.c
504 504 $ hg status
505 505 A foo.c
506 506
507 507 - Specific files to be added can be specified:
508 508
509 509 $ ls
510 510 bar.c foo.c
511 511 $ hg status
512 512 ? bar.c
513 513 ? foo.c
514 514 $ hg add bar.c
515 515 $ hg status
516 516 A bar.c
517 517 ? foo.c
518 518
519 519 Returns 0 if all files are successfully added.
520 520
521 521 options ([+] can be repeated):
522 522
523 523 -I --include PATTERN [+] include names matching the given patterns
524 524 -X --exclude PATTERN [+] exclude names matching the given patterns
525 525 -S --subrepos recurse into subrepositories
526 526 -n --dry-run do not perform actions, just print output
527 527
528 528 global options ([+] can be repeated):
529 529
530 530 -R --repository REPO repository root directory or name of overlay bundle
531 531 file
532 532 --cwd DIR change working directory
533 533 -y --noninteractive do not prompt, automatically pick the first choice for
534 534 all prompts
535 535 -q --quiet suppress output
536 536 -v --verbose enable additional output
537 537 --color TYPE when to colorize (boolean, always, auto, never, or
538 538 debug)
539 539 --config CONFIG [+] set/override config option (use 'section.name=value')
540 540 --debug enable debugging output
541 541 --debugger start debugger
542 542 --encoding ENCODE set the charset encoding (default: ascii)
543 543 --encodingmode MODE set the charset encoding mode (default: strict)
544 544 --traceback always print a traceback on exception
545 545 --time time how long the command takes
546 546 --profile print command execution profile
547 547 --version output version information and exit
548 548 -h --help display help and exit
549 549 --hidden consider hidden changesets
550 550 --pager TYPE when to paginate (boolean, always, auto, or never)
551 551 (default: auto)
552 552
553 553 Test the textwidth config option
554 554
555 555 $ hg root -h --config ui.textwidth=50
556 556 hg root
557 557
558 558 print the root (top) of the current working
559 559 directory
560 560
561 561 Print the root directory of the current
562 562 repository.
563 563
564 564 Returns 0 on success.
565 565
566 566 options:
567 567
568 568 -T --template TEMPLATE display with template
569 569
570 570 (some details hidden, use --verbose to show
571 571 complete help)
572 572
573 573 Test help option with version option
574 574
575 575 $ hg add -h --version
576 576 Mercurial Distributed SCM (version *) (glob)
577 577 (see https://mercurial-scm.org for more information)
578 578
579 579 Copyright (C) 2005-* Matt Mackall and others (glob)
580 580 This is free software; see the source for copying conditions. There is NO
581 581 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
582 582
583 583 $ hg add --skjdfks
584 584 hg add: option --skjdfks not recognized
585 585 hg add [OPTION]... [FILE]...
586 586
587 587 add the specified files on the next commit
588 588
589 589 options ([+] can be repeated):
590 590
591 591 -I --include PATTERN [+] include names matching the given patterns
592 592 -X --exclude PATTERN [+] exclude names matching the given patterns
593 593 -S --subrepos recurse into subrepositories
594 594 -n --dry-run do not perform actions, just print output
595 595
596 596 (use 'hg add -h' to show more help)
597 597 [255]
598 598
599 599 Test ambiguous command help
600 600
601 601 $ hg help ad
602 602 list of commands:
603 603
604 604 add add the specified files on the next commit
605 605 addremove add all new files, delete all missing files
606 606
607 607 (use 'hg help -v ad' to show built-in aliases and global options)
608 608
609 609 Test command without options
610 610
611 611 $ hg help verify
612 612 hg verify
613 613
614 614 verify the integrity of the repository
615 615
616 616 Verify the integrity of the current repository.
617 617
618 618 This will perform an extensive check of the repository's integrity,
619 619 validating the hashes and checksums of each entry in the changelog,
620 620 manifest, and tracked files, as well as the integrity of their crosslinks
621 621 and indices.
622 622
623 623 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
624 624 information about recovery from corruption of the repository.
625 625
626 626 Returns 0 on success, 1 if errors are encountered.
627 627
628 628 options:
629 629
630 630 (some details hidden, use --verbose to show complete help)
631 631
632 632 $ hg help diff
633 633 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
634 634
635 635 diff repository (or selected files)
636 636
637 637 Show differences between revisions for the specified files.
638 638
639 639 Differences between files are shown using the unified diff format.
640 640
641 641 Note:
642 642 'hg diff' may generate unexpected results for merges, as it will
643 643 default to comparing against the working directory's first parent
644 644 changeset if no revisions are specified.
645 645
646 646 When two revision arguments are given, then changes are shown between
647 647 those revisions. If only one revision is specified then that revision is
648 648 compared to the working directory, and, when no revisions are specified,
649 649 the working directory files are compared to its first parent.
650 650
651 651 Alternatively you can specify -c/--change with a revision to see the
652 652 changes in that changeset relative to its first parent.
653 653
654 654 Without the -a/--text option, diff will avoid generating diffs of files it
655 655 detects as binary. With -a, diff will generate a diff anyway, probably
656 656 with undesirable results.
657 657
658 658 Use the -g/--git option to generate diffs in the git extended diff format.
659 659 For more information, read 'hg help diffs'.
660 660
661 661 Returns 0 on success.
662 662
663 663 options ([+] can be repeated):
664 664
665 665 -r --rev REV [+] revision
666 666 -c --change REV change made by revision
667 667 -a --text treat all files as text
668 668 -g --git use git extended diff format
669 669 --binary generate binary diffs in git mode (default)
670 670 --nodates omit dates from diff headers
671 671 --noprefix omit a/ and b/ prefixes from filenames
672 672 -p --show-function show which function each change is in
673 673 --reverse produce a diff that undoes the changes
674 674 -w --ignore-all-space ignore white space when comparing lines
675 675 -b --ignore-space-change ignore changes in the amount of white space
676 676 -B --ignore-blank-lines ignore changes whose lines are all blank
677 677 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
678 678 -U --unified NUM number of lines of context to show
679 679 --stat output diffstat-style summary of changes
680 680 --root DIR produce diffs relative to subdirectory
681 681 -I --include PATTERN [+] include names matching the given patterns
682 682 -X --exclude PATTERN [+] exclude names matching the given patterns
683 683 -S --subrepos recurse into subrepositories
684 684
685 685 (some details hidden, use --verbose to show complete help)
686 686
687 687 $ hg help status
688 688 hg status [OPTION]... [FILE]...
689 689
690 690 aliases: st
691 691
692 692 show changed files in the working directory
693 693
694 694 Show status of files in the repository. If names are given, only files
695 695 that match are shown. Files that are clean or ignored or the source of a
696 696 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
697 697 -C/--copies or -A/--all are given. Unless options described with "show
698 698 only ..." are given, the options -mardu are used.
699 699
700 700 Option -q/--quiet hides untracked (unknown and ignored) files unless
701 701 explicitly requested with -u/--unknown or -i/--ignored.
702 702
703 703 Note:
704 704 'hg status' may appear to disagree with diff if permissions have
705 705 changed or a merge has occurred. The standard diff format does not
706 706 report permission changes and diff only reports changes relative to one
707 707 merge parent.
708 708
709 709 If one revision is given, it is used as the base revision. If two
710 710 revisions are given, the differences between them are shown. The --change
711 711 option can also be used as a shortcut to list the changed files of a
712 712 revision from its first parent.
713 713
714 714 The codes used to show the status of files are:
715 715
716 716 M = modified
717 717 A = added
718 718 R = removed
719 719 C = clean
720 720 ! = missing (deleted by non-hg command, but still tracked)
721 721 ? = not tracked
722 722 I = ignored
723 723 = origin of the previous file (with --copies)
724 724
725 725 Returns 0 on success.
726 726
727 727 options ([+] can be repeated):
728 728
729 729 -A --all show status of all files
730 730 -m --modified show only modified files
731 731 -a --added show only added files
732 732 -r --removed show only removed files
733 733 -d --deleted show only deleted (but tracked) files
734 734 -c --clean show only files without changes
735 735 -u --unknown show only unknown (not tracked) files
736 736 -i --ignored show only ignored files
737 737 -n --no-status hide status prefix
738 738 -C --copies show source of copied files
739 739 -0 --print0 end filenames with NUL, for use with xargs
740 740 --rev REV [+] show difference from revision
741 741 --change REV list the changed files of a revision
742 742 -I --include PATTERN [+] include names matching the given patterns
743 743 -X --exclude PATTERN [+] exclude names matching the given patterns
744 744 -S --subrepos recurse into subrepositories
745 745 -T --template TEMPLATE display with template
746 746
747 747 (some details hidden, use --verbose to show complete help)
748 748
749 749 $ hg -q help status
750 750 hg status [OPTION]... [FILE]...
751 751
752 752 show changed files in the working directory
753 753
754 754 $ hg help foo
755 755 abort: no such help topic: foo
756 756 (try 'hg help --keyword foo')
757 757 [255]
758 758
759 759 $ hg skjdfks
760 760 hg: unknown command 'skjdfks'
761 761 (use 'hg help' for a list of commands)
762 762 [255]
763 763
764 764 Typoed command gives suggestion
765 765 $ hg puls
766 766 hg: unknown command 'puls'
767 767 (did you mean one of pull, push?)
768 768 [255]
769 769
770 770 Not enabled extension gets suggested
771 771
772 772 $ hg rebase
773 773 hg: unknown command 'rebase'
774 774 'rebase' is provided by the following extension:
775 775
776 776 rebase command to move sets of revisions to a different ancestor
777 777
778 778 (use 'hg help extensions' for information on enabling extensions)
779 779 [255]
780 780
781 781 Disabled extension gets suggested
782 782 $ hg --config extensions.rebase=! rebase
783 783 hg: unknown command 'rebase'
784 784 'rebase' is provided by the following extension:
785 785
786 786 rebase command to move sets of revisions to a different ancestor
787 787
788 788 (use 'hg help extensions' for information on enabling extensions)
789 789 [255]
790 790
791 791 Make sure that we don't run afoul of the help system thinking that
792 792 this is a section and erroring out weirdly.
793 793
794 794 $ hg .log
795 795 hg: unknown command '.log'
796 796 (did you mean log?)
797 797 [255]
798 798
799 799 $ hg log.
800 800 hg: unknown command 'log.'
801 801 (did you mean log?)
802 802 [255]
803 803 $ hg pu.lh
804 804 hg: unknown command 'pu.lh'
805 805 (did you mean one of pull, push?)
806 806 [255]
807 807
808 808 $ cat > helpext.py <<EOF
809 809 > import os
810 810 > from mercurial import commands, fancyopts, registrar
811 811 >
812 812 > def func(arg):
813 813 > return '%sfoo' % arg
814 814 > class customopt(fancyopts.customopt):
815 815 > def newstate(self, oldstate, newparam, abort):
816 816 > return '%sbar' % oldstate
817 817 > cmdtable = {}
818 818 > command = registrar.command(cmdtable)
819 819 >
820 820 > @command(b'nohelp',
821 821 > [(b'', b'longdesc', 3, b'x'*67),
822 822 > (b'n', b'', None, b'normal desc'),
823 823 > (b'', b'newline', b'', b'line1\nline2'),
824 824 > (b'', b'default-off', False, b'enable X'),
825 825 > (b'', b'default-on', True, b'enable Y'),
826 826 > (b'', b'callableopt', func, b'adds foo'),
827 827 > (b'', b'customopt', customopt(''), b'adds bar'),
828 828 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
829 829 > b'hg nohelp',
830 830 > norepo=True)
831 831 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
832 832 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
833 833 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
834 834 > def nohelp(ui, *args, **kwargs):
835 835 > pass
836 836 >
837 837 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
838 838 > def hashelp(ui, *args, **kwargs):
839 839 > """Extension command's help"""
840 840 >
841 841 > def uisetup(ui):
842 842 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
843 843 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
844 844 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
845 845 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
846 846 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
847 847 >
848 848 > EOF
849 849 $ echo '[extensions]' >> $HGRCPATH
850 850 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
851 851
852 852 Test for aliases
853 853
854 854 $ hg help | grep hgalias
855 855 hgalias My doc
856 856
857 857 $ hg help hgalias
858 858 hg hgalias [--remote]
859 859
860 860 alias for: hg summary
861 861
862 862 My doc
863 863
864 864 defined by: helpext
865 865
866 866 options:
867 867
868 868 --remote check for push and pull
869 869
870 870 (some details hidden, use --verbose to show complete help)
871 871 $ hg help hgaliasnodoc
872 872 hg hgaliasnodoc [--remote]
873 873
874 874 alias for: hg summary
875 875
876 876 summarize working directory state
877 877
878 878 This generates a brief summary of the working directory state, including
879 879 parents, branch, commit status, phase and available updates.
880 880
881 881 With the --remote option, this will check the default paths for incoming
882 882 and outgoing changes. This can be time-consuming.
883 883
884 884 Returns 0 on success.
885 885
886 886 defined by: helpext
887 887
888 888 options:
889 889
890 890 --remote check for push and pull
891 891
892 892 (some details hidden, use --verbose to show complete help)
893 893
894 894 $ hg help shellalias
895 895 hg shellalias
896 896
897 897 shell alias for: echo hi
898 898
899 899 (no help text available)
900 900
901 901 defined by: helpext
902 902
903 903 (some details hidden, use --verbose to show complete help)
904 904
905 905 Test command with no help text
906 906
907 907 $ hg help nohelp
908 908 hg nohelp
909 909
910 910 (no help text available)
911 911
912 912 options:
913 913
914 914 --longdesc VALUE
915 915 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
916 916 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
917 917 -n -- normal desc
918 918 --newline VALUE line1 line2
919 919 --default-off enable X
920 920 --[no-]default-on enable Y (default: on)
921 921 --callableopt VALUE adds foo
922 922 --customopt VALUE adds bar
923 923 --customopt-withdefault VALUE adds bar (default: foo)
924 924
925 925 (some details hidden, use --verbose to show complete help)
926 926
927 927 Test that default list of commands includes extension commands that have help,
928 928 but not those that don't, except in verbose mode, when a keyword is passed, or
929 929 when help about the extension is requested.
930 930
931 931 #if no-extraextensions
932 932
933 933 $ hg help | grep hashelp
934 934 hashelp Extension command's help
935 935 $ hg help | grep nohelp
936 936 [1]
937 937 $ hg help -v | grep nohelp
938 938 nohelp (no help text available)
939 939
940 940 $ hg help -k nohelp
941 941 Commands:
942 942
943 943 nohelp hg nohelp
944 944
945 945 Extension Commands:
946 946
947 947 nohelp (no help text available)
948 948
949 949 $ hg help helpext
950 950 helpext extension - no help text available
951 951
952 952 list of commands:
953 953
954 954 hashelp Extension command's help
955 955 nohelp (no help text available)
956 956
957 957 (use 'hg help -v helpext' to show built-in aliases and global options)
958 958
959 959 #endif
960 960
961 961 Test list of internal help commands
962 962
963 963 $ hg help debug
964 964 debug commands (internal and unsupported):
965 965
966 966 debugancestor
967 967 find the ancestor revision of two revisions in a given index
968 968 debugapplystreamclonebundle
969 969 apply a stream clone bundle file
970 970 debugbuilddag
971 971 builds a repo with a given DAG from scratch in the current
972 972 empty repo
973 973 debugbundle lists the contents of a bundle
974 974 debugcapabilities
975 975 lists the capabilities of a remote peer
976 976 debugcheckstate
977 977 validate the correctness of the current dirstate
978 978 debugcolor show available color, effects or style
979 979 debugcommands
980 980 list all available commands and options
981 981 debugcomplete
982 982 returns the completion list associated with the given command
983 983 debugcreatestreamclonebundle
984 984 create a stream clone bundle file
985 985 debugdag format the changelog or an index DAG as a concise textual
986 986 description
987 987 debugdata dump the contents of a data file revision
988 988 debugdate parse and display a date
989 989 debugdeltachain
990 990 dump information about delta chains in a revlog
991 991 debugdirstate
992 992 show the contents of the current dirstate
993 993 debugdiscovery
994 994 runs the changeset discovery protocol in isolation
995 995 debugdownload
996 996 download a resource using Mercurial logic and config
997 997 debugextensions
998 998 show information about active extensions
999 999 debugfileset parse and apply a fileset specification
1000 1000 debugformat display format information about the current repository
1001 1001 debugfsinfo show information detected about current filesystem
1002 1002 debuggetbundle
1003 1003 retrieves a bundle from a repo
1004 1004 debugignore display the combined ignore pattern and information about
1005 1005 ignored files
1006 1006 debugindex dump index data for a storage primitive
1007 1007 debugindexdot
1008 1008 dump an index DAG as a graphviz dot file
1009 1009 debugindexstats
1010 1010 show stats related to the changelog index
1011 1011 debuginstall test Mercurial installation
1012 1012 debugknown test whether node ids are known to a repo
1013 1013 debuglocks show or modify state of locks
1014 1014 debugmanifestfulltextcache
1015 1015 show, clear or amend the contents of the manifest fulltext
1016 1016 cache
1017 1017 debugmergestate
1018 1018 print merge state
1019 1019 debugnamecomplete
1020 1020 complete "names" - tags, open branch names, bookmark names
1021 1021 debugobsolete
1022 1022 create arbitrary obsolete marker
1023 1023 debugoptADV (no help text available)
1024 1024 debugoptDEP (no help text available)
1025 1025 debugoptEXP (no help text available)
1026 1026 debugp1copies
1027 1027 dump copy information compared to p1
1028 1028 debugp2copies
1029 1029 dump copy information compared to p2
1030 1030 debugpathcomplete
1031 1031 complete part or all of a tracked path
1032 1032 debugpathcopies
1033 1033 show copies between two revisions
1034 1034 debugpeer establish a connection to a peer repository
1035 1035 debugpickmergetool
1036 1036 examine which merge tool is chosen for specified file
1037 1037 debugpushkey access the pushkey key/value protocol
1038 1038 debugpvec (no help text available)
1039 1039 debugrebuilddirstate
1040 1040 rebuild the dirstate as it would look like for the given
1041 1041 revision
1042 1042 debugrebuildfncache
1043 1043 rebuild the fncache file
1044 1044 debugrename dump rename information
1045 1045 debugrevlog show data and statistics about a revlog
1046 1046 debugrevlogindex
1047 1047 dump the contents of a revlog index
1048 1048 debugrevspec parse and apply a revision specification
1049 1049 debugserve run a server with advanced settings
1050 1050 debugsetparents
1051 1051 manually set the parents of the current working directory
1052 1052 debugsidedata
1053 1053 dump the side data for a cl/manifest/file revision
1054 1054 debugssl test a secure connection to a server
1055 1055 debugsub (no help text available)
1056 1056 debugsuccessorssets
1057 1057 show set of successors for revision
1058 debugtagscache
1059 display the contents of .hg/cache/hgtagsfnodes1
1058 1060 debugtemplate
1059 1061 parse and apply a template
1060 1062 debuguigetpass
1061 1063 show prompt to type password
1062 1064 debuguiprompt
1063 1065 show plain prompt
1064 1066 debugupdatecaches
1065 1067 warm all known caches in the repository
1066 1068 debugupgraderepo
1067 1069 upgrade a repository to use different features
1068 1070 debugwalk show how files match on given patterns
1069 1071 debugwhyunstable
1070 1072 explain instabilities of a changeset
1071 1073 debugwireargs
1072 1074 (no help text available)
1073 1075 debugwireproto
1074 1076 send wire protocol commands to a server
1075 1077
1076 1078 (use 'hg help -v debug' to show built-in aliases and global options)
1077 1079
1078 1080 internals topic renders index of available sub-topics
1079 1081
1080 1082 $ hg help internals
1081 1083 Technical implementation topics
1082 1084 """""""""""""""""""""""""""""""
1083 1085
1084 1086 To access a subtopic, use "hg help internals.{subtopic-name}"
1085 1087
1086 1088 bundle2 Bundle2
1087 1089 bundles Bundles
1088 1090 cbor CBOR
1089 1091 censor Censor
1090 1092 changegroups Changegroups
1091 1093 config Config Registrar
1092 1094 extensions Extension API
1093 1095 mergestate Mergestate
1094 1096 requirements Repository Requirements
1095 1097 revlogs Revision Logs
1096 1098 wireprotocol Wire Protocol
1097 1099 wireprotocolrpc
1098 1100 Wire Protocol RPC
1099 1101 wireprotocolv2
1100 1102 Wire Protocol Version 2
1101 1103
1102 1104 sub-topics can be accessed
1103 1105
1104 1106 $ hg help internals.changegroups
1105 1107 Changegroups
1106 1108 """"""""""""
1107 1109
1108 1110 Changegroups are representations of repository revlog data, specifically
1109 1111 the changelog data, root/flat manifest data, treemanifest data, and
1110 1112 filelogs.
1111 1113
1112 1114 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1113 1115 level, versions "1" and "2" are almost exactly the same, with the only
1114 1116 difference being an additional item in the *delta header*. Version "3"
1115 1117 adds support for storage flags in the *delta header* and optionally
1116 1118 exchanging treemanifests (enabled by setting an option on the
1117 1119 "changegroup" part in the bundle2).
1118 1120
1119 1121 Changegroups when not exchanging treemanifests consist of 3 logical
1120 1122 segments:
1121 1123
1122 1124 +---------------------------------+
1123 1125 | | | |
1124 1126 | changeset | manifest | filelogs |
1125 1127 | | | |
1126 1128 | | | |
1127 1129 +---------------------------------+
1128 1130
1129 1131 When exchanging treemanifests, there are 4 logical segments:
1130 1132
1131 1133 +-------------------------------------------------+
1132 1134 | | | | |
1133 1135 | changeset | root | treemanifests | filelogs |
1134 1136 | | manifest | | |
1135 1137 | | | | |
1136 1138 +-------------------------------------------------+
1137 1139
1138 1140 The principle building block of each segment is a *chunk*. A *chunk* is a
1139 1141 framed piece of data:
1140 1142
1141 1143 +---------------------------------------+
1142 1144 | | |
1143 1145 | length | data |
1144 1146 | (4 bytes) | (<length - 4> bytes) |
1145 1147 | | |
1146 1148 +---------------------------------------+
1147 1149
1148 1150 All integers are big-endian signed integers. Each chunk starts with a
1149 1151 32-bit integer indicating the length of the entire chunk (including the
1150 1152 length field itself).
1151 1153
1152 1154 There is a special case chunk that has a value of 0 for the length
1153 1155 ("0x00000000"). We call this an *empty chunk*.
1154 1156
1155 1157 Delta Groups
1156 1158 ============
1157 1159
1158 1160 A *delta group* expresses the content of a revlog as a series of deltas,
1159 1161 or patches against previous revisions.
1160 1162
1161 1163 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1162 1164 to signal the end of the delta group:
1163 1165
1164 1166 +------------------------------------------------------------------------+
1165 1167 | | | | | |
1166 1168 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1167 1169 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1168 1170 | | | | | |
1169 1171 +------------------------------------------------------------------------+
1170 1172
1171 1173 Each *chunk*'s data consists of the following:
1172 1174
1173 1175 +---------------------------------------+
1174 1176 | | |
1175 1177 | delta header | delta data |
1176 1178 | (various by version) | (various) |
1177 1179 | | |
1178 1180 +---------------------------------------+
1179 1181
1180 1182 The *delta data* is a series of *delta*s that describe a diff from an
1181 1183 existing entry (either that the recipient already has, or previously
1182 1184 specified in the bundle/changegroup).
1183 1185
1184 1186 The *delta header* is different between versions "1", "2", and "3" of the
1185 1187 changegroup format.
1186 1188
1187 1189 Version 1 (headerlen=80):
1188 1190
1189 1191 +------------------------------------------------------+
1190 1192 | | | | |
1191 1193 | node | p1 node | p2 node | link node |
1192 1194 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1193 1195 | | | | |
1194 1196 +------------------------------------------------------+
1195 1197
1196 1198 Version 2 (headerlen=100):
1197 1199
1198 1200 +------------------------------------------------------------------+
1199 1201 | | | | | |
1200 1202 | node | p1 node | p2 node | base node | link node |
1201 1203 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1202 1204 | | | | | |
1203 1205 +------------------------------------------------------------------+
1204 1206
1205 1207 Version 3 (headerlen=102):
1206 1208
1207 1209 +------------------------------------------------------------------------------+
1208 1210 | | | | | | |
1209 1211 | node | p1 node | p2 node | base node | link node | flags |
1210 1212 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1211 1213 | | | | | | |
1212 1214 +------------------------------------------------------------------------------+
1213 1215
1214 1216 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1215 1217 contain a series of *delta*s, densely packed (no separators). These deltas
1216 1218 describe a diff from an existing entry (either that the recipient already
1217 1219 has, or previously specified in the bundle/changegroup). The format is
1218 1220 described more fully in "hg help internals.bdiff", but briefly:
1219 1221
1220 1222 +---------------------------------------------------------------+
1221 1223 | | | | |
1222 1224 | start offset | end offset | new length | content |
1223 1225 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1224 1226 | | | | |
1225 1227 +---------------------------------------------------------------+
1226 1228
1227 1229 Please note that the length field in the delta data does *not* include
1228 1230 itself.
1229 1231
1230 1232 In version 1, the delta is always applied against the previous node from
1231 1233 the changegroup or the first parent if this is the first entry in the
1232 1234 changegroup.
1233 1235
1234 1236 In version 2 and up, the delta base node is encoded in the entry in the
1235 1237 changegroup. This allows the delta to be expressed against any parent,
1236 1238 which can result in smaller deltas and more efficient encoding of data.
1237 1239
1238 1240 The *flags* field holds bitwise flags affecting the processing of revision
1239 1241 data. The following flags are defined:
1240 1242
1241 1243 32768
1242 1244 Censored revision. The revision's fulltext has been replaced by censor
1243 1245 metadata. May only occur on file revisions.
1244 1246
1245 1247 16384
1246 1248 Ellipsis revision. Revision hash does not match data (likely due to
1247 1249 rewritten parents).
1248 1250
1249 1251 8192
1250 1252 Externally stored. The revision fulltext contains "key:value" "\n"
1251 1253 delimited metadata defining an object stored elsewhere. Used by the LFS
1252 1254 extension.
1253 1255
1254 1256 For historical reasons, the integer values are identical to revlog version
1255 1257 1 per-revision storage flags and correspond to bits being set in this
1256 1258 2-byte field. Bits were allocated starting from the most-significant bit,
1257 1259 hence the reverse ordering and allocation of these flags.
1258 1260
1259 1261 Changeset Segment
1260 1262 =================
1261 1263
1262 1264 The *changeset segment* consists of a single *delta group* holding
1263 1265 changelog data. The *empty chunk* at the end of the *delta group* denotes
1264 1266 the boundary to the *manifest segment*.
1265 1267
1266 1268 Manifest Segment
1267 1269 ================
1268 1270
1269 1271 The *manifest segment* consists of a single *delta group* holding manifest
1270 1272 data. If treemanifests are in use, it contains only the manifest for the
1271 1273 root directory of the repository. Otherwise, it contains the entire
1272 1274 manifest data. The *empty chunk* at the end of the *delta group* denotes
1273 1275 the boundary to the next segment (either the *treemanifests segment* or
1274 1276 the *filelogs segment*, depending on version and the request options).
1275 1277
1276 1278 Treemanifests Segment
1277 1279 ---------------------
1278 1280
1279 1281 The *treemanifests segment* only exists in changegroup version "3", and
1280 1282 only if the 'treemanifest' param is part of the bundle2 changegroup part
1281 1283 (it is not possible to use changegroup version 3 outside of bundle2).
1282 1284 Aside from the filenames in the *treemanifests segment* containing a
1283 1285 trailing "/" character, it behaves identically to the *filelogs segment*
1284 1286 (see below). The final sub-segment is followed by an *empty chunk*
1285 1287 (logically, a sub-segment with filename size 0). This denotes the boundary
1286 1288 to the *filelogs segment*.
1287 1289
1288 1290 Filelogs Segment
1289 1291 ================
1290 1292
1291 1293 The *filelogs segment* consists of multiple sub-segments, each
1292 1294 corresponding to an individual file whose data is being described:
1293 1295
1294 1296 +--------------------------------------------------+
1295 1297 | | | | | |
1296 1298 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1297 1299 | | | | | (4 bytes) |
1298 1300 | | | | | |
1299 1301 +--------------------------------------------------+
1300 1302
1301 1303 The final filelog sub-segment is followed by an *empty chunk* (logically,
1302 1304 a sub-segment with filename size 0). This denotes the end of the segment
1303 1305 and of the overall changegroup.
1304 1306
1305 1307 Each filelog sub-segment consists of the following:
1306 1308
1307 1309 +------------------------------------------------------+
1308 1310 | | | |
1309 1311 | filename length | filename | delta group |
1310 1312 | (4 bytes) | (<length - 4> bytes) | (various) |
1311 1313 | | | |
1312 1314 +------------------------------------------------------+
1313 1315
1314 1316 That is, a *chunk* consisting of the filename (not terminated or padded)
1315 1317 followed by N chunks constituting the *delta group* for this file. The
1316 1318 *empty chunk* at the end of each *delta group* denotes the boundary to the
1317 1319 next filelog sub-segment.
1318 1320
1319 1321 non-existent subtopics print an error
1320 1322
1321 1323 $ hg help internals.foo
1322 1324 abort: no such help topic: internals.foo
1323 1325 (try 'hg help --keyword foo')
1324 1326 [255]
1325 1327
1326 1328 test advanced, deprecated and experimental options are hidden in command help
1327 1329 $ hg help debugoptADV
1328 1330 hg debugoptADV
1329 1331
1330 1332 (no help text available)
1331 1333
1332 1334 options:
1333 1335
1334 1336 (some details hidden, use --verbose to show complete help)
1335 1337 $ hg help debugoptDEP
1336 1338 hg debugoptDEP
1337 1339
1338 1340 (no help text available)
1339 1341
1340 1342 options:
1341 1343
1342 1344 (some details hidden, use --verbose to show complete help)
1343 1345
1344 1346 $ hg help debugoptEXP
1345 1347 hg debugoptEXP
1346 1348
1347 1349 (no help text available)
1348 1350
1349 1351 options:
1350 1352
1351 1353 (some details hidden, use --verbose to show complete help)
1352 1354
1353 1355 test advanced, deprecated and experimental options are shown with -v
1354 1356 $ hg help -v debugoptADV | grep aopt
1355 1357 --aopt option is (ADVANCED)
1356 1358 $ hg help -v debugoptDEP | grep dopt
1357 1359 --dopt option is (DEPRECATED)
1358 1360 $ hg help -v debugoptEXP | grep eopt
1359 1361 --eopt option is (EXPERIMENTAL)
1360 1362
1361 1363 #if gettext
1362 1364 test deprecated option is hidden with translation with untranslated description
1363 1365 (use many globy for not failing on changed transaction)
1364 1366 $ LANGUAGE=sv hg help debugoptDEP
1365 1367 hg debugoptDEP
1366 1368
1367 1369 (*) (glob)
1368 1370
1369 1371 options:
1370 1372
1371 1373 (some details hidden, use --verbose to show complete help)
1372 1374 #endif
1373 1375
1374 1376 Test commands that collide with topics (issue4240)
1375 1377
1376 1378 $ hg config -hq
1377 1379 hg config [-u] [NAME]...
1378 1380
1379 1381 show combined config settings from all hgrc files
1380 1382 $ hg showconfig -hq
1381 1383 hg config [-u] [NAME]...
1382 1384
1383 1385 show combined config settings from all hgrc files
1384 1386
1385 1387 Test a help topic
1386 1388
1387 1389 $ hg help dates
1388 1390 Date Formats
1389 1391 """"""""""""
1390 1392
1391 1393 Some commands allow the user to specify a date, e.g.:
1392 1394
1393 1395 - backout, commit, import, tag: Specify the commit date.
1394 1396 - log, revert, update: Select revision(s) by date.
1395 1397
1396 1398 Many date formats are valid. Here are some examples:
1397 1399
1398 1400 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1399 1401 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1400 1402 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1401 1403 - "Dec 6" (midnight)
1402 1404 - "13:18" (today assumed)
1403 1405 - "3:39" (3:39AM assumed)
1404 1406 - "3:39pm" (15:39)
1405 1407 - "2006-12-06 13:18:29" (ISO 8601 format)
1406 1408 - "2006-12-6 13:18"
1407 1409 - "2006-12-6"
1408 1410 - "12-6"
1409 1411 - "12/6"
1410 1412 - "12/6/6" (Dec 6 2006)
1411 1413 - "today" (midnight)
1412 1414 - "yesterday" (midnight)
1413 1415 - "now" - right now
1414 1416
1415 1417 Lastly, there is Mercurial's internal format:
1416 1418
1417 1419 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1418 1420
1419 1421 This is the internal representation format for dates. The first number is
1420 1422 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1421 1423 is the offset of the local timezone, in seconds west of UTC (negative if
1422 1424 the timezone is east of UTC).
1423 1425
1424 1426 The log command also accepts date ranges:
1425 1427
1426 1428 - "<DATE" - at or before a given date/time
1427 1429 - ">DATE" - on or after a given date/time
1428 1430 - "DATE to DATE" - a date range, inclusive
1429 1431 - "-DAYS" - within a given number of days of today
1430 1432
1431 1433 Test repeated config section name
1432 1434
1433 1435 $ hg help config.host
1434 1436 "http_proxy.host"
1435 1437 Host name and (optional) port of the proxy server, for example
1436 1438 "myproxy:8000".
1437 1439
1438 1440 "smtp.host"
1439 1441 Host name of mail server, e.g. "mail.example.com".
1440 1442
1441 1443
1442 1444 Test section name with dot
1443 1445
1444 1446 $ hg help config.ui.username
1445 1447 "ui.username"
1446 1448 The committer of a changeset created when running "commit". Typically
1447 1449 a person's name and email address, e.g. "Fred Widget
1448 1450 <fred@example.com>". Environment variables in the username are
1449 1451 expanded.
1450 1452
1451 1453 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1452 1454 empty, e.g. if the system admin set "username =" in the system hgrc,
1453 1455 it has to be specified manually or in a different hgrc file)
1454 1456
1455 1457
1456 1458 $ hg help config.annotate.git
1457 1459 abort: help section not found: config.annotate.git
1458 1460 [255]
1459 1461
1460 1462 $ hg help config.update.check
1461 1463 "commands.update.check"
1462 1464 Determines what level of checking 'hg update' will perform before
1463 1465 moving to a destination revision. Valid values are "abort", "none",
1464 1466 "linear", and "noconflict". "abort" always fails if the working
1465 1467 directory has uncommitted changes. "none" performs no checking, and
1466 1468 may result in a merge with uncommitted changes. "linear" allows any
1467 1469 update as long as it follows a straight line in the revision history,
1468 1470 and may trigger a merge with uncommitted changes. "noconflict" will
1469 1471 allow any update which would not trigger a merge with uncommitted
1470 1472 changes, if any are present. (default: "linear")
1471 1473
1472 1474
1473 1475 $ hg help config.commands.update.check
1474 1476 "commands.update.check"
1475 1477 Determines what level of checking 'hg update' will perform before
1476 1478 moving to a destination revision. Valid values are "abort", "none",
1477 1479 "linear", and "noconflict". "abort" always fails if the working
1478 1480 directory has uncommitted changes. "none" performs no checking, and
1479 1481 may result in a merge with uncommitted changes. "linear" allows any
1480 1482 update as long as it follows a straight line in the revision history,
1481 1483 and may trigger a merge with uncommitted changes. "noconflict" will
1482 1484 allow any update which would not trigger a merge with uncommitted
1483 1485 changes, if any are present. (default: "linear")
1484 1486
1485 1487
1486 1488 $ hg help config.ommands.update.check
1487 1489 abort: help section not found: config.ommands.update.check
1488 1490 [255]
1489 1491
1490 1492 Unrelated trailing paragraphs shouldn't be included
1491 1493
1492 1494 $ hg help config.extramsg | grep '^$'
1493 1495
1494 1496
1495 1497 Test capitalized section name
1496 1498
1497 1499 $ hg help scripting.HGPLAIN > /dev/null
1498 1500
1499 1501 Help subsection:
1500 1502
1501 1503 $ hg help config.charsets |grep "Email example:" > /dev/null
1502 1504 [1]
1503 1505
1504 1506 Show nested definitions
1505 1507 ("profiling.type"[break]"ls"[break]"stat"[break])
1506 1508
1507 1509 $ hg help config.type | egrep '^$'|wc -l
1508 1510 \s*3 (re)
1509 1511
1510 1512 $ hg help config.profiling.type.ls
1511 1513 "profiling.type.ls"
1512 1514 Use Python's built-in instrumenting profiler. This profiler works on
1513 1515 all platforms, but each line number it reports is the first line of
1514 1516 a function. This restriction makes it difficult to identify the
1515 1517 expensive parts of a non-trivial function.
1516 1518
1517 1519
1518 1520 Separate sections from subsections
1519 1521
1520 1522 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1521 1523 "format"
1522 1524 --------
1523 1525
1524 1526 "usegeneraldelta"
1525 1527
1526 1528 "dotencode"
1527 1529
1528 1530 "usefncache"
1529 1531
1530 1532 "usestore"
1531 1533
1532 1534 "sparse-revlog"
1533 1535
1534 1536 "revlog-compression"
1535 1537
1536 1538 "bookmarks-in-store"
1537 1539
1538 1540 "profiling"
1539 1541 -----------
1540 1542
1541 1543 "format"
1542 1544
1543 1545 "progress"
1544 1546 ----------
1545 1547
1546 1548 "format"
1547 1549
1548 1550
1549 1551 Last item in help config.*:
1550 1552
1551 1553 $ hg help config.`hg help config|grep '^ "'| \
1552 1554 > tail -1|sed 's![ "]*!!g'`| \
1553 1555 > grep 'hg help -c config' > /dev/null
1554 1556 [1]
1555 1557
1556 1558 note to use help -c for general hg help config:
1557 1559
1558 1560 $ hg help config |grep 'hg help -c config' > /dev/null
1559 1561
1560 1562 Test templating help
1561 1563
1562 1564 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1563 1565 desc String. The text of the changeset description.
1564 1566 diffstat String. Statistics of changes with the following format:
1565 1567 firstline Any text. Returns the first line of text.
1566 1568 nonempty Any text. Returns '(none)' if the string is empty.
1567 1569
1568 1570 Test deprecated items
1569 1571
1570 1572 $ hg help -v templating | grep currentbookmark
1571 1573 currentbookmark
1572 1574 $ hg help templating | (grep currentbookmark || true)
1573 1575
1574 1576 Test help hooks
1575 1577
1576 1578 $ cat > helphook1.py <<EOF
1577 1579 > from mercurial import help
1578 1580 >
1579 1581 > def rewrite(ui, topic, doc):
1580 1582 > return doc + b'\nhelphook1\n'
1581 1583 >
1582 1584 > def extsetup(ui):
1583 1585 > help.addtopichook(b'revisions', rewrite)
1584 1586 > EOF
1585 1587 $ cat > helphook2.py <<EOF
1586 1588 > from mercurial import help
1587 1589 >
1588 1590 > def rewrite(ui, topic, doc):
1589 1591 > return doc + b'\nhelphook2\n'
1590 1592 >
1591 1593 > def extsetup(ui):
1592 1594 > help.addtopichook(b'revisions', rewrite)
1593 1595 > EOF
1594 1596 $ echo '[extensions]' >> $HGRCPATH
1595 1597 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1596 1598 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1597 1599 $ hg help revsets | grep helphook
1598 1600 helphook1
1599 1601 helphook2
1600 1602
1601 1603 help -c should only show debug --debug
1602 1604
1603 1605 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1604 1606 [1]
1605 1607
1606 1608 help -c should only show deprecated for -v
1607 1609
1608 1610 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1609 1611 [1]
1610 1612
1611 1613 Test -s / --system
1612 1614
1613 1615 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1614 1616 > wc -l | sed -e 's/ //g'
1615 1617 0
1616 1618 $ hg help config.files --system unix | grep 'USER' | \
1617 1619 > wc -l | sed -e 's/ //g'
1618 1620 0
1619 1621
1620 1622 Test -e / -c / -k combinations
1621 1623
1622 1624 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1623 1625 Commands:
1624 1626 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1625 1627 Extensions:
1626 1628 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1627 1629 Topics:
1628 1630 Commands:
1629 1631 Extensions:
1630 1632 Extension Commands:
1631 1633 $ hg help -c schemes
1632 1634 abort: no such help topic: schemes
1633 1635 (try 'hg help --keyword schemes')
1634 1636 [255]
1635 1637 $ hg help -e schemes |head -1
1636 1638 schemes extension - extend schemes with shortcuts to repository swarms
1637 1639 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1638 1640 Commands:
1639 1641 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1640 1642 Extensions:
1641 1643 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1642 1644 Extensions:
1643 1645 Commands:
1644 1646 $ hg help -c commit > /dev/null
1645 1647 $ hg help -e -c commit > /dev/null
1646 1648 $ hg help -e commit
1647 1649 abort: no such help topic: commit
1648 1650 (try 'hg help --keyword commit')
1649 1651 [255]
1650 1652
1651 1653 Test keyword search help
1652 1654
1653 1655 $ cat > prefixedname.py <<EOF
1654 1656 > '''matched against word "clone"
1655 1657 > '''
1656 1658 > EOF
1657 1659 $ echo '[extensions]' >> $HGRCPATH
1658 1660 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1659 1661 $ hg help -k clone
1660 1662 Topics:
1661 1663
1662 1664 config Configuration Files
1663 1665 extensions Using Additional Features
1664 1666 glossary Glossary
1665 1667 phases Working with Phases
1666 1668 subrepos Subrepositories
1667 1669 urls URL Paths
1668 1670
1669 1671 Commands:
1670 1672
1671 1673 bookmarks create a new bookmark or list existing bookmarks
1672 1674 clone make a copy of an existing repository
1673 1675 paths show aliases for remote repositories
1674 1676 pull pull changes from the specified source
1675 1677 update update working directory (or switch revisions)
1676 1678
1677 1679 Extensions:
1678 1680
1679 1681 clonebundles advertise pre-generated bundles to seed clones
1680 1682 narrow create clones which fetch history data for subset of files
1681 1683 (EXPERIMENTAL)
1682 1684 prefixedname matched against word "clone"
1683 1685 relink recreates hardlinks between repository clones
1684 1686
1685 1687 Extension Commands:
1686 1688
1687 1689 qclone clone main and patch repository at same time
1688 1690
1689 1691 Test unfound topic
1690 1692
1691 1693 $ hg help nonexistingtopicthatwillneverexisteverever
1692 1694 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1693 1695 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1694 1696 [255]
1695 1697
1696 1698 Test unfound keyword
1697 1699
1698 1700 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1699 1701 abort: no matches
1700 1702 (try 'hg help' for a list of topics)
1701 1703 [255]
1702 1704
1703 1705 Test omit indicating for help
1704 1706
1705 1707 $ cat > addverboseitems.py <<EOF
1706 1708 > r'''extension to test omit indicating.
1707 1709 >
1708 1710 > This paragraph is never omitted (for extension)
1709 1711 >
1710 1712 > .. container:: verbose
1711 1713 >
1712 1714 > This paragraph is omitted,
1713 1715 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1714 1716 >
1715 1717 > This paragraph is never omitted, too (for extension)
1716 1718 > '''
1717 1719 > from __future__ import absolute_import
1718 1720 > from mercurial import commands, help
1719 1721 > testtopic = br"""This paragraph is never omitted (for topic).
1720 1722 >
1721 1723 > .. container:: verbose
1722 1724 >
1723 1725 > This paragraph is omitted,
1724 1726 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1725 1727 >
1726 1728 > This paragraph is never omitted, too (for topic)
1727 1729 > """
1728 1730 > def extsetup(ui):
1729 1731 > help.helptable.append(([b"topic-containing-verbose"],
1730 1732 > b"This is the topic to test omit indicating.",
1731 1733 > lambda ui: testtopic))
1732 1734 > EOF
1733 1735 $ echo '[extensions]' >> $HGRCPATH
1734 1736 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1735 1737 $ hg help addverboseitems
1736 1738 addverboseitems extension - extension to test omit indicating.
1737 1739
1738 1740 This paragraph is never omitted (for extension)
1739 1741
1740 1742 This paragraph is never omitted, too (for extension)
1741 1743
1742 1744 (some details hidden, use --verbose to show complete help)
1743 1745
1744 1746 no commands defined
1745 1747 $ hg help -v addverboseitems
1746 1748 addverboseitems extension - extension to test omit indicating.
1747 1749
1748 1750 This paragraph is never omitted (for extension)
1749 1751
1750 1752 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1751 1753 extension)
1752 1754
1753 1755 This paragraph is never omitted, too (for extension)
1754 1756
1755 1757 no commands defined
1756 1758 $ hg help topic-containing-verbose
1757 1759 This is the topic to test omit indicating.
1758 1760 """"""""""""""""""""""""""""""""""""""""""
1759 1761
1760 1762 This paragraph is never omitted (for topic).
1761 1763
1762 1764 This paragraph is never omitted, too (for topic)
1763 1765
1764 1766 (some details hidden, use --verbose to show complete help)
1765 1767 $ hg help -v topic-containing-verbose
1766 1768 This is the topic to test omit indicating.
1767 1769 """"""""""""""""""""""""""""""""""""""""""
1768 1770
1769 1771 This paragraph is never omitted (for topic).
1770 1772
1771 1773 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1772 1774 topic)
1773 1775
1774 1776 This paragraph is never omitted, too (for topic)
1775 1777
1776 1778 Test section lookup
1777 1779
1778 1780 $ hg help revset.merge
1779 1781 "merge()"
1780 1782 Changeset is a merge changeset.
1781 1783
1782 1784 $ hg help glossary.dag
1783 1785 DAG
1784 1786 The repository of changesets of a distributed version control system
1785 1787 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1786 1788 of nodes and edges, where nodes correspond to changesets and edges
1787 1789 imply a parent -> child relation. This graph can be visualized by
1788 1790 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1789 1791 limited by the requirement for children to have at most two parents.
1790 1792
1791 1793
1792 1794 $ hg help hgrc.paths
1793 1795 "paths"
1794 1796 -------
1795 1797
1796 1798 Assigns symbolic names and behavior to repositories.
1797 1799
1798 1800 Options are symbolic names defining the URL or directory that is the
1799 1801 location of the repository. Example:
1800 1802
1801 1803 [paths]
1802 1804 my_server = https://example.com/my_repo
1803 1805 local_path = /home/me/repo
1804 1806
1805 1807 These symbolic names can be used from the command line. To pull from
1806 1808 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1807 1809 local_path'.
1808 1810
1809 1811 Options containing colons (":") denote sub-options that can influence
1810 1812 behavior for that specific path. Example:
1811 1813
1812 1814 [paths]
1813 1815 my_server = https://example.com/my_path
1814 1816 my_server:pushurl = ssh://example.com/my_path
1815 1817
1816 1818 The following sub-options can be defined:
1817 1819
1818 1820 "pushurl"
1819 1821 The URL to use for push operations. If not defined, the location
1820 1822 defined by the path's main entry is used.
1821 1823
1822 1824 "pushrev"
1823 1825 A revset defining which revisions to push by default.
1824 1826
1825 1827 When 'hg push' is executed without a "-r" argument, the revset defined
1826 1828 by this sub-option is evaluated to determine what to push.
1827 1829
1828 1830 For example, a value of "." will push the working directory's revision
1829 1831 by default.
1830 1832
1831 1833 Revsets specifying bookmarks will not result in the bookmark being
1832 1834 pushed.
1833 1835
1834 1836 The following special named paths exist:
1835 1837
1836 1838 "default"
1837 1839 The URL or directory to use when no source or remote is specified.
1838 1840
1839 1841 'hg clone' will automatically define this path to the location the
1840 1842 repository was cloned from.
1841 1843
1842 1844 "default-push"
1843 1845 (deprecated) The URL or directory for the default 'hg push' location.
1844 1846 "default:pushurl" should be used instead.
1845 1847
1846 1848 $ hg help glossary.mcguffin
1847 1849 abort: help section not found: glossary.mcguffin
1848 1850 [255]
1849 1851
1850 1852 $ hg help glossary.mc.guffin
1851 1853 abort: help section not found: glossary.mc.guffin
1852 1854 [255]
1853 1855
1854 1856 $ hg help template.files
1855 1857 files List of strings. All files modified, added, or removed by
1856 1858 this changeset.
1857 1859 files(pattern)
1858 1860 All files of the current changeset matching the pattern. See
1859 1861 'hg help patterns'.
1860 1862
1861 1863 Test section lookup by translated message
1862 1864
1863 1865 str.lower() instead of encoding.lower(str) on translated message might
1864 1866 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1865 1867 as the second or later byte of multi-byte character.
1866 1868
1867 1869 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1868 1870 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1869 1871 replacement makes message meaningless.
1870 1872
1871 1873 This tests that section lookup by translated string isn't broken by
1872 1874 such str.lower().
1873 1875
1874 1876 $ "$PYTHON" <<EOF
1875 1877 > def escape(s):
1876 1878 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1877 1879 > # translation of "record" in ja_JP.cp932
1878 1880 > upper = b"\x8bL\x98^"
1879 1881 > # str.lower()-ed section name should be treated as different one
1880 1882 > lower = b"\x8bl\x98^"
1881 1883 > with open('ambiguous.py', 'wb') as fp:
1882 1884 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1883 1885 > u'''summary of extension
1884 1886 >
1885 1887 > %s
1886 1888 > ----
1887 1889 >
1888 1890 > Upper name should show only this message
1889 1891 >
1890 1892 > %s
1891 1893 > ----
1892 1894 >
1893 1895 > Lower name should show only this message
1894 1896 >
1895 1897 > subsequent section
1896 1898 > ------------------
1897 1899 >
1898 1900 > This should be hidden at 'hg help ambiguous' with section name.
1899 1901 > '''
1900 1902 > """ % (escape(upper), escape(lower)))
1901 1903 > EOF
1902 1904
1903 1905 $ cat >> $HGRCPATH <<EOF
1904 1906 > [extensions]
1905 1907 > ambiguous = ./ambiguous.py
1906 1908 > EOF
1907 1909
1908 1910 $ "$PYTHON" <<EOF | sh
1909 1911 > from mercurial import pycompat
1910 1912 > upper = b"\x8bL\x98^"
1911 1913 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1912 1914 > EOF
1913 1915 \x8bL\x98^ (esc)
1914 1916 ----
1915 1917
1916 1918 Upper name should show only this message
1917 1919
1918 1920
1919 1921 $ "$PYTHON" <<EOF | sh
1920 1922 > from mercurial import pycompat
1921 1923 > lower = b"\x8bl\x98^"
1922 1924 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1923 1925 > EOF
1924 1926 \x8bl\x98^ (esc)
1925 1927 ----
1926 1928
1927 1929 Lower name should show only this message
1928 1930
1929 1931
1930 1932 $ cat >> $HGRCPATH <<EOF
1931 1933 > [extensions]
1932 1934 > ambiguous = !
1933 1935 > EOF
1934 1936
1935 1937 Show help content of disabled extensions
1936 1938
1937 1939 $ cat >> $HGRCPATH <<EOF
1938 1940 > [extensions]
1939 1941 > ambiguous = !./ambiguous.py
1940 1942 > EOF
1941 1943 $ hg help -e ambiguous
1942 1944 ambiguous extension - (no help text available)
1943 1945
1944 1946 (use 'hg help extensions' for information on enabling extensions)
1945 1947
1946 1948 Test dynamic list of merge tools only shows up once
1947 1949 $ hg help merge-tools
1948 1950 Merge Tools
1949 1951 """""""""""
1950 1952
1951 1953 To merge files Mercurial uses merge tools.
1952 1954
1953 1955 A merge tool combines two different versions of a file into a merged file.
1954 1956 Merge tools are given the two files and the greatest common ancestor of
1955 1957 the two file versions, so they can determine the changes made on both
1956 1958 branches.
1957 1959
1958 1960 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1959 1961 backout' and in several extensions.
1960 1962
1961 1963 Usually, the merge tool tries to automatically reconcile the files by
1962 1964 combining all non-overlapping changes that occurred separately in the two
1963 1965 different evolutions of the same initial base file. Furthermore, some
1964 1966 interactive merge programs make it easier to manually resolve conflicting
1965 1967 merges, either in a graphical way, or by inserting some conflict markers.
1966 1968 Mercurial does not include any interactive merge programs but relies on
1967 1969 external tools for that.
1968 1970
1969 1971 Available merge tools
1970 1972 =====================
1971 1973
1972 1974 External merge tools and their properties are configured in the merge-
1973 1975 tools configuration section - see hgrc(5) - but they can often just be
1974 1976 named by their executable.
1975 1977
1976 1978 A merge tool is generally usable if its executable can be found on the
1977 1979 system and if it can handle the merge. The executable is found if it is an
1978 1980 absolute or relative executable path or the name of an application in the
1979 1981 executable search path. The tool is assumed to be able to handle the merge
1980 1982 if it can handle symlinks if the file is a symlink, if it can handle
1981 1983 binary files if the file is binary, and if a GUI is available if the tool
1982 1984 requires a GUI.
1983 1985
1984 1986 There are some internal merge tools which can be used. The internal merge
1985 1987 tools are:
1986 1988
1987 1989 ":dump"
1988 1990 Creates three versions of the files to merge, containing the contents of
1989 1991 local, other and base. These files can then be used to perform a merge
1990 1992 manually. If the file to be merged is named "a.txt", these files will
1991 1993 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1992 1994 they will be placed in the same directory as "a.txt".
1993 1995
1994 1996 This implies premerge. Therefore, files aren't dumped, if premerge runs
1995 1997 successfully. Use :forcedump to forcibly write files out.
1996 1998
1997 1999 (actual capabilities: binary, symlink)
1998 2000
1999 2001 ":fail"
2000 2002 Rather than attempting to merge files that were modified on both
2001 2003 branches, it marks them as unresolved. The resolve command must be used
2002 2004 to resolve these conflicts.
2003 2005
2004 2006 (actual capabilities: binary, symlink)
2005 2007
2006 2008 ":forcedump"
2007 2009 Creates three versions of the files as same as :dump, but omits
2008 2010 premerge.
2009 2011
2010 2012 (actual capabilities: binary, symlink)
2011 2013
2012 2014 ":local"
2013 2015 Uses the local 'p1()' version of files as the merged version.
2014 2016
2015 2017 (actual capabilities: binary, symlink)
2016 2018
2017 2019 ":merge"
2018 2020 Uses the internal non-interactive simple merge algorithm for merging
2019 2021 files. It will fail if there are any conflicts and leave markers in the
2020 2022 partially merged file. Markers will have two sections, one for each side
2021 2023 of merge.
2022 2024
2023 2025 ":merge-local"
2024 2026 Like :merge, but resolve all conflicts non-interactively in favor of the
2025 2027 local 'p1()' changes.
2026 2028
2027 2029 ":merge-other"
2028 2030 Like :merge, but resolve all conflicts non-interactively in favor of the
2029 2031 other 'p2()' changes.
2030 2032
2031 2033 ":merge3"
2032 2034 Uses the internal non-interactive simple merge algorithm for merging
2033 2035 files. It will fail if there are any conflicts and leave markers in the
2034 2036 partially merged file. Marker will have three sections, one from each
2035 2037 side of the merge and one for the base content.
2036 2038
2037 2039 ":other"
2038 2040 Uses the other 'p2()' version of files as the merged version.
2039 2041
2040 2042 (actual capabilities: binary, symlink)
2041 2043
2042 2044 ":prompt"
2043 2045 Asks the user which of the local 'p1()' or the other 'p2()' version to
2044 2046 keep as the merged version.
2045 2047
2046 2048 (actual capabilities: binary, symlink)
2047 2049
2048 2050 ":tagmerge"
2049 2051 Uses the internal tag merge algorithm (experimental).
2050 2052
2051 2053 ":union"
2052 2054 Uses the internal non-interactive simple merge algorithm for merging
2053 2055 files. It will use both left and right sides for conflict regions. No
2054 2056 markers are inserted.
2055 2057
2056 2058 Internal tools are always available and do not require a GUI but will by
2057 2059 default not handle symlinks or binary files. See next section for detail
2058 2060 about "actual capabilities" described above.
2059 2061
2060 2062 Choosing a merge tool
2061 2063 =====================
2062 2064
2063 2065 Mercurial uses these rules when deciding which merge tool to use:
2064 2066
2065 2067 1. If a tool has been specified with the --tool option to merge or
2066 2068 resolve, it is used. If it is the name of a tool in the merge-tools
2067 2069 configuration, its configuration is used. Otherwise the specified tool
2068 2070 must be executable by the shell.
2069 2071 2. If the "HGMERGE" environment variable is present, its value is used and
2070 2072 must be executable by the shell.
2071 2073 3. If the filename of the file to be merged matches any of the patterns in
2072 2074 the merge-patterns configuration section, the first usable merge tool
2073 2075 corresponding to a matching pattern is used.
2074 2076 4. If ui.merge is set it will be considered next. If the value is not the
2075 2077 name of a configured tool, the specified value is used and must be
2076 2078 executable by the shell. Otherwise the named tool is used if it is
2077 2079 usable.
2078 2080 5. If any usable merge tools are present in the merge-tools configuration
2079 2081 section, the one with the highest priority is used.
2080 2082 6. If a program named "hgmerge" can be found on the system, it is used -
2081 2083 but it will by default not be used for symlinks and binary files.
2082 2084 7. If the file to be merged is not binary and is not a symlink, then
2083 2085 internal ":merge" is used.
2084 2086 8. Otherwise, ":prompt" is used.
2085 2087
2086 2088 For historical reason, Mercurial treats merge tools as below while
2087 2089 examining rules above.
2088 2090
2089 2091 step specified via binary symlink
2090 2092 ----------------------------------
2091 2093 1. --tool o/o o/o
2092 2094 2. HGMERGE o/o o/o
2093 2095 3. merge-patterns o/o(*) x/?(*)
2094 2096 4. ui.merge x/?(*) x/?(*)
2095 2097
2096 2098 Each capability column indicates Mercurial behavior for internal/external
2097 2099 merge tools at examining each rule.
2098 2100
2099 2101 - "o": "assume that a tool has capability"
2100 2102 - "x": "assume that a tool does not have capability"
2101 2103 - "?": "check actual capability of a tool"
2102 2104
2103 2105 If "merge.strict-capability-check" configuration is true, Mercurial checks
2104 2106 capabilities of merge tools strictly in (*) cases above (= each capability
2105 2107 column becomes "?/?"). It is false by default for backward compatibility.
2106 2108
2107 2109 Note:
2108 2110 After selecting a merge program, Mercurial will by default attempt to
2109 2111 merge the files using a simple merge algorithm first. Only if it
2110 2112 doesn't succeed because of conflicting changes will Mercurial actually
2111 2113 execute the merge program. Whether to use the simple merge algorithm
2112 2114 first can be controlled by the premerge setting of the merge tool.
2113 2115 Premerge is enabled by default unless the file is binary or a symlink.
2114 2116
2115 2117 See the merge-tools and ui sections of hgrc(5) for details on the
2116 2118 configuration of merge tools.
2117 2119
2118 2120 Compression engines listed in `hg help bundlespec`
2119 2121
2120 2122 $ hg help bundlespec | grep gzip
2121 2123 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2122 2124 An algorithm that produces smaller bundles than "gzip".
2123 2125 This engine will likely produce smaller bundles than "gzip" but will be
2124 2126 "gzip"
2125 2127 better compression than "gzip". It also frequently yields better (?)
2126 2128
2127 2129 Test usage of section marks in help documents
2128 2130
2129 2131 $ cd "$TESTDIR"/../doc
2130 2132 $ "$PYTHON" check-seclevel.py
2131 2133 $ cd $TESTTMP
2132 2134
2133 2135 #if serve
2134 2136
2135 2137 Test the help pages in hgweb.
2136 2138
2137 2139 Dish up an empty repo; serve it cold.
2138 2140
2139 2141 $ hg init "$TESTTMP/test"
2140 2142 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2141 2143 $ cat hg.pid >> $DAEMON_PIDS
2142 2144
2143 2145 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2144 2146 200 Script output follows
2145 2147
2146 2148 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2147 2149 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2148 2150 <head>
2149 2151 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2150 2152 <meta name="robots" content="index, nofollow" />
2151 2153 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2152 2154 <script type="text/javascript" src="/static/mercurial.js"></script>
2153 2155
2154 2156 <title>Help: Index</title>
2155 2157 </head>
2156 2158 <body>
2157 2159
2158 2160 <div class="container">
2159 2161 <div class="menu">
2160 2162 <div class="logo">
2161 2163 <a href="https://mercurial-scm.org/">
2162 2164 <img src="/static/hglogo.png" alt="mercurial" /></a>
2163 2165 </div>
2164 2166 <ul>
2165 2167 <li><a href="/shortlog">log</a></li>
2166 2168 <li><a href="/graph">graph</a></li>
2167 2169 <li><a href="/tags">tags</a></li>
2168 2170 <li><a href="/bookmarks">bookmarks</a></li>
2169 2171 <li><a href="/branches">branches</a></li>
2170 2172 </ul>
2171 2173 <ul>
2172 2174 <li class="active">help</li>
2173 2175 </ul>
2174 2176 </div>
2175 2177
2176 2178 <div class="main">
2177 2179 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2178 2180
2179 2181 <form class="search" action="/log">
2180 2182
2181 2183 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2182 2184 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2183 2185 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2184 2186 </form>
2185 2187 <table class="bigtable">
2186 2188 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2187 2189
2188 2190 <tr><td>
2189 2191 <a href="/help/bundlespec">
2190 2192 bundlespec
2191 2193 </a>
2192 2194 </td><td>
2193 2195 Bundle File Formats
2194 2196 </td></tr>
2195 2197 <tr><td>
2196 2198 <a href="/help/color">
2197 2199 color
2198 2200 </a>
2199 2201 </td><td>
2200 2202 Colorizing Outputs
2201 2203 </td></tr>
2202 2204 <tr><td>
2203 2205 <a href="/help/config">
2204 2206 config
2205 2207 </a>
2206 2208 </td><td>
2207 2209 Configuration Files
2208 2210 </td></tr>
2209 2211 <tr><td>
2210 2212 <a href="/help/dates">
2211 2213 dates
2212 2214 </a>
2213 2215 </td><td>
2214 2216 Date Formats
2215 2217 </td></tr>
2216 2218 <tr><td>
2217 2219 <a href="/help/deprecated">
2218 2220 deprecated
2219 2221 </a>
2220 2222 </td><td>
2221 2223 Deprecated Features
2222 2224 </td></tr>
2223 2225 <tr><td>
2224 2226 <a href="/help/diffs">
2225 2227 diffs
2226 2228 </a>
2227 2229 </td><td>
2228 2230 Diff Formats
2229 2231 </td></tr>
2230 2232 <tr><td>
2231 2233 <a href="/help/environment">
2232 2234 environment
2233 2235 </a>
2234 2236 </td><td>
2235 2237 Environment Variables
2236 2238 </td></tr>
2237 2239 <tr><td>
2238 2240 <a href="/help/extensions">
2239 2241 extensions
2240 2242 </a>
2241 2243 </td><td>
2242 2244 Using Additional Features
2243 2245 </td></tr>
2244 2246 <tr><td>
2245 2247 <a href="/help/filesets">
2246 2248 filesets
2247 2249 </a>
2248 2250 </td><td>
2249 2251 Specifying File Sets
2250 2252 </td></tr>
2251 2253 <tr><td>
2252 2254 <a href="/help/flags">
2253 2255 flags
2254 2256 </a>
2255 2257 </td><td>
2256 2258 Command-line flags
2257 2259 </td></tr>
2258 2260 <tr><td>
2259 2261 <a href="/help/glossary">
2260 2262 glossary
2261 2263 </a>
2262 2264 </td><td>
2263 2265 Glossary
2264 2266 </td></tr>
2265 2267 <tr><td>
2266 2268 <a href="/help/hgignore">
2267 2269 hgignore
2268 2270 </a>
2269 2271 </td><td>
2270 2272 Syntax for Mercurial Ignore Files
2271 2273 </td></tr>
2272 2274 <tr><td>
2273 2275 <a href="/help/hgweb">
2274 2276 hgweb
2275 2277 </a>
2276 2278 </td><td>
2277 2279 Configuring hgweb
2278 2280 </td></tr>
2279 2281 <tr><td>
2280 2282 <a href="/help/internals">
2281 2283 internals
2282 2284 </a>
2283 2285 </td><td>
2284 2286 Technical implementation topics
2285 2287 </td></tr>
2286 2288 <tr><td>
2287 2289 <a href="/help/merge-tools">
2288 2290 merge-tools
2289 2291 </a>
2290 2292 </td><td>
2291 2293 Merge Tools
2292 2294 </td></tr>
2293 2295 <tr><td>
2294 2296 <a href="/help/pager">
2295 2297 pager
2296 2298 </a>
2297 2299 </td><td>
2298 2300 Pager Support
2299 2301 </td></tr>
2300 2302 <tr><td>
2301 2303 <a href="/help/patterns">
2302 2304 patterns
2303 2305 </a>
2304 2306 </td><td>
2305 2307 File Name Patterns
2306 2308 </td></tr>
2307 2309 <tr><td>
2308 2310 <a href="/help/phases">
2309 2311 phases
2310 2312 </a>
2311 2313 </td><td>
2312 2314 Working with Phases
2313 2315 </td></tr>
2314 2316 <tr><td>
2315 2317 <a href="/help/revisions">
2316 2318 revisions
2317 2319 </a>
2318 2320 </td><td>
2319 2321 Specifying Revisions
2320 2322 </td></tr>
2321 2323 <tr><td>
2322 2324 <a href="/help/scripting">
2323 2325 scripting
2324 2326 </a>
2325 2327 </td><td>
2326 2328 Using Mercurial from scripts and automation
2327 2329 </td></tr>
2328 2330 <tr><td>
2329 2331 <a href="/help/subrepos">
2330 2332 subrepos
2331 2333 </a>
2332 2334 </td><td>
2333 2335 Subrepositories
2334 2336 </td></tr>
2335 2337 <tr><td>
2336 2338 <a href="/help/templating">
2337 2339 templating
2338 2340 </a>
2339 2341 </td><td>
2340 2342 Template Usage
2341 2343 </td></tr>
2342 2344 <tr><td>
2343 2345 <a href="/help/urls">
2344 2346 urls
2345 2347 </a>
2346 2348 </td><td>
2347 2349 URL Paths
2348 2350 </td></tr>
2349 2351 <tr><td>
2350 2352 <a href="/help/topic-containing-verbose">
2351 2353 topic-containing-verbose
2352 2354 </a>
2353 2355 </td><td>
2354 2356 This is the topic to test omit indicating.
2355 2357 </td></tr>
2356 2358
2357 2359
2358 2360 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2359 2361
2360 2362 <tr><td>
2361 2363 <a href="/help/abort">
2362 2364 abort
2363 2365 </a>
2364 2366 </td><td>
2365 2367 abort an unfinished operation (EXPERIMENTAL)
2366 2368 </td></tr>
2367 2369 <tr><td>
2368 2370 <a href="/help/add">
2369 2371 add
2370 2372 </a>
2371 2373 </td><td>
2372 2374 add the specified files on the next commit
2373 2375 </td></tr>
2374 2376 <tr><td>
2375 2377 <a href="/help/annotate">
2376 2378 annotate
2377 2379 </a>
2378 2380 </td><td>
2379 2381 show changeset information by line for each file
2380 2382 </td></tr>
2381 2383 <tr><td>
2382 2384 <a href="/help/clone">
2383 2385 clone
2384 2386 </a>
2385 2387 </td><td>
2386 2388 make a copy of an existing repository
2387 2389 </td></tr>
2388 2390 <tr><td>
2389 2391 <a href="/help/commit">
2390 2392 commit
2391 2393 </a>
2392 2394 </td><td>
2393 2395 commit the specified files or all outstanding changes
2394 2396 </td></tr>
2395 2397 <tr><td>
2396 2398 <a href="/help/continue">
2397 2399 continue
2398 2400 </a>
2399 2401 </td><td>
2400 2402 resumes an interrupted operation (EXPERIMENTAL)
2401 2403 </td></tr>
2402 2404 <tr><td>
2403 2405 <a href="/help/diff">
2404 2406 diff
2405 2407 </a>
2406 2408 </td><td>
2407 2409 diff repository (or selected files)
2408 2410 </td></tr>
2409 2411 <tr><td>
2410 2412 <a href="/help/export">
2411 2413 export
2412 2414 </a>
2413 2415 </td><td>
2414 2416 dump the header and diffs for one or more changesets
2415 2417 </td></tr>
2416 2418 <tr><td>
2417 2419 <a href="/help/forget">
2418 2420 forget
2419 2421 </a>
2420 2422 </td><td>
2421 2423 forget the specified files on the next commit
2422 2424 </td></tr>
2423 2425 <tr><td>
2424 2426 <a href="/help/init">
2425 2427 init
2426 2428 </a>
2427 2429 </td><td>
2428 2430 create a new repository in the given directory
2429 2431 </td></tr>
2430 2432 <tr><td>
2431 2433 <a href="/help/log">
2432 2434 log
2433 2435 </a>
2434 2436 </td><td>
2435 2437 show revision history of entire repository or files
2436 2438 </td></tr>
2437 2439 <tr><td>
2438 2440 <a href="/help/merge">
2439 2441 merge
2440 2442 </a>
2441 2443 </td><td>
2442 2444 merge another revision into working directory
2443 2445 </td></tr>
2444 2446 <tr><td>
2445 2447 <a href="/help/pull">
2446 2448 pull
2447 2449 </a>
2448 2450 </td><td>
2449 2451 pull changes from the specified source
2450 2452 </td></tr>
2451 2453 <tr><td>
2452 2454 <a href="/help/push">
2453 2455 push
2454 2456 </a>
2455 2457 </td><td>
2456 2458 push changes to the specified destination
2457 2459 </td></tr>
2458 2460 <tr><td>
2459 2461 <a href="/help/remove">
2460 2462 remove
2461 2463 </a>
2462 2464 </td><td>
2463 2465 remove the specified files on the next commit
2464 2466 </td></tr>
2465 2467 <tr><td>
2466 2468 <a href="/help/serve">
2467 2469 serve
2468 2470 </a>
2469 2471 </td><td>
2470 2472 start stand-alone webserver
2471 2473 </td></tr>
2472 2474 <tr><td>
2473 2475 <a href="/help/status">
2474 2476 status
2475 2477 </a>
2476 2478 </td><td>
2477 2479 show changed files in the working directory
2478 2480 </td></tr>
2479 2481 <tr><td>
2480 2482 <a href="/help/summary">
2481 2483 summary
2482 2484 </a>
2483 2485 </td><td>
2484 2486 summarize working directory state
2485 2487 </td></tr>
2486 2488 <tr><td>
2487 2489 <a href="/help/update">
2488 2490 update
2489 2491 </a>
2490 2492 </td><td>
2491 2493 update working directory (or switch revisions)
2492 2494 </td></tr>
2493 2495
2494 2496
2495 2497
2496 2498 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2497 2499
2498 2500 <tr><td>
2499 2501 <a href="/help/addremove">
2500 2502 addremove
2501 2503 </a>
2502 2504 </td><td>
2503 2505 add all new files, delete all missing files
2504 2506 </td></tr>
2505 2507 <tr><td>
2506 2508 <a href="/help/archive">
2507 2509 archive
2508 2510 </a>
2509 2511 </td><td>
2510 2512 create an unversioned archive of a repository revision
2511 2513 </td></tr>
2512 2514 <tr><td>
2513 2515 <a href="/help/backout">
2514 2516 backout
2515 2517 </a>
2516 2518 </td><td>
2517 2519 reverse effect of earlier changeset
2518 2520 </td></tr>
2519 2521 <tr><td>
2520 2522 <a href="/help/bisect">
2521 2523 bisect
2522 2524 </a>
2523 2525 </td><td>
2524 2526 subdivision search of changesets
2525 2527 </td></tr>
2526 2528 <tr><td>
2527 2529 <a href="/help/bookmarks">
2528 2530 bookmarks
2529 2531 </a>
2530 2532 </td><td>
2531 2533 create a new bookmark or list existing bookmarks
2532 2534 </td></tr>
2533 2535 <tr><td>
2534 2536 <a href="/help/branch">
2535 2537 branch
2536 2538 </a>
2537 2539 </td><td>
2538 2540 set or show the current branch name
2539 2541 </td></tr>
2540 2542 <tr><td>
2541 2543 <a href="/help/branches">
2542 2544 branches
2543 2545 </a>
2544 2546 </td><td>
2545 2547 list repository named branches
2546 2548 </td></tr>
2547 2549 <tr><td>
2548 2550 <a href="/help/bundle">
2549 2551 bundle
2550 2552 </a>
2551 2553 </td><td>
2552 2554 create a bundle file
2553 2555 </td></tr>
2554 2556 <tr><td>
2555 2557 <a href="/help/cat">
2556 2558 cat
2557 2559 </a>
2558 2560 </td><td>
2559 2561 output the current or given revision of files
2560 2562 </td></tr>
2561 2563 <tr><td>
2562 2564 <a href="/help/config">
2563 2565 config
2564 2566 </a>
2565 2567 </td><td>
2566 2568 show combined config settings from all hgrc files
2567 2569 </td></tr>
2568 2570 <tr><td>
2569 2571 <a href="/help/copy">
2570 2572 copy
2571 2573 </a>
2572 2574 </td><td>
2573 2575 mark files as copied for the next commit
2574 2576 </td></tr>
2575 2577 <tr><td>
2576 2578 <a href="/help/files">
2577 2579 files
2578 2580 </a>
2579 2581 </td><td>
2580 2582 list tracked files
2581 2583 </td></tr>
2582 2584 <tr><td>
2583 2585 <a href="/help/graft">
2584 2586 graft
2585 2587 </a>
2586 2588 </td><td>
2587 2589 copy changes from other branches onto the current branch
2588 2590 </td></tr>
2589 2591 <tr><td>
2590 2592 <a href="/help/grep">
2591 2593 grep
2592 2594 </a>
2593 2595 </td><td>
2594 2596 search for a pattern in specified files
2595 2597 </td></tr>
2596 2598 <tr><td>
2597 2599 <a href="/help/hashelp">
2598 2600 hashelp
2599 2601 </a>
2600 2602 </td><td>
2601 2603 Extension command's help
2602 2604 </td></tr>
2603 2605 <tr><td>
2604 2606 <a href="/help/heads">
2605 2607 heads
2606 2608 </a>
2607 2609 </td><td>
2608 2610 show branch heads
2609 2611 </td></tr>
2610 2612 <tr><td>
2611 2613 <a href="/help/help">
2612 2614 help
2613 2615 </a>
2614 2616 </td><td>
2615 2617 show help for a given topic or a help overview
2616 2618 </td></tr>
2617 2619 <tr><td>
2618 2620 <a href="/help/hgalias">
2619 2621 hgalias
2620 2622 </a>
2621 2623 </td><td>
2622 2624 My doc
2623 2625 </td></tr>
2624 2626 <tr><td>
2625 2627 <a href="/help/hgaliasnodoc">
2626 2628 hgaliasnodoc
2627 2629 </a>
2628 2630 </td><td>
2629 2631 summarize working directory state
2630 2632 </td></tr>
2631 2633 <tr><td>
2632 2634 <a href="/help/identify">
2633 2635 identify
2634 2636 </a>
2635 2637 </td><td>
2636 2638 identify the working directory or specified revision
2637 2639 </td></tr>
2638 2640 <tr><td>
2639 2641 <a href="/help/import">
2640 2642 import
2641 2643 </a>
2642 2644 </td><td>
2643 2645 import an ordered set of patches
2644 2646 </td></tr>
2645 2647 <tr><td>
2646 2648 <a href="/help/incoming">
2647 2649 incoming
2648 2650 </a>
2649 2651 </td><td>
2650 2652 show new changesets found in source
2651 2653 </td></tr>
2652 2654 <tr><td>
2653 2655 <a href="/help/manifest">
2654 2656 manifest
2655 2657 </a>
2656 2658 </td><td>
2657 2659 output the current or given revision of the project manifest
2658 2660 </td></tr>
2659 2661 <tr><td>
2660 2662 <a href="/help/nohelp">
2661 2663 nohelp
2662 2664 </a>
2663 2665 </td><td>
2664 2666 (no help text available)
2665 2667 </td></tr>
2666 2668 <tr><td>
2667 2669 <a href="/help/outgoing">
2668 2670 outgoing
2669 2671 </a>
2670 2672 </td><td>
2671 2673 show changesets not found in the destination
2672 2674 </td></tr>
2673 2675 <tr><td>
2674 2676 <a href="/help/paths">
2675 2677 paths
2676 2678 </a>
2677 2679 </td><td>
2678 2680 show aliases for remote repositories
2679 2681 </td></tr>
2680 2682 <tr><td>
2681 2683 <a href="/help/phase">
2682 2684 phase
2683 2685 </a>
2684 2686 </td><td>
2685 2687 set or show the current phase name
2686 2688 </td></tr>
2687 2689 <tr><td>
2688 2690 <a href="/help/recover">
2689 2691 recover
2690 2692 </a>
2691 2693 </td><td>
2692 2694 roll back an interrupted transaction
2693 2695 </td></tr>
2694 2696 <tr><td>
2695 2697 <a href="/help/rename">
2696 2698 rename
2697 2699 </a>
2698 2700 </td><td>
2699 2701 rename files; equivalent of copy + remove
2700 2702 </td></tr>
2701 2703 <tr><td>
2702 2704 <a href="/help/resolve">
2703 2705 resolve
2704 2706 </a>
2705 2707 </td><td>
2706 2708 redo merges or set/view the merge status of files
2707 2709 </td></tr>
2708 2710 <tr><td>
2709 2711 <a href="/help/revert">
2710 2712 revert
2711 2713 </a>
2712 2714 </td><td>
2713 2715 restore files to their checkout state
2714 2716 </td></tr>
2715 2717 <tr><td>
2716 2718 <a href="/help/root">
2717 2719 root
2718 2720 </a>
2719 2721 </td><td>
2720 2722 print the root (top) of the current working directory
2721 2723 </td></tr>
2722 2724 <tr><td>
2723 2725 <a href="/help/shellalias">
2724 2726 shellalias
2725 2727 </a>
2726 2728 </td><td>
2727 2729 (no help text available)
2728 2730 </td></tr>
2729 2731 <tr><td>
2730 2732 <a href="/help/shelve">
2731 2733 shelve
2732 2734 </a>
2733 2735 </td><td>
2734 2736 save and set aside changes from the working directory
2735 2737 </td></tr>
2736 2738 <tr><td>
2737 2739 <a href="/help/tag">
2738 2740 tag
2739 2741 </a>
2740 2742 </td><td>
2741 2743 add one or more tags for the current or given revision
2742 2744 </td></tr>
2743 2745 <tr><td>
2744 2746 <a href="/help/tags">
2745 2747 tags
2746 2748 </a>
2747 2749 </td><td>
2748 2750 list repository tags
2749 2751 </td></tr>
2750 2752 <tr><td>
2751 2753 <a href="/help/unbundle">
2752 2754 unbundle
2753 2755 </a>
2754 2756 </td><td>
2755 2757 apply one or more bundle files
2756 2758 </td></tr>
2757 2759 <tr><td>
2758 2760 <a href="/help/unshelve">
2759 2761 unshelve
2760 2762 </a>
2761 2763 </td><td>
2762 2764 restore a shelved change to the working directory
2763 2765 </td></tr>
2764 2766 <tr><td>
2765 2767 <a href="/help/verify">
2766 2768 verify
2767 2769 </a>
2768 2770 </td><td>
2769 2771 verify the integrity of the repository
2770 2772 </td></tr>
2771 2773 <tr><td>
2772 2774 <a href="/help/version">
2773 2775 version
2774 2776 </a>
2775 2777 </td><td>
2776 2778 output version and copyright information
2777 2779 </td></tr>
2778 2780
2779 2781
2780 2782 </table>
2781 2783 </div>
2782 2784 </div>
2783 2785
2784 2786
2785 2787
2786 2788 </body>
2787 2789 </html>
2788 2790
2789 2791
2790 2792 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2791 2793 200 Script output follows
2792 2794
2793 2795 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2794 2796 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2795 2797 <head>
2796 2798 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2797 2799 <meta name="robots" content="index, nofollow" />
2798 2800 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2799 2801 <script type="text/javascript" src="/static/mercurial.js"></script>
2800 2802
2801 2803 <title>Help: add</title>
2802 2804 </head>
2803 2805 <body>
2804 2806
2805 2807 <div class="container">
2806 2808 <div class="menu">
2807 2809 <div class="logo">
2808 2810 <a href="https://mercurial-scm.org/">
2809 2811 <img src="/static/hglogo.png" alt="mercurial" /></a>
2810 2812 </div>
2811 2813 <ul>
2812 2814 <li><a href="/shortlog">log</a></li>
2813 2815 <li><a href="/graph">graph</a></li>
2814 2816 <li><a href="/tags">tags</a></li>
2815 2817 <li><a href="/bookmarks">bookmarks</a></li>
2816 2818 <li><a href="/branches">branches</a></li>
2817 2819 </ul>
2818 2820 <ul>
2819 2821 <li class="active"><a href="/help">help</a></li>
2820 2822 </ul>
2821 2823 </div>
2822 2824
2823 2825 <div class="main">
2824 2826 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2825 2827 <h3>Help: add</h3>
2826 2828
2827 2829 <form class="search" action="/log">
2828 2830
2829 2831 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2830 2832 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2831 2833 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2832 2834 </form>
2833 2835 <div id="doc">
2834 2836 <p>
2835 2837 hg add [OPTION]... [FILE]...
2836 2838 </p>
2837 2839 <p>
2838 2840 add the specified files on the next commit
2839 2841 </p>
2840 2842 <p>
2841 2843 Schedule files to be version controlled and added to the
2842 2844 repository.
2843 2845 </p>
2844 2846 <p>
2845 2847 The files will be added to the repository at the next commit. To
2846 2848 undo an add before that, see 'hg forget'.
2847 2849 </p>
2848 2850 <p>
2849 2851 If no names are given, add all files to the repository (except
2850 2852 files matching &quot;.hgignore&quot;).
2851 2853 </p>
2852 2854 <p>
2853 2855 Examples:
2854 2856 </p>
2855 2857 <ul>
2856 2858 <li> New (unknown) files are added automatically by 'hg add':
2857 2859 <pre>
2858 2860 \$ ls (re)
2859 2861 foo.c
2860 2862 \$ hg status (re)
2861 2863 ? foo.c
2862 2864 \$ hg add (re)
2863 2865 adding foo.c
2864 2866 \$ hg status (re)
2865 2867 A foo.c
2866 2868 </pre>
2867 2869 <li> Specific files to be added can be specified:
2868 2870 <pre>
2869 2871 \$ ls (re)
2870 2872 bar.c foo.c
2871 2873 \$ hg status (re)
2872 2874 ? bar.c
2873 2875 ? foo.c
2874 2876 \$ hg add bar.c (re)
2875 2877 \$ hg status (re)
2876 2878 A bar.c
2877 2879 ? foo.c
2878 2880 </pre>
2879 2881 </ul>
2880 2882 <p>
2881 2883 Returns 0 if all files are successfully added.
2882 2884 </p>
2883 2885 <p>
2884 2886 options ([+] can be repeated):
2885 2887 </p>
2886 2888 <table>
2887 2889 <tr><td>-I</td>
2888 2890 <td>--include PATTERN [+]</td>
2889 2891 <td>include names matching the given patterns</td></tr>
2890 2892 <tr><td>-X</td>
2891 2893 <td>--exclude PATTERN [+]</td>
2892 2894 <td>exclude names matching the given patterns</td></tr>
2893 2895 <tr><td>-S</td>
2894 2896 <td>--subrepos</td>
2895 2897 <td>recurse into subrepositories</td></tr>
2896 2898 <tr><td>-n</td>
2897 2899 <td>--dry-run</td>
2898 2900 <td>do not perform actions, just print output</td></tr>
2899 2901 </table>
2900 2902 <p>
2901 2903 global options ([+] can be repeated):
2902 2904 </p>
2903 2905 <table>
2904 2906 <tr><td>-R</td>
2905 2907 <td>--repository REPO</td>
2906 2908 <td>repository root directory or name of overlay bundle file</td></tr>
2907 2909 <tr><td></td>
2908 2910 <td>--cwd DIR</td>
2909 2911 <td>change working directory</td></tr>
2910 2912 <tr><td>-y</td>
2911 2913 <td>--noninteractive</td>
2912 2914 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2913 2915 <tr><td>-q</td>
2914 2916 <td>--quiet</td>
2915 2917 <td>suppress output</td></tr>
2916 2918 <tr><td>-v</td>
2917 2919 <td>--verbose</td>
2918 2920 <td>enable additional output</td></tr>
2919 2921 <tr><td></td>
2920 2922 <td>--color TYPE</td>
2921 2923 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2922 2924 <tr><td></td>
2923 2925 <td>--config CONFIG [+]</td>
2924 2926 <td>set/override config option (use 'section.name=value')</td></tr>
2925 2927 <tr><td></td>
2926 2928 <td>--debug</td>
2927 2929 <td>enable debugging output</td></tr>
2928 2930 <tr><td></td>
2929 2931 <td>--debugger</td>
2930 2932 <td>start debugger</td></tr>
2931 2933 <tr><td></td>
2932 2934 <td>--encoding ENCODE</td>
2933 2935 <td>set the charset encoding (default: ascii)</td></tr>
2934 2936 <tr><td></td>
2935 2937 <td>--encodingmode MODE</td>
2936 2938 <td>set the charset encoding mode (default: strict)</td></tr>
2937 2939 <tr><td></td>
2938 2940 <td>--traceback</td>
2939 2941 <td>always print a traceback on exception</td></tr>
2940 2942 <tr><td></td>
2941 2943 <td>--time</td>
2942 2944 <td>time how long the command takes</td></tr>
2943 2945 <tr><td></td>
2944 2946 <td>--profile</td>
2945 2947 <td>print command execution profile</td></tr>
2946 2948 <tr><td></td>
2947 2949 <td>--version</td>
2948 2950 <td>output version information and exit</td></tr>
2949 2951 <tr><td>-h</td>
2950 2952 <td>--help</td>
2951 2953 <td>display help and exit</td></tr>
2952 2954 <tr><td></td>
2953 2955 <td>--hidden</td>
2954 2956 <td>consider hidden changesets</td></tr>
2955 2957 <tr><td></td>
2956 2958 <td>--pager TYPE</td>
2957 2959 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2958 2960 </table>
2959 2961
2960 2962 </div>
2961 2963 </div>
2962 2964 </div>
2963 2965
2964 2966
2965 2967
2966 2968 </body>
2967 2969 </html>
2968 2970
2969 2971
2970 2972 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2971 2973 200 Script output follows
2972 2974
2973 2975 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2974 2976 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2975 2977 <head>
2976 2978 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2977 2979 <meta name="robots" content="index, nofollow" />
2978 2980 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2979 2981 <script type="text/javascript" src="/static/mercurial.js"></script>
2980 2982
2981 2983 <title>Help: remove</title>
2982 2984 </head>
2983 2985 <body>
2984 2986
2985 2987 <div class="container">
2986 2988 <div class="menu">
2987 2989 <div class="logo">
2988 2990 <a href="https://mercurial-scm.org/">
2989 2991 <img src="/static/hglogo.png" alt="mercurial" /></a>
2990 2992 </div>
2991 2993 <ul>
2992 2994 <li><a href="/shortlog">log</a></li>
2993 2995 <li><a href="/graph">graph</a></li>
2994 2996 <li><a href="/tags">tags</a></li>
2995 2997 <li><a href="/bookmarks">bookmarks</a></li>
2996 2998 <li><a href="/branches">branches</a></li>
2997 2999 </ul>
2998 3000 <ul>
2999 3001 <li class="active"><a href="/help">help</a></li>
3000 3002 </ul>
3001 3003 </div>
3002 3004
3003 3005 <div class="main">
3004 3006 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3005 3007 <h3>Help: remove</h3>
3006 3008
3007 3009 <form class="search" action="/log">
3008 3010
3009 3011 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3010 3012 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3011 3013 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3012 3014 </form>
3013 3015 <div id="doc">
3014 3016 <p>
3015 3017 hg remove [OPTION]... FILE...
3016 3018 </p>
3017 3019 <p>
3018 3020 aliases: rm
3019 3021 </p>
3020 3022 <p>
3021 3023 remove the specified files on the next commit
3022 3024 </p>
3023 3025 <p>
3024 3026 Schedule the indicated files for removal from the current branch.
3025 3027 </p>
3026 3028 <p>
3027 3029 This command schedules the files to be removed at the next commit.
3028 3030 To undo a remove before that, see 'hg revert'. To undo added
3029 3031 files, see 'hg forget'.
3030 3032 </p>
3031 3033 <p>
3032 3034 -A/--after can be used to remove only files that have already
3033 3035 been deleted, -f/--force can be used to force deletion, and -Af
3034 3036 can be used to remove files from the next revision without
3035 3037 deleting them from the working directory.
3036 3038 </p>
3037 3039 <p>
3038 3040 The following table details the behavior of remove for different
3039 3041 file states (columns) and option combinations (rows). The file
3040 3042 states are Added [A], Clean [C], Modified [M] and Missing [!]
3041 3043 (as reported by 'hg status'). The actions are Warn, Remove
3042 3044 (from branch) and Delete (from disk):
3043 3045 </p>
3044 3046 <table>
3045 3047 <tr><td>opt/state</td>
3046 3048 <td>A</td>
3047 3049 <td>C</td>
3048 3050 <td>M</td>
3049 3051 <td>!</td></tr>
3050 3052 <tr><td>none</td>
3051 3053 <td>W</td>
3052 3054 <td>RD</td>
3053 3055 <td>W</td>
3054 3056 <td>R</td></tr>
3055 3057 <tr><td>-f</td>
3056 3058 <td>R</td>
3057 3059 <td>RD</td>
3058 3060 <td>RD</td>
3059 3061 <td>R</td></tr>
3060 3062 <tr><td>-A</td>
3061 3063 <td>W</td>
3062 3064 <td>W</td>
3063 3065 <td>W</td>
3064 3066 <td>R</td></tr>
3065 3067 <tr><td>-Af</td>
3066 3068 <td>R</td>
3067 3069 <td>R</td>
3068 3070 <td>R</td>
3069 3071 <td>R</td></tr>
3070 3072 </table>
3071 3073 <p>
3072 3074 <b>Note:</b>
3073 3075 </p>
3074 3076 <p>
3075 3077 'hg remove' never deletes files in Added [A] state from the
3076 3078 working directory, not even if &quot;--force&quot; is specified.
3077 3079 </p>
3078 3080 <p>
3079 3081 Returns 0 on success, 1 if any warnings encountered.
3080 3082 </p>
3081 3083 <p>
3082 3084 options ([+] can be repeated):
3083 3085 </p>
3084 3086 <table>
3085 3087 <tr><td>-A</td>
3086 3088 <td>--after</td>
3087 3089 <td>record delete for missing files</td></tr>
3088 3090 <tr><td>-f</td>
3089 3091 <td>--force</td>
3090 3092 <td>forget added files, delete modified files</td></tr>
3091 3093 <tr><td>-S</td>
3092 3094 <td>--subrepos</td>
3093 3095 <td>recurse into subrepositories</td></tr>
3094 3096 <tr><td>-I</td>
3095 3097 <td>--include PATTERN [+]</td>
3096 3098 <td>include names matching the given patterns</td></tr>
3097 3099 <tr><td>-X</td>
3098 3100 <td>--exclude PATTERN [+]</td>
3099 3101 <td>exclude names matching the given patterns</td></tr>
3100 3102 <tr><td>-n</td>
3101 3103 <td>--dry-run</td>
3102 3104 <td>do not perform actions, just print output</td></tr>
3103 3105 </table>
3104 3106 <p>
3105 3107 global options ([+] can be repeated):
3106 3108 </p>
3107 3109 <table>
3108 3110 <tr><td>-R</td>
3109 3111 <td>--repository REPO</td>
3110 3112 <td>repository root directory or name of overlay bundle file</td></tr>
3111 3113 <tr><td></td>
3112 3114 <td>--cwd DIR</td>
3113 3115 <td>change working directory</td></tr>
3114 3116 <tr><td>-y</td>
3115 3117 <td>--noninteractive</td>
3116 3118 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3117 3119 <tr><td>-q</td>
3118 3120 <td>--quiet</td>
3119 3121 <td>suppress output</td></tr>
3120 3122 <tr><td>-v</td>
3121 3123 <td>--verbose</td>
3122 3124 <td>enable additional output</td></tr>
3123 3125 <tr><td></td>
3124 3126 <td>--color TYPE</td>
3125 3127 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3126 3128 <tr><td></td>
3127 3129 <td>--config CONFIG [+]</td>
3128 3130 <td>set/override config option (use 'section.name=value')</td></tr>
3129 3131 <tr><td></td>
3130 3132 <td>--debug</td>
3131 3133 <td>enable debugging output</td></tr>
3132 3134 <tr><td></td>
3133 3135 <td>--debugger</td>
3134 3136 <td>start debugger</td></tr>
3135 3137 <tr><td></td>
3136 3138 <td>--encoding ENCODE</td>
3137 3139 <td>set the charset encoding (default: ascii)</td></tr>
3138 3140 <tr><td></td>
3139 3141 <td>--encodingmode MODE</td>
3140 3142 <td>set the charset encoding mode (default: strict)</td></tr>
3141 3143 <tr><td></td>
3142 3144 <td>--traceback</td>
3143 3145 <td>always print a traceback on exception</td></tr>
3144 3146 <tr><td></td>
3145 3147 <td>--time</td>
3146 3148 <td>time how long the command takes</td></tr>
3147 3149 <tr><td></td>
3148 3150 <td>--profile</td>
3149 3151 <td>print command execution profile</td></tr>
3150 3152 <tr><td></td>
3151 3153 <td>--version</td>
3152 3154 <td>output version information and exit</td></tr>
3153 3155 <tr><td>-h</td>
3154 3156 <td>--help</td>
3155 3157 <td>display help and exit</td></tr>
3156 3158 <tr><td></td>
3157 3159 <td>--hidden</td>
3158 3160 <td>consider hidden changesets</td></tr>
3159 3161 <tr><td></td>
3160 3162 <td>--pager TYPE</td>
3161 3163 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3162 3164 </table>
3163 3165
3164 3166 </div>
3165 3167 </div>
3166 3168 </div>
3167 3169
3168 3170
3169 3171
3170 3172 </body>
3171 3173 </html>
3172 3174
3173 3175
3174 3176 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3175 3177 200 Script output follows
3176 3178
3177 3179 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3178 3180 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3179 3181 <head>
3180 3182 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3181 3183 <meta name="robots" content="index, nofollow" />
3182 3184 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3183 3185 <script type="text/javascript" src="/static/mercurial.js"></script>
3184 3186
3185 3187 <title>Help: dates</title>
3186 3188 </head>
3187 3189 <body>
3188 3190
3189 3191 <div class="container">
3190 3192 <div class="menu">
3191 3193 <div class="logo">
3192 3194 <a href="https://mercurial-scm.org/">
3193 3195 <img src="/static/hglogo.png" alt="mercurial" /></a>
3194 3196 </div>
3195 3197 <ul>
3196 3198 <li><a href="/shortlog">log</a></li>
3197 3199 <li><a href="/graph">graph</a></li>
3198 3200 <li><a href="/tags">tags</a></li>
3199 3201 <li><a href="/bookmarks">bookmarks</a></li>
3200 3202 <li><a href="/branches">branches</a></li>
3201 3203 </ul>
3202 3204 <ul>
3203 3205 <li class="active"><a href="/help">help</a></li>
3204 3206 </ul>
3205 3207 </div>
3206 3208
3207 3209 <div class="main">
3208 3210 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3209 3211 <h3>Help: dates</h3>
3210 3212
3211 3213 <form class="search" action="/log">
3212 3214
3213 3215 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3214 3216 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3215 3217 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3216 3218 </form>
3217 3219 <div id="doc">
3218 3220 <h1>Date Formats</h1>
3219 3221 <p>
3220 3222 Some commands allow the user to specify a date, e.g.:
3221 3223 </p>
3222 3224 <ul>
3223 3225 <li> backout, commit, import, tag: Specify the commit date.
3224 3226 <li> log, revert, update: Select revision(s) by date.
3225 3227 </ul>
3226 3228 <p>
3227 3229 Many date formats are valid. Here are some examples:
3228 3230 </p>
3229 3231 <ul>
3230 3232 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3231 3233 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3232 3234 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3233 3235 <li> &quot;Dec 6&quot; (midnight)
3234 3236 <li> &quot;13:18&quot; (today assumed)
3235 3237 <li> &quot;3:39&quot; (3:39AM assumed)
3236 3238 <li> &quot;3:39pm&quot; (15:39)
3237 3239 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3238 3240 <li> &quot;2006-12-6 13:18&quot;
3239 3241 <li> &quot;2006-12-6&quot;
3240 3242 <li> &quot;12-6&quot;
3241 3243 <li> &quot;12/6&quot;
3242 3244 <li> &quot;12/6/6&quot; (Dec 6 2006)
3243 3245 <li> &quot;today&quot; (midnight)
3244 3246 <li> &quot;yesterday&quot; (midnight)
3245 3247 <li> &quot;now&quot; - right now
3246 3248 </ul>
3247 3249 <p>
3248 3250 Lastly, there is Mercurial's internal format:
3249 3251 </p>
3250 3252 <ul>
3251 3253 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3252 3254 </ul>
3253 3255 <p>
3254 3256 This is the internal representation format for dates. The first number
3255 3257 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3256 3258 second is the offset of the local timezone, in seconds west of UTC
3257 3259 (negative if the timezone is east of UTC).
3258 3260 </p>
3259 3261 <p>
3260 3262 The log command also accepts date ranges:
3261 3263 </p>
3262 3264 <ul>
3263 3265 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3264 3266 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3265 3267 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3266 3268 <li> &quot;-DAYS&quot; - within a given number of days of today
3267 3269 </ul>
3268 3270
3269 3271 </div>
3270 3272 </div>
3271 3273 </div>
3272 3274
3273 3275
3274 3276
3275 3277 </body>
3276 3278 </html>
3277 3279
3278 3280
3279 3281 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3280 3282 200 Script output follows
3281 3283
3282 3284 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3283 3285 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3284 3286 <head>
3285 3287 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3286 3288 <meta name="robots" content="index, nofollow" />
3287 3289 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3288 3290 <script type="text/javascript" src="/static/mercurial.js"></script>
3289 3291
3290 3292 <title>Help: pager</title>
3291 3293 </head>
3292 3294 <body>
3293 3295
3294 3296 <div class="container">
3295 3297 <div class="menu">
3296 3298 <div class="logo">
3297 3299 <a href="https://mercurial-scm.org/">
3298 3300 <img src="/static/hglogo.png" alt="mercurial" /></a>
3299 3301 </div>
3300 3302 <ul>
3301 3303 <li><a href="/shortlog">log</a></li>
3302 3304 <li><a href="/graph">graph</a></li>
3303 3305 <li><a href="/tags">tags</a></li>
3304 3306 <li><a href="/bookmarks">bookmarks</a></li>
3305 3307 <li><a href="/branches">branches</a></li>
3306 3308 </ul>
3307 3309 <ul>
3308 3310 <li class="active"><a href="/help">help</a></li>
3309 3311 </ul>
3310 3312 </div>
3311 3313
3312 3314 <div class="main">
3313 3315 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3314 3316 <h3>Help: pager</h3>
3315 3317
3316 3318 <form class="search" action="/log">
3317 3319
3318 3320 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3319 3321 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3320 3322 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3321 3323 </form>
3322 3324 <div id="doc">
3323 3325 <h1>Pager Support</h1>
3324 3326 <p>
3325 3327 Some Mercurial commands can produce a lot of output, and Mercurial will
3326 3328 attempt to use a pager to make those commands more pleasant.
3327 3329 </p>
3328 3330 <p>
3329 3331 To set the pager that should be used, set the application variable:
3330 3332 </p>
3331 3333 <pre>
3332 3334 [pager]
3333 3335 pager = less -FRX
3334 3336 </pre>
3335 3337 <p>
3336 3338 If no pager is set in the user or repository configuration, Mercurial uses the
3337 3339 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3338 3340 or system configuration is used. If none of these are set, a default pager will
3339 3341 be used, typically 'less' on Unix and 'more' on Windows.
3340 3342 </p>
3341 3343 <p>
3342 3344 You can disable the pager for certain commands by adding them to the
3343 3345 pager.ignore list:
3344 3346 </p>
3345 3347 <pre>
3346 3348 [pager]
3347 3349 ignore = version, help, update
3348 3350 </pre>
3349 3351 <p>
3350 3352 To ignore global commands like 'hg version' or 'hg help', you have
3351 3353 to specify them in your user configuration file.
3352 3354 </p>
3353 3355 <p>
3354 3356 To control whether the pager is used at all for an individual command,
3355 3357 you can use --pager=&lt;value&gt;:
3356 3358 </p>
3357 3359 <ul>
3358 3360 <li> use as needed: 'auto'.
3359 3361 <li> require the pager: 'yes' or 'on'.
3360 3362 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3361 3363 </ul>
3362 3364 <p>
3363 3365 To globally turn off all attempts to use a pager, set:
3364 3366 </p>
3365 3367 <pre>
3366 3368 [ui]
3367 3369 paginate = never
3368 3370 </pre>
3369 3371 <p>
3370 3372 which will prevent the pager from running.
3371 3373 </p>
3372 3374
3373 3375 </div>
3374 3376 </div>
3375 3377 </div>
3376 3378
3377 3379
3378 3380
3379 3381 </body>
3380 3382 </html>
3381 3383
3382 3384
3383 3385 Sub-topic indexes rendered properly
3384 3386
3385 3387 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3386 3388 200 Script output follows
3387 3389
3388 3390 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3389 3391 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3390 3392 <head>
3391 3393 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3392 3394 <meta name="robots" content="index, nofollow" />
3393 3395 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3394 3396 <script type="text/javascript" src="/static/mercurial.js"></script>
3395 3397
3396 3398 <title>Help: internals</title>
3397 3399 </head>
3398 3400 <body>
3399 3401
3400 3402 <div class="container">
3401 3403 <div class="menu">
3402 3404 <div class="logo">
3403 3405 <a href="https://mercurial-scm.org/">
3404 3406 <img src="/static/hglogo.png" alt="mercurial" /></a>
3405 3407 </div>
3406 3408 <ul>
3407 3409 <li><a href="/shortlog">log</a></li>
3408 3410 <li><a href="/graph">graph</a></li>
3409 3411 <li><a href="/tags">tags</a></li>
3410 3412 <li><a href="/bookmarks">bookmarks</a></li>
3411 3413 <li><a href="/branches">branches</a></li>
3412 3414 </ul>
3413 3415 <ul>
3414 3416 <li><a href="/help">help</a></li>
3415 3417 </ul>
3416 3418 </div>
3417 3419
3418 3420 <div class="main">
3419 3421 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3420 3422
3421 3423 <form class="search" action="/log">
3422 3424
3423 3425 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3424 3426 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3425 3427 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3426 3428 </form>
3427 3429 <table class="bigtable">
3428 3430 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3429 3431
3430 3432 <tr><td>
3431 3433 <a href="/help/internals.bundle2">
3432 3434 bundle2
3433 3435 </a>
3434 3436 </td><td>
3435 3437 Bundle2
3436 3438 </td></tr>
3437 3439 <tr><td>
3438 3440 <a href="/help/internals.bundles">
3439 3441 bundles
3440 3442 </a>
3441 3443 </td><td>
3442 3444 Bundles
3443 3445 </td></tr>
3444 3446 <tr><td>
3445 3447 <a href="/help/internals.cbor">
3446 3448 cbor
3447 3449 </a>
3448 3450 </td><td>
3449 3451 CBOR
3450 3452 </td></tr>
3451 3453 <tr><td>
3452 3454 <a href="/help/internals.censor">
3453 3455 censor
3454 3456 </a>
3455 3457 </td><td>
3456 3458 Censor
3457 3459 </td></tr>
3458 3460 <tr><td>
3459 3461 <a href="/help/internals.changegroups">
3460 3462 changegroups
3461 3463 </a>
3462 3464 </td><td>
3463 3465 Changegroups
3464 3466 </td></tr>
3465 3467 <tr><td>
3466 3468 <a href="/help/internals.config">
3467 3469 config
3468 3470 </a>
3469 3471 </td><td>
3470 3472 Config Registrar
3471 3473 </td></tr>
3472 3474 <tr><td>
3473 3475 <a href="/help/internals.extensions">
3474 3476 extensions
3475 3477 </a>
3476 3478 </td><td>
3477 3479 Extension API
3478 3480 </td></tr>
3479 3481 <tr><td>
3480 3482 <a href="/help/internals.mergestate">
3481 3483 mergestate
3482 3484 </a>
3483 3485 </td><td>
3484 3486 Mergestate
3485 3487 </td></tr>
3486 3488 <tr><td>
3487 3489 <a href="/help/internals.requirements">
3488 3490 requirements
3489 3491 </a>
3490 3492 </td><td>
3491 3493 Repository Requirements
3492 3494 </td></tr>
3493 3495 <tr><td>
3494 3496 <a href="/help/internals.revlogs">
3495 3497 revlogs
3496 3498 </a>
3497 3499 </td><td>
3498 3500 Revision Logs
3499 3501 </td></tr>
3500 3502 <tr><td>
3501 3503 <a href="/help/internals.wireprotocol">
3502 3504 wireprotocol
3503 3505 </a>
3504 3506 </td><td>
3505 3507 Wire Protocol
3506 3508 </td></tr>
3507 3509 <tr><td>
3508 3510 <a href="/help/internals.wireprotocolrpc">
3509 3511 wireprotocolrpc
3510 3512 </a>
3511 3513 </td><td>
3512 3514 Wire Protocol RPC
3513 3515 </td></tr>
3514 3516 <tr><td>
3515 3517 <a href="/help/internals.wireprotocolv2">
3516 3518 wireprotocolv2
3517 3519 </a>
3518 3520 </td><td>
3519 3521 Wire Protocol Version 2
3520 3522 </td></tr>
3521 3523
3522 3524
3523 3525
3524 3526
3525 3527
3526 3528 </table>
3527 3529 </div>
3528 3530 </div>
3529 3531
3530 3532
3531 3533
3532 3534 </body>
3533 3535 </html>
3534 3536
3535 3537
3536 3538 Sub-topic topics rendered properly
3537 3539
3538 3540 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3539 3541 200 Script output follows
3540 3542
3541 3543 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3542 3544 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3543 3545 <head>
3544 3546 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3545 3547 <meta name="robots" content="index, nofollow" />
3546 3548 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3547 3549 <script type="text/javascript" src="/static/mercurial.js"></script>
3548 3550
3549 3551 <title>Help: internals.changegroups</title>
3550 3552 </head>
3551 3553 <body>
3552 3554
3553 3555 <div class="container">
3554 3556 <div class="menu">
3555 3557 <div class="logo">
3556 3558 <a href="https://mercurial-scm.org/">
3557 3559 <img src="/static/hglogo.png" alt="mercurial" /></a>
3558 3560 </div>
3559 3561 <ul>
3560 3562 <li><a href="/shortlog">log</a></li>
3561 3563 <li><a href="/graph">graph</a></li>
3562 3564 <li><a href="/tags">tags</a></li>
3563 3565 <li><a href="/bookmarks">bookmarks</a></li>
3564 3566 <li><a href="/branches">branches</a></li>
3565 3567 </ul>
3566 3568 <ul>
3567 3569 <li class="active"><a href="/help">help</a></li>
3568 3570 </ul>
3569 3571 </div>
3570 3572
3571 3573 <div class="main">
3572 3574 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3573 3575 <h3>Help: internals.changegroups</h3>
3574 3576
3575 3577 <form class="search" action="/log">
3576 3578
3577 3579 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3578 3580 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3579 3581 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3580 3582 </form>
3581 3583 <div id="doc">
3582 3584 <h1>Changegroups</h1>
3583 3585 <p>
3584 3586 Changegroups are representations of repository revlog data, specifically
3585 3587 the changelog data, root/flat manifest data, treemanifest data, and
3586 3588 filelogs.
3587 3589 </p>
3588 3590 <p>
3589 3591 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3590 3592 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3591 3593 only difference being an additional item in the *delta header*. Version
3592 3594 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3593 3595 exchanging treemanifests (enabled by setting an option on the
3594 3596 &quot;changegroup&quot; part in the bundle2).
3595 3597 </p>
3596 3598 <p>
3597 3599 Changegroups when not exchanging treemanifests consist of 3 logical
3598 3600 segments:
3599 3601 </p>
3600 3602 <pre>
3601 3603 +---------------------------------+
3602 3604 | | | |
3603 3605 | changeset | manifest | filelogs |
3604 3606 | | | |
3605 3607 | | | |
3606 3608 +---------------------------------+
3607 3609 </pre>
3608 3610 <p>
3609 3611 When exchanging treemanifests, there are 4 logical segments:
3610 3612 </p>
3611 3613 <pre>
3612 3614 +-------------------------------------------------+
3613 3615 | | | | |
3614 3616 | changeset | root | treemanifests | filelogs |
3615 3617 | | manifest | | |
3616 3618 | | | | |
3617 3619 +-------------------------------------------------+
3618 3620 </pre>
3619 3621 <p>
3620 3622 The principle building block of each segment is a *chunk*. A *chunk*
3621 3623 is a framed piece of data:
3622 3624 </p>
3623 3625 <pre>
3624 3626 +---------------------------------------+
3625 3627 | | |
3626 3628 | length | data |
3627 3629 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3628 3630 | | |
3629 3631 +---------------------------------------+
3630 3632 </pre>
3631 3633 <p>
3632 3634 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3633 3635 integer indicating the length of the entire chunk (including the length field
3634 3636 itself).
3635 3637 </p>
3636 3638 <p>
3637 3639 There is a special case chunk that has a value of 0 for the length
3638 3640 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3639 3641 </p>
3640 3642 <h2>Delta Groups</h2>
3641 3643 <p>
3642 3644 A *delta group* expresses the content of a revlog as a series of deltas,
3643 3645 or patches against previous revisions.
3644 3646 </p>
3645 3647 <p>
3646 3648 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3647 3649 to signal the end of the delta group:
3648 3650 </p>
3649 3651 <pre>
3650 3652 +------------------------------------------------------------------------+
3651 3653 | | | | | |
3652 3654 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3653 3655 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3654 3656 | | | | | |
3655 3657 +------------------------------------------------------------------------+
3656 3658 </pre>
3657 3659 <p>
3658 3660 Each *chunk*'s data consists of the following:
3659 3661 </p>
3660 3662 <pre>
3661 3663 +---------------------------------------+
3662 3664 | | |
3663 3665 | delta header | delta data |
3664 3666 | (various by version) | (various) |
3665 3667 | | |
3666 3668 +---------------------------------------+
3667 3669 </pre>
3668 3670 <p>
3669 3671 The *delta data* is a series of *delta*s that describe a diff from an existing
3670 3672 entry (either that the recipient already has, or previously specified in the
3671 3673 bundle/changegroup).
3672 3674 </p>
3673 3675 <p>
3674 3676 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3675 3677 &quot;3&quot; of the changegroup format.
3676 3678 </p>
3677 3679 <p>
3678 3680 Version 1 (headerlen=80):
3679 3681 </p>
3680 3682 <pre>
3681 3683 +------------------------------------------------------+
3682 3684 | | | | |
3683 3685 | node | p1 node | p2 node | link node |
3684 3686 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3685 3687 | | | | |
3686 3688 +------------------------------------------------------+
3687 3689 </pre>
3688 3690 <p>
3689 3691 Version 2 (headerlen=100):
3690 3692 </p>
3691 3693 <pre>
3692 3694 +------------------------------------------------------------------+
3693 3695 | | | | | |
3694 3696 | node | p1 node | p2 node | base node | link node |
3695 3697 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3696 3698 | | | | | |
3697 3699 +------------------------------------------------------------------+
3698 3700 </pre>
3699 3701 <p>
3700 3702 Version 3 (headerlen=102):
3701 3703 </p>
3702 3704 <pre>
3703 3705 +------------------------------------------------------------------------------+
3704 3706 | | | | | | |
3705 3707 | node | p1 node | p2 node | base node | link node | flags |
3706 3708 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3707 3709 | | | | | | |
3708 3710 +------------------------------------------------------------------------------+
3709 3711 </pre>
3710 3712 <p>
3711 3713 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3712 3714 series of *delta*s, densely packed (no separators). These deltas describe a diff
3713 3715 from an existing entry (either that the recipient already has, or previously
3714 3716 specified in the bundle/changegroup). The format is described more fully in
3715 3717 &quot;hg help internals.bdiff&quot;, but briefly:
3716 3718 </p>
3717 3719 <pre>
3718 3720 +---------------------------------------------------------------+
3719 3721 | | | | |
3720 3722 | start offset | end offset | new length | content |
3721 3723 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3722 3724 | | | | |
3723 3725 +---------------------------------------------------------------+
3724 3726 </pre>
3725 3727 <p>
3726 3728 Please note that the length field in the delta data does *not* include itself.
3727 3729 </p>
3728 3730 <p>
3729 3731 In version 1, the delta is always applied against the previous node from
3730 3732 the changegroup or the first parent if this is the first entry in the
3731 3733 changegroup.
3732 3734 </p>
3733 3735 <p>
3734 3736 In version 2 and up, the delta base node is encoded in the entry in the
3735 3737 changegroup. This allows the delta to be expressed against any parent,
3736 3738 which can result in smaller deltas and more efficient encoding of data.
3737 3739 </p>
3738 3740 <p>
3739 3741 The *flags* field holds bitwise flags affecting the processing of revision
3740 3742 data. The following flags are defined:
3741 3743 </p>
3742 3744 <dl>
3743 3745 <dt>32768
3744 3746 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3745 3747 <dt>16384
3746 3748 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3747 3749 <dt>8192
3748 3750 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3749 3751 </dl>
3750 3752 <p>
3751 3753 For historical reasons, the integer values are identical to revlog version 1
3752 3754 per-revision storage flags and correspond to bits being set in this 2-byte
3753 3755 field. Bits were allocated starting from the most-significant bit, hence the
3754 3756 reverse ordering and allocation of these flags.
3755 3757 </p>
3756 3758 <h2>Changeset Segment</h2>
3757 3759 <p>
3758 3760 The *changeset segment* consists of a single *delta group* holding
3759 3761 changelog data. The *empty chunk* at the end of the *delta group* denotes
3760 3762 the boundary to the *manifest segment*.
3761 3763 </p>
3762 3764 <h2>Manifest Segment</h2>
3763 3765 <p>
3764 3766 The *manifest segment* consists of a single *delta group* holding manifest
3765 3767 data. If treemanifests are in use, it contains only the manifest for the
3766 3768 root directory of the repository. Otherwise, it contains the entire
3767 3769 manifest data. The *empty chunk* at the end of the *delta group* denotes
3768 3770 the boundary to the next segment (either the *treemanifests segment* or the
3769 3771 *filelogs segment*, depending on version and the request options).
3770 3772 </p>
3771 3773 <h3>Treemanifests Segment</h3>
3772 3774 <p>
3773 3775 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3774 3776 only if the 'treemanifest' param is part of the bundle2 changegroup part
3775 3777 (it is not possible to use changegroup version 3 outside of bundle2).
3776 3778 Aside from the filenames in the *treemanifests segment* containing a
3777 3779 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3778 3780 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3779 3781 a sub-segment with filename size 0). This denotes the boundary to the
3780 3782 *filelogs segment*.
3781 3783 </p>
3782 3784 <h2>Filelogs Segment</h2>
3783 3785 <p>
3784 3786 The *filelogs segment* consists of multiple sub-segments, each
3785 3787 corresponding to an individual file whose data is being described:
3786 3788 </p>
3787 3789 <pre>
3788 3790 +--------------------------------------------------+
3789 3791 | | | | | |
3790 3792 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3791 3793 | | | | | (4 bytes) |
3792 3794 | | | | | |
3793 3795 +--------------------------------------------------+
3794 3796 </pre>
3795 3797 <p>
3796 3798 The final filelog sub-segment is followed by an *empty chunk* (logically,
3797 3799 a sub-segment with filename size 0). This denotes the end of the segment
3798 3800 and of the overall changegroup.
3799 3801 </p>
3800 3802 <p>
3801 3803 Each filelog sub-segment consists of the following:
3802 3804 </p>
3803 3805 <pre>
3804 3806 +------------------------------------------------------+
3805 3807 | | | |
3806 3808 | filename length | filename | delta group |
3807 3809 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3808 3810 | | | |
3809 3811 +------------------------------------------------------+
3810 3812 </pre>
3811 3813 <p>
3812 3814 That is, a *chunk* consisting of the filename (not terminated or padded)
3813 3815 followed by N chunks constituting the *delta group* for this file. The
3814 3816 *empty chunk* at the end of each *delta group* denotes the boundary to the
3815 3817 next filelog sub-segment.
3816 3818 </p>
3817 3819
3818 3820 </div>
3819 3821 </div>
3820 3822 </div>
3821 3823
3822 3824
3823 3825
3824 3826 </body>
3825 3827 </html>
3826 3828
3827 3829
3828 3830 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3829 3831 404 Not Found
3830 3832
3831 3833 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3832 3834 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3833 3835 <head>
3834 3836 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3835 3837 <meta name="robots" content="index, nofollow" />
3836 3838 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3837 3839 <script type="text/javascript" src="/static/mercurial.js"></script>
3838 3840
3839 3841 <title>test: error</title>
3840 3842 </head>
3841 3843 <body>
3842 3844
3843 3845 <div class="container">
3844 3846 <div class="menu">
3845 3847 <div class="logo">
3846 3848 <a href="https://mercurial-scm.org/">
3847 3849 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3848 3850 </div>
3849 3851 <ul>
3850 3852 <li><a href="/shortlog">log</a></li>
3851 3853 <li><a href="/graph">graph</a></li>
3852 3854 <li><a href="/tags">tags</a></li>
3853 3855 <li><a href="/bookmarks">bookmarks</a></li>
3854 3856 <li><a href="/branches">branches</a></li>
3855 3857 </ul>
3856 3858 <ul>
3857 3859 <li><a href="/help">help</a></li>
3858 3860 </ul>
3859 3861 </div>
3860 3862
3861 3863 <div class="main">
3862 3864
3863 3865 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3864 3866 <h3>error</h3>
3865 3867
3866 3868
3867 3869 <form class="search" action="/log">
3868 3870
3869 3871 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3870 3872 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3871 3873 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3872 3874 </form>
3873 3875
3874 3876 <div class="description">
3875 3877 <p>
3876 3878 An error occurred while processing your request:
3877 3879 </p>
3878 3880 <p>
3879 3881 Not Found
3880 3882 </p>
3881 3883 </div>
3882 3884 </div>
3883 3885 </div>
3884 3886
3885 3887
3886 3888
3887 3889 </body>
3888 3890 </html>
3889 3891
3890 3892 [1]
3891 3893
3892 3894 $ killdaemons.py
3893 3895
3894 3896 #endif
@@ -1,827 +1,830 b''
1 1 setup
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [extensions]
5 5 > blackbox=
6 6 > mock=$TESTDIR/mockblackbox.py
7 7 > [blackbox]
8 8 > track = command, commandfinish, tagscache
9 9 > EOF
10 10
11 11 Helper functions:
12 12
13 13 $ cacheexists() {
14 14 > [ -f .hg/cache/tags2-visible ] && echo "tag cache exists" || echo "no tag cache"
15 15 > }
16 16
17 17 $ fnodescacheexists() {
18 18 > [ -f .hg/cache/hgtagsfnodes1 ] && echo "fnodes cache exists" || echo "no fnodes cache"
19 19 > }
20 20
21 21 $ dumptags() {
22 22 > rev=$1
23 23 > echo "rev $rev: .hgtags:"
24 24 > hg cat -r$rev .hgtags
25 25 > }
26 26
27 27 # XXX need to test that the tag cache works when we strip an old head
28 28 # and add a new one rooted off non-tip: i.e. node and rev of tip are the
29 29 # same, but stuff has changed behind tip.
30 30
31 31 Setup:
32 32
33 33 $ hg init t
34 34 $ cd t
35 35 $ cacheexists
36 36 no tag cache
37 37 $ fnodescacheexists
38 38 no fnodes cache
39 39 $ hg id
40 40 000000000000 tip
41 41 $ cacheexists
42 42 no tag cache
43 43 $ fnodescacheexists
44 44 no fnodes cache
45 45 $ echo a > a
46 46 $ hg add a
47 47 $ hg commit -m "test"
48 48 $ hg co
49 49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 50 $ hg identify
51 51 acb14030fe0a tip
52 52 $ hg identify -r 'wdir()'
53 53 acb14030fe0a tip
54 54 $ cacheexists
55 55 tag cache exists
56 56 No fnodes cache because .hgtags file doesn't exist
57 57 (this is an implementation detail)
58 58 $ fnodescacheexists
59 59 no fnodes cache
60 60
61 61 Try corrupting the cache
62 62
63 63 $ printf 'a b' > .hg/cache/tags2-visible
64 64 $ hg identify
65 65 acb14030fe0a tip
66 66 $ cacheexists
67 67 tag cache exists
68 68 $ fnodescacheexists
69 69 no fnodes cache
70 70 $ hg identify
71 71 acb14030fe0a tip
72 72
73 73 Create local tag with long name:
74 74
75 75 $ T=`hg identify --debug --id`
76 76 $ hg tag -l "This is a local tag with a really long name!"
77 77 $ hg tags
78 78 tip 0:acb14030fe0a
79 79 This is a local tag with a really long name! 0:acb14030fe0a
80 80 $ rm .hg/localtags
81 81
82 82 Create a tag behind hg's back:
83 83
84 84 $ echo "$T first" > .hgtags
85 85 $ cat .hgtags
86 86 acb14030fe0a21b60322c440ad2d20cf7685a376 first
87 87 $ hg add .hgtags
88 88 $ hg commit -m "add tags"
89 89 $ hg tags
90 90 tip 1:b9154636be93
91 91 first 0:acb14030fe0a
92 92 $ hg identify
93 93 b9154636be93 tip
94 94
95 95 We should have a fnodes cache now that we have a real tag
96 96 The cache should have an empty entry for rev 0 and a valid entry for rev 1.
97 97
98 98
99 99 $ fnodescacheexists
100 100 fnodes cache exists
101 101 $ f --size --hexdump .hg/cache/hgtagsfnodes1
102 102 .hg/cache/hgtagsfnodes1: size=48
103 103 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
104 104 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
105 105 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
106 $ hg debugtagscache
107 0 acb14030fe0a21b60322c440ad2d20cf7685a376 missing/invalid
108 1 b9154636be938d3d431e75a7c906504a079bfe07 26b7b4a773e09ee3c52f510e19e05e1ff966d859
106 109
107 110 Repeat with cold tag cache:
108 111
109 112 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
110 113 $ hg identify
111 114 b9154636be93 tip
112 115
113 116 $ fnodescacheexists
114 117 fnodes cache exists
115 118 $ f --size --hexdump .hg/cache/hgtagsfnodes1
116 119 .hg/cache/hgtagsfnodes1: size=48
117 120 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
118 121 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
119 122 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
120 123
121 124 And again, but now unable to write tag cache or lock file:
122 125
123 126 #if unix-permissions no-fsmonitor
124 127
125 128 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
126 129 $ chmod 555 .hg/cache
127 130 $ hg identify
128 131 b9154636be93 tip
129 132 $ chmod 755 .hg/cache
130 133
131 134 (this block should be protected by no-fsmonitor, because "chmod 555 .hg"
132 135 makes watchman fail at accessing to files under .hg)
133 136
134 137 $ chmod 555 .hg
135 138 $ hg identify
136 139 b9154636be93 tip
137 140 $ chmod 755 .hg
138 141 #endif
139 142
140 143 Tag cache debug info written to blackbox log
141 144
142 145 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
143 146 $ hg identify
144 147 b9154636be93 tip
145 148 $ hg blackbox -l 6
146 149 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify
147 150 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing 48 bytes to cache/hgtagsfnodes1
148 151 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> 0/2 cache hits/lookups in * seconds (glob)
149 152 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing .hg/cache/tags2-visible with 1 tags
150 153 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify exited 0 after * seconds (glob)
151 154 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> blackbox -l 6
152 155
153 156 Failure to acquire lock results in no write
154 157
155 158 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
156 159 $ echo 'foo:1' > .hg/wlock
157 160 $ hg identify
158 161 b9154636be93 tip
159 162 $ hg blackbox -l 6
160 163 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify
161 164 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> not writing .hg/cache/hgtagsfnodes1 because lock cannot be acquired
162 165 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> 0/2 cache hits/lookups in * seconds (glob)
163 166 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing .hg/cache/tags2-visible with 1 tags
164 167 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify exited 0 after * seconds (glob)
165 168 1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> blackbox -l 6
166 169
167 170 $ fnodescacheexists
168 171 no fnodes cache
169 172
170 173 $ rm .hg/wlock
171 174
172 175 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
173 176 $ hg identify
174 177 b9154636be93 tip
175 178
176 179 Create a branch:
177 180
178 181 $ echo bb > a
179 182 $ hg status
180 183 M a
181 184 $ hg identify
182 185 b9154636be93+ tip
183 186 $ hg co first
184 187 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
185 188 $ hg id
186 189 acb14030fe0a+ first
187 190 $ hg id -r 'wdir()'
188 191 acb14030fe0a+ first
189 192 $ hg -v id
190 193 acb14030fe0a+ first
191 194 $ hg status
192 195 M a
193 196 $ echo 1 > b
194 197 $ hg add b
195 198 $ hg commit -m "branch"
196 199 created new head
197 200
198 201 Creating a new commit shouldn't append the .hgtags fnodes cache until
199 202 tags info is accessed
200 203
201 204 $ f --size --hexdump .hg/cache/hgtagsfnodes1
202 205 .hg/cache/hgtagsfnodes1: size=48
203 206 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
204 207 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
205 208 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
206 209
207 210 $ hg id
208 211 c8edf04160c7 tip
209 212
210 213 First 4 bytes of record 3 are changeset fragment
211 214
212 215 $ f --size --hexdump .hg/cache/hgtagsfnodes1
213 216 .hg/cache/hgtagsfnodes1: size=72
214 217 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
215 218 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
216 219 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
217 220 0030: c8 ed f0 41 00 00 00 00 00 00 00 00 00 00 00 00 |...A............|
218 221 0040: 00 00 00 00 00 00 00 00 |........|
219 222
220 223 Merge the two heads:
221 224
222 225 $ hg merge 1
223 226 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 227 (branch merge, don't forget to commit)
225 228 $ hg blackbox -l3
226 229 1970/01/01 00:00:00 bob @c8edf04160c7f731e4589d66ab3ab3486a64ac28 (5000)> merge 1
227 230 1970/01/01 00:00:00 bob @c8edf04160c7f731e4589d66ab3ab3486a64ac28+b9154636be938d3d431e75a7c906504a079bfe07 (5000)> merge 1 exited 0 after * seconds (glob)
228 231 1970/01/01 00:00:00 bob @c8edf04160c7f731e4589d66ab3ab3486a64ac28+b9154636be938d3d431e75a7c906504a079bfe07 (5000)> blackbox -l3
229 232 $ hg id
230 233 c8edf04160c7+b9154636be93+ tip
231 234 $ hg status
232 235 M .hgtags
233 236 $ hg commit -m "merge"
234 237
235 238 Create a fake head, make sure tag not visible afterwards:
236 239
237 240 $ cp .hgtags tags
238 241 $ hg tag last
239 242 $ hg rm .hgtags
240 243 $ hg commit -m "remove"
241 244
242 245 $ mv tags .hgtags
243 246 $ hg add .hgtags
244 247 $ hg commit -m "readd"
245 248 $
246 249 $ hg tags
247 250 tip 6:35ff301afafe
248 251 first 0:acb14030fe0a
249 252
250 253 Add invalid tags:
251 254
252 255 $ echo "spam" >> .hgtags
253 256 $ echo >> .hgtags
254 257 $ echo "foo bar" >> .hgtags
255 258 $ echo "a5a5 invalid" >> .hg/localtags
256 259 $ cat .hgtags
257 260 acb14030fe0a21b60322c440ad2d20cf7685a376 first
258 261 spam
259 262
260 263 foo bar
261 264 $ hg commit -m "tags"
262 265
263 266 Report tag parse error on other head:
264 267
265 268 $ hg up 3
266 269 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 270 $ echo 'x y' >> .hgtags
268 271 $ hg commit -m "head"
269 272 created new head
270 273
271 274 $ hg tags --debug
272 275 .hgtags@75d9f02dfe28, line 2: cannot parse entry
273 276 .hgtags@75d9f02dfe28, line 4: node 'foo' is not well formed
274 277 .hgtags@c4be69a18c11, line 2: node 'x' is not well formed
275 278 tip 8:c4be69a18c11e8bc3a5fdbb576017c25f7d84663
276 279 first 0:acb14030fe0a21b60322c440ad2d20cf7685a376
277 280 $ hg tip
278 281 changeset: 8:c4be69a18c11
279 282 tag: tip
280 283 parent: 3:ac5e980c4dc0
281 284 user: test
282 285 date: Thu Jan 01 00:00:00 1970 +0000
283 286 summary: head
284 287
285 288
286 289 Test tag precedence rules:
287 290
288 291 $ cd ..
289 292 $ hg init t2
290 293 $ cd t2
291 294 $ echo foo > foo
292 295 $ hg add foo
293 296 $ hg ci -m 'add foo' # rev 0
294 297 $ hg tag bar # rev 1
295 298 $ echo >> foo
296 299 $ hg ci -m 'change foo 1' # rev 2
297 300 $ hg up -C 1
298 301 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
299 302 $ hg tag -r 1 -f bar # rev 3
300 303 $ hg up -C 1
301 304 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 305 $ echo >> foo
303 306 $ hg ci -m 'change foo 2' # rev 4
304 307 created new head
305 308 $ hg tags
306 309 tip 4:0c192d7d5e6b
307 310 bar 1:78391a272241
308 311
309 312 Repeat in case of cache effects:
310 313
311 314 $ hg tags
312 315 tip 4:0c192d7d5e6b
313 316 bar 1:78391a272241
314 317
315 318 Detailed dump of tag info:
316 319
317 320 $ hg heads -q # expect 4, 3, 2
318 321 4:0c192d7d5e6b
319 322 3:6fa450212aeb
320 323 2:7a94127795a3
321 324 $ dumptags 2
322 325 rev 2: .hgtags:
323 326 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
324 327 $ dumptags 3
325 328 rev 3: .hgtags:
326 329 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
327 330 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
328 331 78391a272241d70354aa14c874552cad6b51bb42 bar
329 332 $ dumptags 4
330 333 rev 4: .hgtags:
331 334 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
332 335
333 336 Dump cache:
334 337
335 338 $ cat .hg/cache/tags2-visible
336 339 4 0c192d7d5e6b78a714de54a2e9627952a877e25a
337 340 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
338 341 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
339 342 78391a272241d70354aa14c874552cad6b51bb42 bar
340 343
341 344 $ f --size --hexdump .hg/cache/hgtagsfnodes1
342 345 .hg/cache/hgtagsfnodes1: size=120
343 346 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
344 347 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
345 348 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
346 349 0030: 7a 94 12 77 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |z..w.....1....B(|
347 350 0040: 78 ee 5a 2d ad bc 94 3d 6f a4 50 21 7d 3b 71 8c |x.Z-...=o.P!};q.|
348 351 0050: 96 4e f3 7b 89 e5 50 eb da fd 57 89 e7 6c e1 b0 |.N.{..P...W..l..|
349 352 0060: 0c 19 2d 7d 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |..-}.....1....B(|
350 353 0070: 78 ee 5a 2d ad bc 94 3d |x.Z-...=|
351 354
352 355 Corrupt the .hgtags fnodes cache
353 356 Extra junk data at the end should get overwritten on next cache update
354 357
355 358 $ echo extra >> .hg/cache/hgtagsfnodes1
356 359 $ echo dummy1 > foo
357 360 $ hg commit -m throwaway1
358 361
359 362 $ hg tags
360 363 tip 5:8dbfe60eff30
361 364 bar 1:78391a272241
362 365
363 366 $ hg blackbox -l 6
364 367 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> tags
365 368 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> writing 24 bytes to cache/hgtagsfnodes1
366 369 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> 3/4 cache hits/lookups in * seconds (glob)
367 370 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> writing .hg/cache/tags2-visible with 1 tags
368 371 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> tags exited 0 after * seconds (glob)
369 372 1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> blackbox -l 6
370 373
371 374 #if unix-permissions no-root
372 375 Errors writing to .hgtags fnodes cache are silently ignored
373 376
374 377 $ echo dummy2 > foo
375 378 $ hg commit -m throwaway2
376 379
377 380 $ chmod a-w .hg/cache/hgtagsfnodes1
378 381 $ rm -f .hg/cache/tags2-visible
379 382
380 383 $ hg tags
381 384 tip 6:b968051b5cf3
382 385 bar 1:78391a272241
383 386
384 387 $ hg blackbox -l 6
385 388 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags
386 389 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> couldn't write cache/hgtagsfnodes1: [Errno *] * (glob)
387 390 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> 3/4 cache hits/lookups in * seconds (glob)
388 391 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing .hg/cache/tags2-visible with 1 tags
389 392 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags exited 0 after * seconds (glob)
390 393 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> blackbox -l 6
391 394
392 395 $ chmod a+w .hg/cache/hgtagsfnodes1
393 396
394 397 $ rm -f .hg/cache/tags2-visible
395 398 $ hg tags
396 399 tip 6:b968051b5cf3
397 400 bar 1:78391a272241
398 401
399 402 $ hg blackbox -l 6
400 403 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags
401 404 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing 24 bytes to cache/hgtagsfnodes1
402 405 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> 3/4 cache hits/lookups in * seconds (glob)
403 406 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing .hg/cache/tags2-visible with 1 tags
404 407 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags exited 0 after * seconds (glob)
405 408 1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> blackbox -l 6
406 409
407 410 $ f --size .hg/cache/hgtagsfnodes1
408 411 .hg/cache/hgtagsfnodes1: size=168
409 412
410 413 $ hg -q --config extensions.strip= strip -r 6 --no-backup
411 414 #endif
412 415
413 416 Stripping doesn't truncate the tags cache until new data is available
414 417
415 418 $ rm -f .hg/cache/hgtagsfnodes1 .hg/cache/tags2-visible
416 419 $ hg tags
417 420 tip 5:8dbfe60eff30
418 421 bar 1:78391a272241
419 422
420 423 $ f --size .hg/cache/hgtagsfnodes1
421 424 .hg/cache/hgtagsfnodes1: size=144
422 425
423 426 $ hg -q --config extensions.strip= strip -r 5 --no-backup
424 427 $ hg tags
425 428 tip 4:0c192d7d5e6b
426 429 bar 1:78391a272241
427 430
428 431 $ hg blackbox -l 5
429 432 1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> writing 24 bytes to cache/hgtagsfnodes1
430 433 1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> 2/4 cache hits/lookups in * seconds (glob)
431 434 1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> writing .hg/cache/tags2-visible with 1 tags
432 435 1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> tags exited 0 after * seconds (glob)
433 436 1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> blackbox -l 5
434 437
435 438 $ f --size .hg/cache/hgtagsfnodes1
436 439 .hg/cache/hgtagsfnodes1: size=120
437 440
438 441 $ echo dummy > foo
439 442 $ hg commit -m throwaway3
440 443
441 444 $ hg tags
442 445 tip 5:035f65efb448
443 446 bar 1:78391a272241
444 447
445 448 $ hg blackbox -l 6
446 449 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> tags
447 450 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> writing 24 bytes to cache/hgtagsfnodes1
448 451 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> 3/4 cache hits/lookups in * seconds (glob)
449 452 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> writing .hg/cache/tags2-visible with 1 tags
450 453 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> tags exited 0 after * seconds (glob)
451 454 1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> blackbox -l 6
452 455 $ f --size .hg/cache/hgtagsfnodes1
453 456 .hg/cache/hgtagsfnodes1: size=144
454 457
455 458 $ hg -q --config extensions.strip= strip -r 5 --no-backup
456 459
457 460 Test tag removal:
458 461
459 462 $ hg tag --remove bar # rev 5
460 463 $ hg tip -vp
461 464 changeset: 5:5f6e8655b1c7
462 465 tag: tip
463 466 user: test
464 467 date: Thu Jan 01 00:00:00 1970 +0000
465 468 files: .hgtags
466 469 description:
467 470 Removed tag bar
468 471
469 472
470 473 diff -r 0c192d7d5e6b -r 5f6e8655b1c7 .hgtags
471 474 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
472 475 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
473 476 @@ -1,1 +1,3 @@
474 477 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
475 478 +78391a272241d70354aa14c874552cad6b51bb42 bar
476 479 +0000000000000000000000000000000000000000 bar
477 480
478 481 $ hg tags
479 482 tip 5:5f6e8655b1c7
480 483 $ hg tags # again, try to expose cache bugs
481 484 tip 5:5f6e8655b1c7
482 485
483 486 Remove nonexistent tag:
484 487
485 488 $ hg tag --remove foobar
486 489 abort: tag 'foobar' does not exist
487 490 [255]
488 491 $ hg tip
489 492 changeset: 5:5f6e8655b1c7
490 493 tag: tip
491 494 user: test
492 495 date: Thu Jan 01 00:00:00 1970 +0000
493 496 summary: Removed tag bar
494 497
495 498
496 499 Undo a tag with rollback:
497 500
498 501 $ hg rollback # destroy rev 5 (restore bar)
499 502 repository tip rolled back to revision 4 (undo commit)
500 503 working directory now based on revision 4
501 504 $ hg tags
502 505 tip 4:0c192d7d5e6b
503 506 bar 1:78391a272241
504 507 $ hg tags
505 508 tip 4:0c192d7d5e6b
506 509 bar 1:78391a272241
507 510
508 511 Test tag rank:
509 512
510 513 $ cd ..
511 514 $ hg init t3
512 515 $ cd t3
513 516 $ echo foo > foo
514 517 $ hg add foo
515 518 $ hg ci -m 'add foo' # rev 0
516 519 $ hg tag -f bar # rev 1 bar -> 0
517 520 $ hg tag -f bar # rev 2 bar -> 1
518 521 $ hg tag -fr 0 bar # rev 3 bar -> 0
519 522 $ hg tag -fr 1 bar # rev 4 bar -> 1
520 523 $ hg tag -fr 0 bar # rev 5 bar -> 0
521 524 $ hg tags
522 525 tip 5:85f05169d91d
523 526 bar 0:bbd179dfa0a7
524 527 $ hg co 3
525 528 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
526 529 $ echo barbar > foo
527 530 $ hg ci -m 'change foo' # rev 6
528 531 created new head
529 532 $ hg tags
530 533 tip 6:735c3ca72986
531 534 bar 0:bbd179dfa0a7
532 535
533 536 Don't allow moving tag without -f:
534 537
535 538 $ hg tag -r 3 bar
536 539 abort: tag 'bar' already exists (use -f to force)
537 540 [255]
538 541 $ hg tags
539 542 tip 6:735c3ca72986
540 543 bar 0:bbd179dfa0a7
541 544
542 545 Strip 1: expose an old head:
543 546
544 547 $ hg --config extensions.mq= strip 5
545 548 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
546 549 $ hg tags # partly stale cache
547 550 tip 5:735c3ca72986
548 551 bar 1:78391a272241
549 552 $ hg tags # up-to-date cache
550 553 tip 5:735c3ca72986
551 554 bar 1:78391a272241
552 555
553 556 Strip 2: destroy whole branch, no old head exposed
554 557
555 558 $ hg --config extensions.mq= strip 4
556 559 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
557 560 $ hg tags # partly stale
558 561 tip 4:735c3ca72986
559 562 bar 0:bbd179dfa0a7
560 563 $ rm -f .hg/cache/tags2-visible
561 564 $ hg tags # cold cache
562 565 tip 4:735c3ca72986
563 566 bar 0:bbd179dfa0a7
564 567
565 568 Test tag rank with 3 heads:
566 569
567 570 $ cd ..
568 571 $ hg init t4
569 572 $ cd t4
570 573 $ echo foo > foo
571 574 $ hg add
572 575 adding foo
573 576 $ hg ci -m 'add foo' # rev 0
574 577 $ hg tag bar # rev 1 bar -> 0
575 578 $ hg tag -f bar # rev 2 bar -> 1
576 579 $ hg up -qC 0
577 580 $ hg tag -fr 2 bar # rev 3 bar -> 2
578 581 $ hg tags
579 582 tip 3:197c21bbbf2c
580 583 bar 2:6fa450212aeb
581 584 $ hg up -qC 0
582 585 $ hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
583 586
584 587 Bar should still point to rev 2:
585 588
586 589 $ hg tags
587 590 tip 4:3b4b14ed0202
588 591 bar 2:6fa450212aeb
589 592
590 593 Test that removing global/local tags does not get confused when trying
591 594 to remove a tag of type X which actually only exists as a type Y:
592 595
593 596 $ cd ..
594 597 $ hg init t5
595 598 $ cd t5
596 599 $ echo foo > foo
597 600 $ hg add
598 601 adding foo
599 602 $ hg ci -m 'add foo' # rev 0
600 603
601 604 $ hg tag -r 0 -l localtag
602 605 $ hg tag --remove localtag
603 606 abort: tag 'localtag' is not a global tag
604 607 [255]
605 608 $
606 609 $ hg tag -r 0 globaltag
607 610 $ hg tag --remove -l globaltag
608 611 abort: tag 'globaltag' is not a local tag
609 612 [255]
610 613 $ hg tags -v
611 614 tip 1:a0b6fe111088
612 615 localtag 0:bbd179dfa0a7 local
613 616 globaltag 0:bbd179dfa0a7
614 617
615 618 Templated output:
616 619
617 620 (immediate values)
618 621
619 622 $ hg tags -T '{pad(tag, 9)} {rev}:{node} ({type})\n'
620 623 tip 1:a0b6fe111088c8c29567d3876cc466aa02927cae ()
621 624 localtag 0:bbd179dfa0a71671c253b3ae0aa1513b60d199fa (local)
622 625 globaltag 0:bbd179dfa0a71671c253b3ae0aa1513b60d199fa ()
623 626
624 627 (ctx/revcache dependent)
625 628
626 629 $ hg tags -T '{pad(tag, 9)} {rev} {file_adds}\n'
627 630 tip 1 .hgtags
628 631 localtag 0 foo
629 632 globaltag 0 foo
630 633
631 634 $ hg tags -T '{pad(tag, 9)} {rev}:{node|shortest}\n'
632 635 tip 1:a0b6
633 636 localtag 0:bbd1
634 637 globaltag 0:bbd1
635 638
636 639 Test for issue3911
637 640
638 641 $ hg tag -r 0 -l localtag2
639 642 $ hg tag -l --remove localtag2
640 643 $ hg tags -v
641 644 tip 1:a0b6fe111088
642 645 localtag 0:bbd179dfa0a7 local
643 646 globaltag 0:bbd179dfa0a7
644 647
645 648 $ hg tag -r 1 -f localtag
646 649 $ hg tags -v
647 650 tip 2:5c70a037bb37
648 651 localtag 1:a0b6fe111088
649 652 globaltag 0:bbd179dfa0a7
650 653
651 654 $ hg tags -v
652 655 tip 2:5c70a037bb37
653 656 localtag 1:a0b6fe111088
654 657 globaltag 0:bbd179dfa0a7
655 658
656 659 $ hg tag -r 1 localtag2
657 660 $ hg tags -v
658 661 tip 3:bbfb8cd42be2
659 662 localtag2 1:a0b6fe111088
660 663 localtag 1:a0b6fe111088
661 664 globaltag 0:bbd179dfa0a7
662 665
663 666 $ hg tags -v
664 667 tip 3:bbfb8cd42be2
665 668 localtag2 1:a0b6fe111088
666 669 localtag 1:a0b6fe111088
667 670 globaltag 0:bbd179dfa0a7
668 671
669 672 $ cd ..
670 673
671 674 Create a repository with tags data to test .hgtags fnodes transfer
672 675
673 676 $ hg init tagsserver
674 677 $ cd tagsserver
675 678 $ touch foo
676 679 $ hg -q commit -A -m initial
677 680 $ hg tag -m 'tag 0.1' 0.1
678 681 $ echo second > foo
679 682 $ hg commit -m second
680 683 $ hg tag -m 'tag 0.2' 0.2
681 684 $ hg tags
682 685 tip 3:40f0358cb314
683 686 0.2 2:f63cc8fe54e4
684 687 0.1 0:96ee1d7354c4
685 688 $ cd ..
686 689
687 690 Cloning should pull down hgtags fnodes mappings and write the cache file
688 691
689 692 $ hg clone --pull tagsserver tagsclient
690 693 requesting all changes
691 694 adding changesets
692 695 adding manifests
693 696 adding file changes
694 697 added 4 changesets with 4 changes to 2 files
695 698 new changesets 96ee1d7354c4:40f0358cb314
696 699 updating to branch default
697 700 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
698 701
699 702 Missing tags2* files means the cache wasn't written through the normal mechanism.
700 703
701 704 $ ls tagsclient/.hg/cache
702 705 branch2-base
703 706 hgtagsfnodes1
704 707 rbc-names-v1
705 708 rbc-revs-v1
706 709
707 710 Cache should contain the head only, even though other nodes have tags data
708 711
709 712 $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes1
710 713 tagsclient/.hg/cache/hgtagsfnodes1: size=96
711 714 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
712 715 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
713 716 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
714 717 0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
715 718 0040: ff ff ff ff ff ff ff ff 40 f0 35 8c 19 e0 a7 d3 |........@.5.....|
716 719 0050: 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 1e 4f 2f 8a |.\j.M...../..O/.|
717 720
718 721 Running hg tags should produce tags2* file and not change cache
719 722
720 723 $ hg -R tagsclient tags
721 724 tip 3:40f0358cb314
722 725 0.2 2:f63cc8fe54e4
723 726 0.1 0:96ee1d7354c4
724 727
725 728 $ ls tagsclient/.hg/cache
726 729 branch2-base
727 730 hgtagsfnodes1
728 731 rbc-names-v1
729 732 rbc-revs-v1
730 733 tags2-visible
731 734
732 735 $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes1
733 736 tagsclient/.hg/cache/hgtagsfnodes1: size=96
734 737 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
735 738 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
736 739 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
737 740 0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
738 741 0040: ff ff ff ff ff ff ff ff 40 f0 35 8c 19 e0 a7 d3 |........@.5.....|
739 742 0050: 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 1e 4f 2f 8a |.\j.M...../..O/.|
740 743
741 744 Check that the bundle includes cache data
742 745
743 746 $ hg -R tagsclient bundle --all ./test-cache-in-bundle-all-rev.hg
744 747 4 changesets found
745 748 $ hg debugbundle ./test-cache-in-bundle-all-rev.hg
746 749 Stream params: {Compression: BZ}
747 750 changegroup -- {nbchanges: 4, version: 02} (mandatory: True)
748 751 96ee1d7354c4ad7372047672c36a1f561e3a6a4c
749 752 c4dab0c2fd337eb9191f80c3024830a4889a8f34
750 753 f63cc8fe54e4d326f8d692805d70e092f851ddb1
751 754 40f0358cb314c824a5929ee527308d90e023bc10
752 755 hgtagsfnodes -- {} (mandatory: True)
753 756 cache:rev-branch-cache -- {} (mandatory: False)
754 757
755 758 Check that local clone includes cache data
756 759
757 760 $ hg clone tagsclient tags-local-clone
758 761 updating to branch default
759 762 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
760 763 $ (cd tags-local-clone/.hg/cache/; ls -1 tag*)
761 764 tags2-visible
762 765
763 766 Avoid writing logs on trying to delete an already deleted tag
764 767 $ hg init issue5752
765 768 $ cd issue5752
766 769 $ echo > a
767 770 $ hg commit -Am 'add a'
768 771 adding a
769 772 $ hg tag a
770 773 $ hg tags
771 774 tip 1:bd7ee4f3939b
772 775 a 0:a8a82d372bb3
773 776 $ hg log
774 777 changeset: 1:bd7ee4f3939b
775 778 tag: tip
776 779 user: test
777 780 date: Thu Jan 01 00:00:00 1970 +0000
778 781 summary: Added tag a for changeset a8a82d372bb3
779 782
780 783 changeset: 0:a8a82d372bb3
781 784 tag: a
782 785 user: test
783 786 date: Thu Jan 01 00:00:00 1970 +0000
784 787 summary: add a
785 788
786 789 $ hg tag --remove a
787 790 $ hg log
788 791 changeset: 2:e7feacc7ec9e
789 792 tag: tip
790 793 user: test
791 794 date: Thu Jan 01 00:00:00 1970 +0000
792 795 summary: Removed tag a
793 796
794 797 changeset: 1:bd7ee4f3939b
795 798 user: test
796 799 date: Thu Jan 01 00:00:00 1970 +0000
797 800 summary: Added tag a for changeset a8a82d372bb3
798 801
799 802 changeset: 0:a8a82d372bb3
800 803 user: test
801 804 date: Thu Jan 01 00:00:00 1970 +0000
802 805 summary: add a
803 806
804 807 $ hg tag --remove a
805 808 abort: tag 'a' is already removed
806 809 [255]
807 810 $ hg log
808 811 changeset: 2:e7feacc7ec9e
809 812 tag: tip
810 813 user: test
811 814 date: Thu Jan 01 00:00:00 1970 +0000
812 815 summary: Removed tag a
813 816
814 817 changeset: 1:bd7ee4f3939b
815 818 user: test
816 819 date: Thu Jan 01 00:00:00 1970 +0000
817 820 summary: Added tag a for changeset a8a82d372bb3
818 821
819 822 changeset: 0:a8a82d372bb3
820 823 user: test
821 824 date: Thu Jan 01 00:00:00 1970 +0000
822 825 summary: add a
823 826
824 827 $ cat .hgtags
825 828 a8a82d372bb35b42ff736e74f07c23bcd99c371f a
826 829 a8a82d372bb35b42ff736e74f07c23bcd99c371f a
827 830 0000000000000000000000000000000000000000 a
General Comments 0
You need to be logged in to leave comments. Login now