##// END OF EJS Templates
help: don't try to render a section on sub-topics...
Gregory Szorc -
r29747:aba2bb2a default
parent child Browse files
Show More
@@ -1,7275 +1,7278 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import difflib
11 11 import errno
12 12 import operator
13 13 import os
14 14 import random
15 15 import re
16 16 import shlex
17 17 import socket
18 18 import sys
19 19 import tempfile
20 20 import time
21 21
22 22 from .i18n import _
23 23 from .node import (
24 24 bin,
25 25 hex,
26 26 nullhex,
27 27 nullid,
28 28 nullrev,
29 29 short,
30 30 )
31 31 from . import (
32 32 archival,
33 33 bookmarks,
34 34 bundle2,
35 35 changegroup,
36 36 cmdutil,
37 37 commandserver,
38 38 context,
39 39 copies,
40 40 dagparser,
41 41 dagutil,
42 42 destutil,
43 43 discovery,
44 44 encoding,
45 45 error,
46 46 exchange,
47 47 extensions,
48 48 fileset,
49 49 formatter,
50 50 graphmod,
51 51 hbisect,
52 52 help,
53 53 hg,
54 54 hgweb,
55 55 localrepo,
56 56 lock as lockmod,
57 57 merge as mergemod,
58 58 minirst,
59 59 obsolete,
60 60 patch,
61 61 phases,
62 62 policy,
63 63 pvec,
64 64 repair,
65 65 revlog,
66 66 revset,
67 67 scmutil,
68 68 setdiscovery,
69 69 simplemerge,
70 70 sshserver,
71 71 streamclone,
72 72 templatekw,
73 73 templater,
74 74 treediscovery,
75 75 ui as uimod,
76 76 util,
77 77 )
78 78
79 79 release = lockmod.release
80 80
81 81 table = {}
82 82
83 83 command = cmdutil.command(table)
84 84
85 85 # label constants
86 86 # until 3.5, bookmarks.current was the advertised name, not
87 87 # bookmarks.active, so we must use both to avoid breaking old
88 88 # custom styles
89 89 activebookmarklabel = 'bookmarks.active bookmarks.current'
90 90
91 91 # common command options
92 92
93 93 globalopts = [
94 94 ('R', 'repository', '',
95 95 _('repository root directory or name of overlay bundle file'),
96 96 _('REPO')),
97 97 ('', 'cwd', '',
98 98 _('change working directory'), _('DIR')),
99 99 ('y', 'noninteractive', None,
100 100 _('do not prompt, automatically pick the first choice for all prompts')),
101 101 ('q', 'quiet', None, _('suppress output')),
102 102 ('v', 'verbose', None, _('enable additional output')),
103 103 ('', 'config', [],
104 104 _('set/override config option (use \'section.name=value\')'),
105 105 _('CONFIG')),
106 106 ('', 'debug', None, _('enable debugging output')),
107 107 ('', 'debugger', None, _('start debugger')),
108 108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
109 109 _('ENCODE')),
110 110 ('', 'encodingmode', encoding.encodingmode,
111 111 _('set the charset encoding mode'), _('MODE')),
112 112 ('', 'traceback', None, _('always print a traceback on exception')),
113 113 ('', 'time', None, _('time how long the command takes')),
114 114 ('', 'profile', None, _('print command execution profile')),
115 115 ('', 'version', None, _('output version information and exit')),
116 116 ('h', 'help', None, _('display help and exit')),
117 117 ('', 'hidden', False, _('consider hidden changesets')),
118 118 ]
119 119
120 120 dryrunopts = [('n', 'dry-run', None,
121 121 _('do not perform actions, just print output'))]
122 122
123 123 remoteopts = [
124 124 ('e', 'ssh', '',
125 125 _('specify ssh command to use'), _('CMD')),
126 126 ('', 'remotecmd', '',
127 127 _('specify hg command to run on the remote side'), _('CMD')),
128 128 ('', 'insecure', None,
129 129 _('do not verify server certificate (ignoring web.cacerts config)')),
130 130 ]
131 131
132 132 walkopts = [
133 133 ('I', 'include', [],
134 134 _('include names matching the given patterns'), _('PATTERN')),
135 135 ('X', 'exclude', [],
136 136 _('exclude names matching the given patterns'), _('PATTERN')),
137 137 ]
138 138
139 139 commitopts = [
140 140 ('m', 'message', '',
141 141 _('use text as commit message'), _('TEXT')),
142 142 ('l', 'logfile', '',
143 143 _('read commit message from file'), _('FILE')),
144 144 ]
145 145
146 146 commitopts2 = [
147 147 ('d', 'date', '',
148 148 _('record the specified date as commit date'), _('DATE')),
149 149 ('u', 'user', '',
150 150 _('record the specified user as committer'), _('USER')),
151 151 ]
152 152
153 153 # hidden for now
154 154 formatteropts = [
155 155 ('T', 'template', '',
156 156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
157 157 ]
158 158
159 159 templateopts = [
160 160 ('', 'style', '',
161 161 _('display using template map file (DEPRECATED)'), _('STYLE')),
162 162 ('T', 'template', '',
163 163 _('display with template'), _('TEMPLATE')),
164 164 ]
165 165
166 166 logopts = [
167 167 ('p', 'patch', None, _('show patch')),
168 168 ('g', 'git', None, _('use git extended diff format')),
169 169 ('l', 'limit', '',
170 170 _('limit number of changes displayed'), _('NUM')),
171 171 ('M', 'no-merges', None, _('do not show merges')),
172 172 ('', 'stat', None, _('output diffstat-style summary of changes')),
173 173 ('G', 'graph', None, _("show the revision DAG")),
174 174 ] + templateopts
175 175
176 176 diffopts = [
177 177 ('a', 'text', None, _('treat all files as text')),
178 178 ('g', 'git', None, _('use git extended diff format')),
179 179 ('', 'nodates', None, _('omit dates from diff headers'))
180 180 ]
181 181
182 182 diffwsopts = [
183 183 ('w', 'ignore-all-space', None,
184 184 _('ignore white space when comparing lines')),
185 185 ('b', 'ignore-space-change', None,
186 186 _('ignore changes in the amount of white space')),
187 187 ('B', 'ignore-blank-lines', None,
188 188 _('ignore changes whose lines are all blank')),
189 189 ]
190 190
191 191 diffopts2 = [
192 192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
193 193 ('p', 'show-function', None, _('show which function each change is in')),
194 194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
195 195 ] + diffwsopts + [
196 196 ('U', 'unified', '',
197 197 _('number of lines of context to show'), _('NUM')),
198 198 ('', 'stat', None, _('output diffstat-style summary of changes')),
199 199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
200 200 ]
201 201
202 202 mergetoolopts = [
203 203 ('t', 'tool', '', _('specify merge tool')),
204 204 ]
205 205
206 206 similarityopts = [
207 207 ('s', 'similarity', '',
208 208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
209 209 ]
210 210
211 211 subrepoopts = [
212 212 ('S', 'subrepos', None,
213 213 _('recurse into subrepositories'))
214 214 ]
215 215
216 216 debugrevlogopts = [
217 217 ('c', 'changelog', False, _('open changelog')),
218 218 ('m', 'manifest', False, _('open manifest')),
219 219 ('', 'dir', '', _('open directory manifest')),
220 220 ]
221 221
222 222 # Commands start here, listed alphabetically
223 223
224 224 @command('^add',
225 225 walkopts + subrepoopts + dryrunopts,
226 226 _('[OPTION]... [FILE]...'),
227 227 inferrepo=True)
228 228 def add(ui, repo, *pats, **opts):
229 229 """add the specified files on the next commit
230 230
231 231 Schedule files to be version controlled and added to the
232 232 repository.
233 233
234 234 The files will be added to the repository at the next commit. To
235 235 undo an add before that, see :hg:`forget`.
236 236
237 237 If no names are given, add all files to the repository (except
238 238 files matching ``.hgignore``).
239 239
240 240 .. container:: verbose
241 241
242 242 Examples:
243 243
244 244 - New (unknown) files are added
245 245 automatically by :hg:`add`::
246 246
247 247 $ ls
248 248 foo.c
249 249 $ hg status
250 250 ? foo.c
251 251 $ hg add
252 252 adding foo.c
253 253 $ hg status
254 254 A foo.c
255 255
256 256 - Specific files to be added can be specified::
257 257
258 258 $ ls
259 259 bar.c foo.c
260 260 $ hg status
261 261 ? bar.c
262 262 ? foo.c
263 263 $ hg add bar.c
264 264 $ hg status
265 265 A bar.c
266 266 ? foo.c
267 267
268 268 Returns 0 if all files are successfully added.
269 269 """
270 270
271 271 m = scmutil.match(repo[None], pats, opts)
272 272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
273 273 return rejected and 1 or 0
274 274
275 275 @command('addremove',
276 276 similarityopts + subrepoopts + walkopts + dryrunopts,
277 277 _('[OPTION]... [FILE]...'),
278 278 inferrepo=True)
279 279 def addremove(ui, repo, *pats, **opts):
280 280 """add all new files, delete all missing files
281 281
282 282 Add all new files and remove all missing files from the
283 283 repository.
284 284
285 285 Unless names are given, new files are ignored if they match any of
286 286 the patterns in ``.hgignore``. As with add, these changes take
287 287 effect at the next commit.
288 288
289 289 Use the -s/--similarity option to detect renamed files. This
290 290 option takes a percentage between 0 (disabled) and 100 (files must
291 291 be identical) as its parameter. With a parameter greater than 0,
292 292 this compares every removed file with every added file and records
293 293 those similar enough as renames. Detecting renamed files this way
294 294 can be expensive. After using this option, :hg:`status -C` can be
295 295 used to check which files were identified as moved or renamed. If
296 296 not specified, -s/--similarity defaults to 100 and only renames of
297 297 identical files are detected.
298 298
299 299 .. container:: verbose
300 300
301 301 Examples:
302 302
303 303 - A number of files (bar.c and foo.c) are new,
304 304 while foobar.c has been removed (without using :hg:`remove`)
305 305 from the repository::
306 306
307 307 $ ls
308 308 bar.c foo.c
309 309 $ hg status
310 310 ! foobar.c
311 311 ? bar.c
312 312 ? foo.c
313 313 $ hg addremove
314 314 adding bar.c
315 315 adding foo.c
316 316 removing foobar.c
317 317 $ hg status
318 318 A bar.c
319 319 A foo.c
320 320 R foobar.c
321 321
322 322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
323 323 Afterwards, it was edited slightly::
324 324
325 325 $ ls
326 326 foo.c
327 327 $ hg status
328 328 ! foobar.c
329 329 ? foo.c
330 330 $ hg addremove --similarity 90
331 331 removing foobar.c
332 332 adding foo.c
333 333 recording removal of foobar.c as rename to foo.c (94% similar)
334 334 $ hg status -C
335 335 A foo.c
336 336 foobar.c
337 337 R foobar.c
338 338
339 339 Returns 0 if all files are successfully added.
340 340 """
341 341 try:
342 342 sim = float(opts.get('similarity') or 100)
343 343 except ValueError:
344 344 raise error.Abort(_('similarity must be a number'))
345 345 if sim < 0 or sim > 100:
346 346 raise error.Abort(_('similarity must be between 0 and 100'))
347 347 matcher = scmutil.match(repo[None], pats, opts)
348 348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
349 349
350 350 @command('^annotate|blame',
351 351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
352 352 ('', 'follow', None,
353 353 _('follow copies/renames and list the filename (DEPRECATED)')),
354 354 ('', 'no-follow', None, _("don't follow copies and renames")),
355 355 ('a', 'text', None, _('treat all files as text')),
356 356 ('u', 'user', None, _('list the author (long with -v)')),
357 357 ('f', 'file', None, _('list the filename')),
358 358 ('d', 'date', None, _('list the date (short with -q)')),
359 359 ('n', 'number', None, _('list the revision number (default)')),
360 360 ('c', 'changeset', None, _('list the changeset')),
361 361 ('l', 'line-number', None, _('show line number at the first appearance'))
362 362 ] + diffwsopts + walkopts + formatteropts,
363 363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
364 364 inferrepo=True)
365 365 def annotate(ui, repo, *pats, **opts):
366 366 """show changeset information by line for each file
367 367
368 368 List changes in files, showing the revision id responsible for
369 369 each line.
370 370
371 371 This command is useful for discovering when a change was made and
372 372 by whom.
373 373
374 374 If you include --file, --user, or --date, the revision number is
375 375 suppressed unless you also include --number.
376 376
377 377 Without the -a/--text option, annotate will avoid processing files
378 378 it detects as binary. With -a, annotate will annotate the file
379 379 anyway, although the results will probably be neither useful
380 380 nor desirable.
381 381
382 382 Returns 0 on success.
383 383 """
384 384 if not pats:
385 385 raise error.Abort(_('at least one filename or pattern is required'))
386 386
387 387 if opts.get('follow'):
388 388 # --follow is deprecated and now just an alias for -f/--file
389 389 # to mimic the behavior of Mercurial before version 1.5
390 390 opts['file'] = True
391 391
392 392 ctx = scmutil.revsingle(repo, opts.get('rev'))
393 393
394 394 fm = ui.formatter('annotate', opts)
395 395 if ui.quiet:
396 396 datefunc = util.shortdate
397 397 else:
398 398 datefunc = util.datestr
399 399 if ctx.rev() is None:
400 400 def hexfn(node):
401 401 if node is None:
402 402 return None
403 403 else:
404 404 return fm.hexfunc(node)
405 405 if opts.get('changeset'):
406 406 # omit "+" suffix which is appended to node hex
407 407 def formatrev(rev):
408 408 if rev is None:
409 409 return '%d' % ctx.p1().rev()
410 410 else:
411 411 return '%d' % rev
412 412 else:
413 413 def formatrev(rev):
414 414 if rev is None:
415 415 return '%d+' % ctx.p1().rev()
416 416 else:
417 417 return '%d ' % rev
418 418 def formathex(hex):
419 419 if hex is None:
420 420 return '%s+' % fm.hexfunc(ctx.p1().node())
421 421 else:
422 422 return '%s ' % hex
423 423 else:
424 424 hexfn = fm.hexfunc
425 425 formatrev = formathex = str
426 426
427 427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
428 428 ('number', ' ', lambda x: x[0].rev(), formatrev),
429 429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
430 430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
431 431 ('file', ' ', lambda x: x[0].path(), str),
432 432 ('line_number', ':', lambda x: x[1], str),
433 433 ]
434 434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
435 435
436 436 if (not opts.get('user') and not opts.get('changeset')
437 437 and not opts.get('date') and not opts.get('file')):
438 438 opts['number'] = True
439 439
440 440 linenumber = opts.get('line_number') is not None
441 441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
442 442 raise error.Abort(_('at least one of -n/-c is required for -l'))
443 443
444 444 if fm:
445 445 def makefunc(get, fmt):
446 446 return get
447 447 else:
448 448 def makefunc(get, fmt):
449 449 return lambda x: fmt(get(x))
450 450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
451 451 if opts.get(op)]
452 452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
453 453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
454 454 if opts.get(op))
455 455
456 456 def bad(x, y):
457 457 raise error.Abort("%s: %s" % (x, y))
458 458
459 459 m = scmutil.match(ctx, pats, opts, badfn=bad)
460 460
461 461 follow = not opts.get('no_follow')
462 462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
463 463 whitespace=True)
464 464 for abs in ctx.walk(m):
465 465 fctx = ctx[abs]
466 466 if not opts.get('text') and util.binary(fctx.data()):
467 467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
468 468 continue
469 469
470 470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
471 471 diffopts=diffopts)
472 472 if not lines:
473 473 continue
474 474 formats = []
475 475 pieces = []
476 476
477 477 for f, sep in funcmap:
478 478 l = [f(n) for n, dummy in lines]
479 479 if fm:
480 480 formats.append(['%s' for x in l])
481 481 else:
482 482 sizes = [encoding.colwidth(x) for x in l]
483 483 ml = max(sizes)
484 484 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
485 485 pieces.append(l)
486 486
487 487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
488 488 fm.startitem()
489 489 fm.write(fields, "".join(f), *p)
490 490 fm.write('line', ": %s", l[1])
491 491
492 492 if not lines[-1][1].endswith('\n'):
493 493 fm.plain('\n')
494 494
495 495 fm.end()
496 496
497 497 @command('archive',
498 498 [('', 'no-decode', None, _('do not pass files through decoders')),
499 499 ('p', 'prefix', '', _('directory prefix for files in archive'),
500 500 _('PREFIX')),
501 501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
502 502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
503 503 ] + subrepoopts + walkopts,
504 504 _('[OPTION]... DEST'))
505 505 def archive(ui, repo, dest, **opts):
506 506 '''create an unversioned archive of a repository revision
507 507
508 508 By default, the revision used is the parent of the working
509 509 directory; use -r/--rev to specify a different revision.
510 510
511 511 The archive type is automatically detected based on file
512 512 extension (to override, use -t/--type).
513 513
514 514 .. container:: verbose
515 515
516 516 Examples:
517 517
518 518 - create a zip file containing the 1.0 release::
519 519
520 520 hg archive -r 1.0 project-1.0.zip
521 521
522 522 - create a tarball excluding .hg files::
523 523
524 524 hg archive project.tar.gz -X ".hg*"
525 525
526 526 Valid types are:
527 527
528 528 :``files``: a directory full of files (default)
529 529 :``tar``: tar archive, uncompressed
530 530 :``tbz2``: tar archive, compressed using bzip2
531 531 :``tgz``: tar archive, compressed using gzip
532 532 :``uzip``: zip archive, uncompressed
533 533 :``zip``: zip archive, compressed using deflate
534 534
535 535 The exact name of the destination archive or directory is given
536 536 using a format string; see :hg:`help export` for details.
537 537
538 538 Each member added to an archive file has a directory prefix
539 539 prepended. Use -p/--prefix to specify a format string for the
540 540 prefix. The default is the basename of the archive, with suffixes
541 541 removed.
542 542
543 543 Returns 0 on success.
544 544 '''
545 545
546 546 ctx = scmutil.revsingle(repo, opts.get('rev'))
547 547 if not ctx:
548 548 raise error.Abort(_('no working directory: please specify a revision'))
549 549 node = ctx.node()
550 550 dest = cmdutil.makefilename(repo, dest, node)
551 551 if os.path.realpath(dest) == repo.root:
552 552 raise error.Abort(_('repository root cannot be destination'))
553 553
554 554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
555 555 prefix = opts.get('prefix')
556 556
557 557 if dest == '-':
558 558 if kind == 'files':
559 559 raise error.Abort(_('cannot archive plain files to stdout'))
560 560 dest = cmdutil.makefileobj(repo, dest)
561 561 if not prefix:
562 562 prefix = os.path.basename(repo.root) + '-%h'
563 563
564 564 prefix = cmdutil.makefilename(repo, prefix, node)
565 565 matchfn = scmutil.match(ctx, [], opts)
566 566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
567 567 matchfn, prefix, subrepos=opts.get('subrepos'))
568 568
569 569 @command('backout',
570 570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
571 571 ('', 'commit', None,
572 572 _('commit if no conflicts were encountered (DEPRECATED)')),
573 573 ('', 'no-commit', None, _('do not commit')),
574 574 ('', 'parent', '',
575 575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
576 576 ('r', 'rev', '', _('revision to backout'), _('REV')),
577 577 ('e', 'edit', False, _('invoke editor on commit messages')),
578 578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
579 579 _('[OPTION]... [-r] REV'))
580 580 def backout(ui, repo, node=None, rev=None, **opts):
581 581 '''reverse effect of earlier changeset
582 582
583 583 Prepare a new changeset with the effect of REV undone in the
584 584 current working directory. If no conflicts were encountered,
585 585 it will be committed immediately.
586 586
587 587 If REV is the parent of the working directory, then this new changeset
588 588 is committed automatically (unless --no-commit is specified).
589 589
590 590 .. note::
591 591
592 592 :hg:`backout` cannot be used to fix either an unwanted or
593 593 incorrect merge.
594 594
595 595 .. container:: verbose
596 596
597 597 Examples:
598 598
599 599 - Reverse the effect of the parent of the working directory.
600 600 This backout will be committed immediately::
601 601
602 602 hg backout -r .
603 603
604 604 - Reverse the effect of previous bad revision 23::
605 605
606 606 hg backout -r 23
607 607
608 608 - Reverse the effect of previous bad revision 23 and
609 609 leave changes uncommitted::
610 610
611 611 hg backout -r 23 --no-commit
612 612 hg commit -m "Backout revision 23"
613 613
614 614 By default, the pending changeset will have one parent,
615 615 maintaining a linear history. With --merge, the pending
616 616 changeset will instead have two parents: the old parent of the
617 617 working directory and a new child of REV that simply undoes REV.
618 618
619 619 Before version 1.7, the behavior without --merge was equivalent
620 620 to specifying --merge followed by :hg:`update --clean .` to
621 621 cancel the merge and leave the child of REV as a head to be
622 622 merged separately.
623 623
624 624 See :hg:`help dates` for a list of formats valid for -d/--date.
625 625
626 626 See :hg:`help revert` for a way to restore files to the state
627 627 of another revision.
628 628
629 629 Returns 0 on success, 1 if nothing to backout or there are unresolved
630 630 files.
631 631 '''
632 632 wlock = lock = None
633 633 try:
634 634 wlock = repo.wlock()
635 635 lock = repo.lock()
636 636 return _dobackout(ui, repo, node, rev, **opts)
637 637 finally:
638 638 release(lock, wlock)
639 639
640 640 def _dobackout(ui, repo, node=None, rev=None, **opts):
641 641 if opts.get('commit') and opts.get('no_commit'):
642 642 raise error.Abort(_("cannot use --commit with --no-commit"))
643 643 if opts.get('merge') and opts.get('no_commit'):
644 644 raise error.Abort(_("cannot use --merge with --no-commit"))
645 645
646 646 if rev and node:
647 647 raise error.Abort(_("please specify just one revision"))
648 648
649 649 if not rev:
650 650 rev = node
651 651
652 652 if not rev:
653 653 raise error.Abort(_("please specify a revision to backout"))
654 654
655 655 date = opts.get('date')
656 656 if date:
657 657 opts['date'] = util.parsedate(date)
658 658
659 659 cmdutil.checkunfinished(repo)
660 660 cmdutil.bailifchanged(repo)
661 661 node = scmutil.revsingle(repo, rev).node()
662 662
663 663 op1, op2 = repo.dirstate.parents()
664 664 if not repo.changelog.isancestor(node, op1):
665 665 raise error.Abort(_('cannot backout change that is not an ancestor'))
666 666
667 667 p1, p2 = repo.changelog.parents(node)
668 668 if p1 == nullid:
669 669 raise error.Abort(_('cannot backout a change with no parents'))
670 670 if p2 != nullid:
671 671 if not opts.get('parent'):
672 672 raise error.Abort(_('cannot backout a merge changeset'))
673 673 p = repo.lookup(opts['parent'])
674 674 if p not in (p1, p2):
675 675 raise error.Abort(_('%s is not a parent of %s') %
676 676 (short(p), short(node)))
677 677 parent = p
678 678 else:
679 679 if opts.get('parent'):
680 680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
681 681 parent = p1
682 682
683 683 # the backout should appear on the same branch
684 684 branch = repo.dirstate.branch()
685 685 bheads = repo.branchheads(branch)
686 686 rctx = scmutil.revsingle(repo, hex(parent))
687 687 if not opts.get('merge') and op1 != node:
688 688 dsguard = cmdutil.dirstateguard(repo, 'backout')
689 689 try:
690 690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 691 'backout')
692 692 stats = mergemod.update(repo, parent, True, True, node, False)
693 693 repo.setparents(op1, op2)
694 694 dsguard.close()
695 695 hg._showstats(repo, stats)
696 696 if stats[3]:
697 697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
698 698 "file merges\n"))
699 699 return 1
700 700 finally:
701 701 ui.setconfig('ui', 'forcemerge', '', '')
702 702 lockmod.release(dsguard)
703 703 else:
704 704 hg.clean(repo, node, show_stats=False)
705 705 repo.dirstate.setbranch(branch)
706 706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
707 707
708 708 if opts.get('no_commit'):
709 709 msg = _("changeset %s backed out, "
710 710 "don't forget to commit.\n")
711 711 ui.status(msg % short(node))
712 712 return 0
713 713
714 714 def commitfunc(ui, repo, message, match, opts):
715 715 editform = 'backout'
716 716 e = cmdutil.getcommiteditor(editform=editform, **opts)
717 717 if not message:
718 718 # we don't translate commit messages
719 719 message = "Backed out changeset %s" % short(node)
720 720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
721 721 return repo.commit(message, opts.get('user'), opts.get('date'),
722 722 match, editor=e)
723 723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
724 724 if not newnode:
725 725 ui.status(_("nothing changed\n"))
726 726 return 1
727 727 cmdutil.commitstatus(repo, newnode, branch, bheads)
728 728
729 729 def nice(node):
730 730 return '%d:%s' % (repo.changelog.rev(node), short(node))
731 731 ui.status(_('changeset %s backs out changeset %s\n') %
732 732 (nice(repo.changelog.tip()), nice(node)))
733 733 if opts.get('merge') and op1 != node:
734 734 hg.clean(repo, op1, show_stats=False)
735 735 ui.status(_('merging with changeset %s\n')
736 736 % nice(repo.changelog.tip()))
737 737 try:
738 738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
739 739 'backout')
740 740 return hg.merge(repo, hex(repo.changelog.tip()))
741 741 finally:
742 742 ui.setconfig('ui', 'forcemerge', '', '')
743 743 return 0
744 744
745 745 @command('bisect',
746 746 [('r', 'reset', False, _('reset bisect state')),
747 747 ('g', 'good', False, _('mark changeset good')),
748 748 ('b', 'bad', False, _('mark changeset bad')),
749 749 ('s', 'skip', False, _('skip testing changeset')),
750 750 ('e', 'extend', False, _('extend the bisect range')),
751 751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
752 752 ('U', 'noupdate', False, _('do not update to target'))],
753 753 _("[-gbsr] [-U] [-c CMD] [REV]"))
754 754 def bisect(ui, repo, rev=None, extra=None, command=None,
755 755 reset=None, good=None, bad=None, skip=None, extend=None,
756 756 noupdate=None):
757 757 """subdivision search of changesets
758 758
759 759 This command helps to find changesets which introduce problems. To
760 760 use, mark the earliest changeset you know exhibits the problem as
761 761 bad, then mark the latest changeset which is free from the problem
762 762 as good. Bisect will update your working directory to a revision
763 763 for testing (unless the -U/--noupdate option is specified). Once
764 764 you have performed tests, mark the working directory as good or
765 765 bad, and bisect will either update to another candidate changeset
766 766 or announce that it has found the bad revision.
767 767
768 768 As a shortcut, you can also use the revision argument to mark a
769 769 revision as good or bad without checking it out first.
770 770
771 771 If you supply a command, it will be used for automatic bisection.
772 772 The environment variable HG_NODE will contain the ID of the
773 773 changeset being tested. The exit status of the command will be
774 774 used to mark revisions as good or bad: status 0 means good, 125
775 775 means to skip the revision, 127 (command not found) will abort the
776 776 bisection, and any other non-zero exit status means the revision
777 777 is bad.
778 778
779 779 .. container:: verbose
780 780
781 781 Some examples:
782 782
783 783 - start a bisection with known bad revision 34, and good revision 12::
784 784
785 785 hg bisect --bad 34
786 786 hg bisect --good 12
787 787
788 788 - advance the current bisection by marking current revision as good or
789 789 bad::
790 790
791 791 hg bisect --good
792 792 hg bisect --bad
793 793
794 794 - mark the current revision, or a known revision, to be skipped (e.g. if
795 795 that revision is not usable because of another issue)::
796 796
797 797 hg bisect --skip
798 798 hg bisect --skip 23
799 799
800 800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
801 801
802 802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
803 803
804 804 - forget the current bisection::
805 805
806 806 hg bisect --reset
807 807
808 808 - use 'make && make tests' to automatically find the first broken
809 809 revision::
810 810
811 811 hg bisect --reset
812 812 hg bisect --bad 34
813 813 hg bisect --good 12
814 814 hg bisect --command "make && make tests"
815 815
816 816 - see all changesets whose states are already known in the current
817 817 bisection::
818 818
819 819 hg log -r "bisect(pruned)"
820 820
821 821 - see the changeset currently being bisected (especially useful
822 822 if running with -U/--noupdate)::
823 823
824 824 hg log -r "bisect(current)"
825 825
826 826 - see all changesets that took part in the current bisection::
827 827
828 828 hg log -r "bisect(range)"
829 829
830 830 - you can even get a nice graph::
831 831
832 832 hg log --graph -r "bisect(range)"
833 833
834 834 See :hg:`help revsets` for more about the `bisect()` keyword.
835 835
836 836 Returns 0 on success.
837 837 """
838 838 def extendbisectrange(nodes, good):
839 839 # bisect is incomplete when it ends on a merge node and
840 840 # one of the parent was not checked.
841 841 parents = repo[nodes[0]].parents()
842 842 if len(parents) > 1:
843 843 if good:
844 844 side = state['bad']
845 845 else:
846 846 side = state['good']
847 847 num = len(set(i.node() for i in parents) & set(side))
848 848 if num == 1:
849 849 return parents[0].ancestor(parents[1])
850 850 return None
851 851
852 852 def print_result(nodes, good):
853 853 displayer = cmdutil.show_changeset(ui, repo, {})
854 854 if len(nodes) == 1:
855 855 # narrowed it down to a single revision
856 856 if good:
857 857 ui.write(_("The first good revision is:\n"))
858 858 else:
859 859 ui.write(_("The first bad revision is:\n"))
860 860 displayer.show(repo[nodes[0]])
861 861 extendnode = extendbisectrange(nodes, good)
862 862 if extendnode is not None:
863 863 ui.write(_('Not all ancestors of this changeset have been'
864 864 ' checked.\nUse bisect --extend to continue the '
865 865 'bisection from\nthe common ancestor, %s.\n')
866 866 % extendnode)
867 867 else:
868 868 # multiple possible revisions
869 869 if good:
870 870 ui.write(_("Due to skipped revisions, the first "
871 871 "good revision could be any of:\n"))
872 872 else:
873 873 ui.write(_("Due to skipped revisions, the first "
874 874 "bad revision could be any of:\n"))
875 875 for n in nodes:
876 876 displayer.show(repo[n])
877 877 displayer.close()
878 878
879 879 def check_state(state, interactive=True):
880 880 if not state['good'] or not state['bad']:
881 881 if (good or bad or skip or reset) and interactive:
882 882 return
883 883 if not state['good']:
884 884 raise error.Abort(_('cannot bisect (no known good revisions)'))
885 885 else:
886 886 raise error.Abort(_('cannot bisect (no known bad revisions)'))
887 887 return True
888 888
889 889 # backward compatibility
890 890 if rev in "good bad reset init".split():
891 891 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
892 892 cmd, rev, extra = rev, extra, None
893 893 if cmd == "good":
894 894 good = True
895 895 elif cmd == "bad":
896 896 bad = True
897 897 else:
898 898 reset = True
899 899 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
900 900 raise error.Abort(_('incompatible arguments'))
901 901
902 902 cmdutil.checkunfinished(repo)
903 903
904 904 if reset:
905 905 p = repo.join("bisect.state")
906 906 if os.path.exists(p):
907 907 os.unlink(p)
908 908 return
909 909
910 910 state = hbisect.load_state(repo)
911 911
912 912 if command:
913 913 changesets = 1
914 914 if noupdate:
915 915 try:
916 916 node = state['current'][0]
917 917 except LookupError:
918 918 raise error.Abort(_('current bisect revision is unknown - '
919 919 'start a new bisect to fix'))
920 920 else:
921 921 node, p2 = repo.dirstate.parents()
922 922 if p2 != nullid:
923 923 raise error.Abort(_('current bisect revision is a merge'))
924 924 try:
925 925 while changesets:
926 926 # update state
927 927 state['current'] = [node]
928 928 hbisect.save_state(repo, state)
929 929 status = ui.system(command, environ={'HG_NODE': hex(node)})
930 930 if status == 125:
931 931 transition = "skip"
932 932 elif status == 0:
933 933 transition = "good"
934 934 # status < 0 means process was killed
935 935 elif status == 127:
936 936 raise error.Abort(_("failed to execute %s") % command)
937 937 elif status < 0:
938 938 raise error.Abort(_("%s killed") % command)
939 939 else:
940 940 transition = "bad"
941 941 ctx = scmutil.revsingle(repo, rev, node)
942 942 rev = None # clear for future iterations
943 943 state[transition].append(ctx.node())
944 944 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
945 945 check_state(state, interactive=False)
946 946 # bisect
947 947 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
948 948 # update to next check
949 949 node = nodes[0]
950 950 if not noupdate:
951 951 cmdutil.bailifchanged(repo)
952 952 hg.clean(repo, node, show_stats=False)
953 953 finally:
954 954 state['current'] = [node]
955 955 hbisect.save_state(repo, state)
956 956 print_result(nodes, bgood)
957 957 return
958 958
959 959 # update state
960 960
961 961 if rev:
962 962 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
963 963 else:
964 964 nodes = [repo.lookup('.')]
965 965
966 966 if good or bad or skip:
967 967 if good:
968 968 state['good'] += nodes
969 969 elif bad:
970 970 state['bad'] += nodes
971 971 elif skip:
972 972 state['skip'] += nodes
973 973 hbisect.save_state(repo, state)
974 974
975 975 if not check_state(state):
976 976 return
977 977
978 978 # actually bisect
979 979 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
980 980 if extend:
981 981 if not changesets:
982 982 extendnode = extendbisectrange(nodes, good)
983 983 if extendnode is not None:
984 984 ui.write(_("Extending search to changeset %d:%s\n")
985 985 % (extendnode.rev(), extendnode))
986 986 state['current'] = [extendnode.node()]
987 987 hbisect.save_state(repo, state)
988 988 if noupdate:
989 989 return
990 990 cmdutil.bailifchanged(repo)
991 991 return hg.clean(repo, extendnode.node())
992 992 raise error.Abort(_("nothing to extend"))
993 993
994 994 if changesets == 0:
995 995 print_result(nodes, good)
996 996 else:
997 997 assert len(nodes) == 1 # only a single node can be tested next
998 998 node = nodes[0]
999 999 # compute the approximate number of remaining tests
1000 1000 tests, size = 0, 2
1001 1001 while size <= changesets:
1002 1002 tests, size = tests + 1, size * 2
1003 1003 rev = repo.changelog.rev(node)
1004 1004 ui.write(_("Testing changeset %d:%s "
1005 1005 "(%d changesets remaining, ~%d tests)\n")
1006 1006 % (rev, short(node), changesets, tests))
1007 1007 state['current'] = [node]
1008 1008 hbisect.save_state(repo, state)
1009 1009 if not noupdate:
1010 1010 cmdutil.bailifchanged(repo)
1011 1011 return hg.clean(repo, node)
1012 1012
1013 1013 @command('bookmarks|bookmark',
1014 1014 [('f', 'force', False, _('force')),
1015 1015 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1016 1016 ('d', 'delete', False, _('delete a given bookmark')),
1017 1017 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1018 1018 ('i', 'inactive', False, _('mark a bookmark inactive')),
1019 1019 ] + formatteropts,
1020 1020 _('hg bookmarks [OPTIONS]... [NAME]...'))
1021 1021 def bookmark(ui, repo, *names, **opts):
1022 1022 '''create a new bookmark or list existing bookmarks
1023 1023
1024 1024 Bookmarks are labels on changesets to help track lines of development.
1025 1025 Bookmarks are unversioned and can be moved, renamed and deleted.
1026 1026 Deleting or moving a bookmark has no effect on the associated changesets.
1027 1027
1028 1028 Creating or updating to a bookmark causes it to be marked as 'active'.
1029 1029 The active bookmark is indicated with a '*'.
1030 1030 When a commit is made, the active bookmark will advance to the new commit.
1031 1031 A plain :hg:`update` will also advance an active bookmark, if possible.
1032 1032 Updating away from a bookmark will cause it to be deactivated.
1033 1033
1034 1034 Bookmarks can be pushed and pulled between repositories (see
1035 1035 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1036 1036 diverged, a new 'divergent bookmark' of the form 'name@path' will
1037 1037 be created. Using :hg:`merge` will resolve the divergence.
1038 1038
1039 1039 A bookmark named '@' has the special property that :hg:`clone` will
1040 1040 check it out by default if it exists.
1041 1041
1042 1042 .. container:: verbose
1043 1043
1044 1044 Examples:
1045 1045
1046 1046 - create an active bookmark for a new line of development::
1047 1047
1048 1048 hg book new-feature
1049 1049
1050 1050 - create an inactive bookmark as a place marker::
1051 1051
1052 1052 hg book -i reviewed
1053 1053
1054 1054 - create an inactive bookmark on another changeset::
1055 1055
1056 1056 hg book -r .^ tested
1057 1057
1058 1058 - rename bookmark turkey to dinner::
1059 1059
1060 1060 hg book -m turkey dinner
1061 1061
1062 1062 - move the '@' bookmark from another branch::
1063 1063
1064 1064 hg book -f @
1065 1065 '''
1066 1066 force = opts.get('force')
1067 1067 rev = opts.get('rev')
1068 1068 delete = opts.get('delete')
1069 1069 rename = opts.get('rename')
1070 1070 inactive = opts.get('inactive')
1071 1071
1072 1072 def checkformat(mark):
1073 1073 mark = mark.strip()
1074 1074 if not mark:
1075 1075 raise error.Abort(_("bookmark names cannot consist entirely of "
1076 1076 "whitespace"))
1077 1077 scmutil.checknewlabel(repo, mark, 'bookmark')
1078 1078 return mark
1079 1079
1080 1080 def checkconflict(repo, mark, cur, force=False, target=None):
1081 1081 if mark in marks and not force:
1082 1082 if target:
1083 1083 if marks[mark] == target and target == cur:
1084 1084 # re-activating a bookmark
1085 1085 return
1086 1086 anc = repo.changelog.ancestors([repo[target].rev()])
1087 1087 bmctx = repo[marks[mark]]
1088 1088 divs = [repo[b].node() for b in marks
1089 1089 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1090 1090
1091 1091 # allow resolving a single divergent bookmark even if moving
1092 1092 # the bookmark across branches when a revision is specified
1093 1093 # that contains a divergent bookmark
1094 1094 if bmctx.rev() not in anc and target in divs:
1095 1095 bookmarks.deletedivergent(repo, [target], mark)
1096 1096 return
1097 1097
1098 1098 deletefrom = [b for b in divs
1099 1099 if repo[b].rev() in anc or b == target]
1100 1100 bookmarks.deletedivergent(repo, deletefrom, mark)
1101 1101 if bookmarks.validdest(repo, bmctx, repo[target]):
1102 1102 ui.status(_("moving bookmark '%s' forward from %s\n") %
1103 1103 (mark, short(bmctx.node())))
1104 1104 return
1105 1105 raise error.Abort(_("bookmark '%s' already exists "
1106 1106 "(use -f to force)") % mark)
1107 1107 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1108 1108 and not force):
1109 1109 raise error.Abort(
1110 1110 _("a bookmark cannot have the name of an existing branch"))
1111 1111
1112 1112 if delete and rename:
1113 1113 raise error.Abort(_("--delete and --rename are incompatible"))
1114 1114 if delete and rev:
1115 1115 raise error.Abort(_("--rev is incompatible with --delete"))
1116 1116 if rename and rev:
1117 1117 raise error.Abort(_("--rev is incompatible with --rename"))
1118 1118 if not names and (delete or rev):
1119 1119 raise error.Abort(_("bookmark name required"))
1120 1120
1121 1121 if delete or rename or names or inactive:
1122 1122 wlock = lock = tr = None
1123 1123 try:
1124 1124 wlock = repo.wlock()
1125 1125 lock = repo.lock()
1126 1126 cur = repo.changectx('.').node()
1127 1127 marks = repo._bookmarks
1128 1128 if delete:
1129 1129 tr = repo.transaction('bookmark')
1130 1130 for mark in names:
1131 1131 if mark not in marks:
1132 1132 raise error.Abort(_("bookmark '%s' does not exist") %
1133 1133 mark)
1134 1134 if mark == repo._activebookmark:
1135 1135 bookmarks.deactivate(repo)
1136 1136 del marks[mark]
1137 1137
1138 1138 elif rename:
1139 1139 tr = repo.transaction('bookmark')
1140 1140 if not names:
1141 1141 raise error.Abort(_("new bookmark name required"))
1142 1142 elif len(names) > 1:
1143 1143 raise error.Abort(_("only one new bookmark name allowed"))
1144 1144 mark = checkformat(names[0])
1145 1145 if rename not in marks:
1146 1146 raise error.Abort(_("bookmark '%s' does not exist")
1147 1147 % rename)
1148 1148 checkconflict(repo, mark, cur, force)
1149 1149 marks[mark] = marks[rename]
1150 1150 if repo._activebookmark == rename and not inactive:
1151 1151 bookmarks.activate(repo, mark)
1152 1152 del marks[rename]
1153 1153 elif names:
1154 1154 tr = repo.transaction('bookmark')
1155 1155 newact = None
1156 1156 for mark in names:
1157 1157 mark = checkformat(mark)
1158 1158 if newact is None:
1159 1159 newact = mark
1160 1160 if inactive and mark == repo._activebookmark:
1161 1161 bookmarks.deactivate(repo)
1162 1162 return
1163 1163 tgt = cur
1164 1164 if rev:
1165 1165 tgt = scmutil.revsingle(repo, rev).node()
1166 1166 checkconflict(repo, mark, cur, force, tgt)
1167 1167 marks[mark] = tgt
1168 1168 if not inactive and cur == marks[newact] and not rev:
1169 1169 bookmarks.activate(repo, newact)
1170 1170 elif cur != tgt and newact == repo._activebookmark:
1171 1171 bookmarks.deactivate(repo)
1172 1172 elif inactive:
1173 1173 if len(marks) == 0:
1174 1174 ui.status(_("no bookmarks set\n"))
1175 1175 elif not repo._activebookmark:
1176 1176 ui.status(_("no active bookmark\n"))
1177 1177 else:
1178 1178 bookmarks.deactivate(repo)
1179 1179 if tr is not None:
1180 1180 marks.recordchange(tr)
1181 1181 tr.close()
1182 1182 finally:
1183 1183 lockmod.release(tr, lock, wlock)
1184 1184 else: # show bookmarks
1185 1185 fm = ui.formatter('bookmarks', opts)
1186 1186 hexfn = fm.hexfunc
1187 1187 marks = repo._bookmarks
1188 1188 if len(marks) == 0 and not fm:
1189 1189 ui.status(_("no bookmarks set\n"))
1190 1190 for bmark, n in sorted(marks.iteritems()):
1191 1191 active = repo._activebookmark
1192 1192 if bmark == active:
1193 1193 prefix, label = '*', activebookmarklabel
1194 1194 else:
1195 1195 prefix, label = ' ', ''
1196 1196
1197 1197 fm.startitem()
1198 1198 if not ui.quiet:
1199 1199 fm.plain(' %s ' % prefix, label=label)
1200 1200 fm.write('bookmark', '%s', bmark, label=label)
1201 1201 pad = " " * (25 - encoding.colwidth(bmark))
1202 1202 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1203 1203 repo.changelog.rev(n), hexfn(n), label=label)
1204 1204 fm.data(active=(bmark == active))
1205 1205 fm.plain('\n')
1206 1206 fm.end()
1207 1207
1208 1208 @command('branch',
1209 1209 [('f', 'force', None,
1210 1210 _('set branch name even if it shadows an existing branch')),
1211 1211 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1212 1212 _('[-fC] [NAME]'))
1213 1213 def branch(ui, repo, label=None, **opts):
1214 1214 """set or show the current branch name
1215 1215
1216 1216 .. note::
1217 1217
1218 1218 Branch names are permanent and global. Use :hg:`bookmark` to create a
1219 1219 light-weight bookmark instead. See :hg:`help glossary` for more
1220 1220 information about named branches and bookmarks.
1221 1221
1222 1222 With no argument, show the current branch name. With one argument,
1223 1223 set the working directory branch name (the branch will not exist
1224 1224 in the repository until the next commit). Standard practice
1225 1225 recommends that primary development take place on the 'default'
1226 1226 branch.
1227 1227
1228 1228 Unless -f/--force is specified, branch will not let you set a
1229 1229 branch name that already exists.
1230 1230
1231 1231 Use -C/--clean to reset the working directory branch to that of
1232 1232 the parent of the working directory, negating a previous branch
1233 1233 change.
1234 1234
1235 1235 Use the command :hg:`update` to switch to an existing branch. Use
1236 1236 :hg:`commit --close-branch` to mark this branch head as closed.
1237 1237 When all heads of a branch are closed, the branch will be
1238 1238 considered closed.
1239 1239
1240 1240 Returns 0 on success.
1241 1241 """
1242 1242 if label:
1243 1243 label = label.strip()
1244 1244
1245 1245 if not opts.get('clean') and not label:
1246 1246 ui.write("%s\n" % repo.dirstate.branch())
1247 1247 return
1248 1248
1249 1249 with repo.wlock():
1250 1250 if opts.get('clean'):
1251 1251 label = repo[None].p1().branch()
1252 1252 repo.dirstate.setbranch(label)
1253 1253 ui.status(_('reset working directory to branch %s\n') % label)
1254 1254 elif label:
1255 1255 if not opts.get('force') and label in repo.branchmap():
1256 1256 if label not in [p.branch() for p in repo[None].parents()]:
1257 1257 raise error.Abort(_('a branch of the same name already'
1258 1258 ' exists'),
1259 1259 # i18n: "it" refers to an existing branch
1260 1260 hint=_("use 'hg update' to switch to it"))
1261 1261 scmutil.checknewlabel(repo, label, 'branch')
1262 1262 repo.dirstate.setbranch(label)
1263 1263 ui.status(_('marked working directory as branch %s\n') % label)
1264 1264
1265 1265 # find any open named branches aside from default
1266 1266 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1267 1267 if n != "default" and not c]
1268 1268 if not others:
1269 1269 ui.status(_('(branches are permanent and global, '
1270 1270 'did you want a bookmark?)\n'))
1271 1271
1272 1272 @command('branches',
1273 1273 [('a', 'active', False,
1274 1274 _('show only branches that have unmerged heads (DEPRECATED)')),
1275 1275 ('c', 'closed', False, _('show normal and closed branches')),
1276 1276 ] + formatteropts,
1277 1277 _('[-c]'))
1278 1278 def branches(ui, repo, active=False, closed=False, **opts):
1279 1279 """list repository named branches
1280 1280
1281 1281 List the repository's named branches, indicating which ones are
1282 1282 inactive. If -c/--closed is specified, also list branches which have
1283 1283 been marked closed (see :hg:`commit --close-branch`).
1284 1284
1285 1285 Use the command :hg:`update` to switch to an existing branch.
1286 1286
1287 1287 Returns 0.
1288 1288 """
1289 1289
1290 1290 fm = ui.formatter('branches', opts)
1291 1291 hexfunc = fm.hexfunc
1292 1292
1293 1293 allheads = set(repo.heads())
1294 1294 branches = []
1295 1295 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1296 1296 isactive = not isclosed and bool(set(heads) & allheads)
1297 1297 branches.append((tag, repo[tip], isactive, not isclosed))
1298 1298 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1299 1299 reverse=True)
1300 1300
1301 1301 for tag, ctx, isactive, isopen in branches:
1302 1302 if active and not isactive:
1303 1303 continue
1304 1304 if isactive:
1305 1305 label = 'branches.active'
1306 1306 notice = ''
1307 1307 elif not isopen:
1308 1308 if not closed:
1309 1309 continue
1310 1310 label = 'branches.closed'
1311 1311 notice = _(' (closed)')
1312 1312 else:
1313 1313 label = 'branches.inactive'
1314 1314 notice = _(' (inactive)')
1315 1315 current = (tag == repo.dirstate.branch())
1316 1316 if current:
1317 1317 label = 'branches.current'
1318 1318
1319 1319 fm.startitem()
1320 1320 fm.write('branch', '%s', tag, label=label)
1321 1321 rev = ctx.rev()
1322 1322 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1323 1323 fmt = ' ' * padsize + ' %d:%s'
1324 1324 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1325 1325 label='log.changeset changeset.%s' % ctx.phasestr())
1326 1326 fm.data(active=isactive, closed=not isopen, current=current)
1327 1327 if not ui.quiet:
1328 1328 fm.plain(notice)
1329 1329 fm.plain('\n')
1330 1330 fm.end()
1331 1331
1332 1332 @command('bundle',
1333 1333 [('f', 'force', None, _('run even when the destination is unrelated')),
1334 1334 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1335 1335 _('REV')),
1336 1336 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1337 1337 _('BRANCH')),
1338 1338 ('', 'base', [],
1339 1339 _('a base changeset assumed to be available at the destination'),
1340 1340 _('REV')),
1341 1341 ('a', 'all', None, _('bundle all changesets in the repository')),
1342 1342 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1343 1343 ] + remoteopts,
1344 1344 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1345 1345 def bundle(ui, repo, fname, dest=None, **opts):
1346 1346 """create a changegroup file
1347 1347
1348 1348 Generate a changegroup file collecting changesets to be added
1349 1349 to a repository.
1350 1350
1351 1351 To create a bundle containing all changesets, use -a/--all
1352 1352 (or --base null). Otherwise, hg assumes the destination will have
1353 1353 all the nodes you specify with --base parameters. Otherwise, hg
1354 1354 will assume the repository has all the nodes in destination, or
1355 1355 default-push/default if no destination is specified.
1356 1356
1357 1357 You can change bundle format with the -t/--type option. You can
1358 1358 specify a compression, a bundle version or both using a dash
1359 1359 (comp-version). The available compression methods are: none, bzip2,
1360 1360 and gzip (by default, bundles are compressed using bzip2). The
1361 1361 available formats are: v1, v2 (default to most suitable).
1362 1362
1363 1363 The bundle file can then be transferred using conventional means
1364 1364 and applied to another repository with the unbundle or pull
1365 1365 command. This is useful when direct push and pull are not
1366 1366 available or when exporting an entire repository is undesirable.
1367 1367
1368 1368 Applying bundles preserves all changeset contents including
1369 1369 permissions, copy/rename information, and revision history.
1370 1370
1371 1371 Returns 0 on success, 1 if no changes found.
1372 1372 """
1373 1373 revs = None
1374 1374 if 'rev' in opts:
1375 1375 revstrings = opts['rev']
1376 1376 revs = scmutil.revrange(repo, revstrings)
1377 1377 if revstrings and not revs:
1378 1378 raise error.Abort(_('no commits to bundle'))
1379 1379
1380 1380 bundletype = opts.get('type', 'bzip2').lower()
1381 1381 try:
1382 1382 bcompression, cgversion, params = exchange.parsebundlespec(
1383 1383 repo, bundletype, strict=False)
1384 1384 except error.UnsupportedBundleSpecification as e:
1385 1385 raise error.Abort(str(e),
1386 1386 hint=_('see "hg help bundle" for supported '
1387 1387 'values for --type'))
1388 1388
1389 1389 # Packed bundles are a pseudo bundle format for now.
1390 1390 if cgversion == 's1':
1391 1391 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1392 1392 hint=_("use 'hg debugcreatestreamclonebundle'"))
1393 1393
1394 1394 if opts.get('all'):
1395 1395 if dest:
1396 1396 raise error.Abort(_("--all is incompatible with specifying "
1397 1397 "a destination"))
1398 1398 if opts.get('base'):
1399 1399 ui.warn(_("ignoring --base because --all was specified\n"))
1400 1400 base = ['null']
1401 1401 else:
1402 1402 base = scmutil.revrange(repo, opts.get('base'))
1403 1403 # TODO: get desired bundlecaps from command line.
1404 1404 bundlecaps = None
1405 1405 if cgversion not in changegroup.supportedoutgoingversions(repo):
1406 1406 raise error.Abort(_("repository does not support bundle version %s") %
1407 1407 cgversion)
1408 1408
1409 1409 if base:
1410 1410 if dest:
1411 1411 raise error.Abort(_("--base is incompatible with specifying "
1412 1412 "a destination"))
1413 1413 common = [repo.lookup(rev) for rev in base]
1414 1414 heads = revs and map(repo.lookup, revs) or revs
1415 1415 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1416 1416 common=common, bundlecaps=bundlecaps,
1417 1417 version=cgversion)
1418 1418 outgoing = None
1419 1419 else:
1420 1420 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1421 1421 dest, branches = hg.parseurl(dest, opts.get('branch'))
1422 1422 other = hg.peer(repo, opts, dest)
1423 1423 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1424 1424 heads = revs and map(repo.lookup, revs) or revs
1425 1425 outgoing = discovery.findcommonoutgoing(repo, other,
1426 1426 onlyheads=heads,
1427 1427 force=opts.get('force'),
1428 1428 portable=True)
1429 1429 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1430 1430 bundlecaps, version=cgversion)
1431 1431 if not cg:
1432 1432 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1433 1433 return 1
1434 1434
1435 1435 if cgversion == '01': #bundle1
1436 1436 if bcompression is None:
1437 1437 bcompression = 'UN'
1438 1438 bversion = 'HG10' + bcompression
1439 1439 bcompression = None
1440 1440 else:
1441 1441 assert cgversion == '02'
1442 1442 bversion = 'HG20'
1443 1443
1444 1444 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1445 1445
1446 1446 @command('cat',
1447 1447 [('o', 'output', '',
1448 1448 _('print output to file with formatted name'), _('FORMAT')),
1449 1449 ('r', 'rev', '', _('print the given revision'), _('REV')),
1450 1450 ('', 'decode', None, _('apply any matching decode filter')),
1451 1451 ] + walkopts,
1452 1452 _('[OPTION]... FILE...'),
1453 1453 inferrepo=True)
1454 1454 def cat(ui, repo, file1, *pats, **opts):
1455 1455 """output the current or given revision of files
1456 1456
1457 1457 Print the specified files as they were at the given revision. If
1458 1458 no revision is given, the parent of the working directory is used.
1459 1459
1460 1460 Output may be to a file, in which case the name of the file is
1461 1461 given using a format string. The formatting rules as follows:
1462 1462
1463 1463 :``%%``: literal "%" character
1464 1464 :``%s``: basename of file being printed
1465 1465 :``%d``: dirname of file being printed, or '.' if in repository root
1466 1466 :``%p``: root-relative path name of file being printed
1467 1467 :``%H``: changeset hash (40 hexadecimal digits)
1468 1468 :``%R``: changeset revision number
1469 1469 :``%h``: short-form changeset hash (12 hexadecimal digits)
1470 1470 :``%r``: zero-padded changeset revision number
1471 1471 :``%b``: basename of the exporting repository
1472 1472
1473 1473 Returns 0 on success.
1474 1474 """
1475 1475 ctx = scmutil.revsingle(repo, opts.get('rev'))
1476 1476 m = scmutil.match(ctx, (file1,) + pats, opts)
1477 1477
1478 1478 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1479 1479
1480 1480 @command('^clone',
1481 1481 [('U', 'noupdate', None, _('the clone will include an empty working '
1482 1482 'directory (only a repository)')),
1483 1483 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1484 1484 _('REV')),
1485 1485 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1486 1486 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1487 1487 ('', 'pull', None, _('use pull protocol to copy metadata')),
1488 1488 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1489 1489 ] + remoteopts,
1490 1490 _('[OPTION]... SOURCE [DEST]'),
1491 1491 norepo=True)
1492 1492 def clone(ui, source, dest=None, **opts):
1493 1493 """make a copy of an existing repository
1494 1494
1495 1495 Create a copy of an existing repository in a new directory.
1496 1496
1497 1497 If no destination directory name is specified, it defaults to the
1498 1498 basename of the source.
1499 1499
1500 1500 The location of the source is added to the new repository's
1501 1501 ``.hg/hgrc`` file, as the default to be used for future pulls.
1502 1502
1503 1503 Only local paths and ``ssh://`` URLs are supported as
1504 1504 destinations. For ``ssh://`` destinations, no working directory or
1505 1505 ``.hg/hgrc`` will be created on the remote side.
1506 1506
1507 1507 If the source repository has a bookmark called '@' set, that
1508 1508 revision will be checked out in the new repository by default.
1509 1509
1510 1510 To check out a particular version, use -u/--update, or
1511 1511 -U/--noupdate to create a clone with no working directory.
1512 1512
1513 1513 To pull only a subset of changesets, specify one or more revisions
1514 1514 identifiers with -r/--rev or branches with -b/--branch. The
1515 1515 resulting clone will contain only the specified changesets and
1516 1516 their ancestors. These options (or 'clone src#rev dest') imply
1517 1517 --pull, even for local source repositories.
1518 1518
1519 1519 .. note::
1520 1520
1521 1521 Specifying a tag will include the tagged changeset but not the
1522 1522 changeset containing the tag.
1523 1523
1524 1524 .. container:: verbose
1525 1525
1526 1526 For efficiency, hardlinks are used for cloning whenever the
1527 1527 source and destination are on the same filesystem (note this
1528 1528 applies only to the repository data, not to the working
1529 1529 directory). Some filesystems, such as AFS, implement hardlinking
1530 1530 incorrectly, but do not report errors. In these cases, use the
1531 1531 --pull option to avoid hardlinking.
1532 1532
1533 1533 In some cases, you can clone repositories and the working
1534 1534 directory using full hardlinks with ::
1535 1535
1536 1536 $ cp -al REPO REPOCLONE
1537 1537
1538 1538 This is the fastest way to clone, but it is not always safe. The
1539 1539 operation is not atomic (making sure REPO is not modified during
1540 1540 the operation is up to you) and you have to make sure your
1541 1541 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1542 1542 so). Also, this is not compatible with certain extensions that
1543 1543 place their metadata under the .hg directory, such as mq.
1544 1544
1545 1545 Mercurial will update the working directory to the first applicable
1546 1546 revision from this list:
1547 1547
1548 1548 a) null if -U or the source repository has no changesets
1549 1549 b) if -u . and the source repository is local, the first parent of
1550 1550 the source repository's working directory
1551 1551 c) the changeset specified with -u (if a branch name, this means the
1552 1552 latest head of that branch)
1553 1553 d) the changeset specified with -r
1554 1554 e) the tipmost head specified with -b
1555 1555 f) the tipmost head specified with the url#branch source syntax
1556 1556 g) the revision marked with the '@' bookmark, if present
1557 1557 h) the tipmost head of the default branch
1558 1558 i) tip
1559 1559
1560 1560 When cloning from servers that support it, Mercurial may fetch
1561 1561 pre-generated data from a server-advertised URL. When this is done,
1562 1562 hooks operating on incoming changesets and changegroups may fire twice,
1563 1563 once for the bundle fetched from the URL and another for any additional
1564 1564 data not fetched from this URL. In addition, if an error occurs, the
1565 1565 repository may be rolled back to a partial clone. This behavior may
1566 1566 change in future releases. See :hg:`help -e clonebundles` for more.
1567 1567
1568 1568 Examples:
1569 1569
1570 1570 - clone a remote repository to a new directory named hg/::
1571 1571
1572 1572 hg clone http://selenic.com/hg
1573 1573
1574 1574 - create a lightweight local clone::
1575 1575
1576 1576 hg clone project/ project-feature/
1577 1577
1578 1578 - clone from an absolute path on an ssh server (note double-slash)::
1579 1579
1580 1580 hg clone ssh://user@server//home/projects/alpha/
1581 1581
1582 1582 - do a high-speed clone over a LAN while checking out a
1583 1583 specified version::
1584 1584
1585 1585 hg clone --uncompressed http://server/repo -u 1.5
1586 1586
1587 1587 - create a repository without changesets after a particular revision::
1588 1588
1589 1589 hg clone -r 04e544 experimental/ good/
1590 1590
1591 1591 - clone (and track) a particular named branch::
1592 1592
1593 1593 hg clone http://selenic.com/hg#stable
1594 1594
1595 1595 See :hg:`help urls` for details on specifying URLs.
1596 1596
1597 1597 Returns 0 on success.
1598 1598 """
1599 1599 if opts.get('noupdate') and opts.get('updaterev'):
1600 1600 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1601 1601
1602 1602 r = hg.clone(ui, opts, source, dest,
1603 1603 pull=opts.get('pull'),
1604 1604 stream=opts.get('uncompressed'),
1605 1605 rev=opts.get('rev'),
1606 1606 update=opts.get('updaterev') or not opts.get('noupdate'),
1607 1607 branch=opts.get('branch'),
1608 1608 shareopts=opts.get('shareopts'))
1609 1609
1610 1610 return r is None
1611 1611
1612 1612 @command('^commit|ci',
1613 1613 [('A', 'addremove', None,
1614 1614 _('mark new/missing files as added/removed before committing')),
1615 1615 ('', 'close-branch', None,
1616 1616 _('mark a branch head as closed')),
1617 1617 ('', 'amend', None, _('amend the parent of the working directory')),
1618 1618 ('s', 'secret', None, _('use the secret phase for committing')),
1619 1619 ('e', 'edit', None, _('invoke editor on commit messages')),
1620 1620 ('i', 'interactive', None, _('use interactive mode')),
1621 1621 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1622 1622 _('[OPTION]... [FILE]...'),
1623 1623 inferrepo=True)
1624 1624 def commit(ui, repo, *pats, **opts):
1625 1625 """commit the specified files or all outstanding changes
1626 1626
1627 1627 Commit changes to the given files into the repository. Unlike a
1628 1628 centralized SCM, this operation is a local operation. See
1629 1629 :hg:`push` for a way to actively distribute your changes.
1630 1630
1631 1631 If a list of files is omitted, all changes reported by :hg:`status`
1632 1632 will be committed.
1633 1633
1634 1634 If you are committing the result of a merge, do not provide any
1635 1635 filenames or -I/-X filters.
1636 1636
1637 1637 If no commit message is specified, Mercurial starts your
1638 1638 configured editor where you can enter a message. In case your
1639 1639 commit fails, you will find a backup of your message in
1640 1640 ``.hg/last-message.txt``.
1641 1641
1642 1642 The --close-branch flag can be used to mark the current branch
1643 1643 head closed. When all heads of a branch are closed, the branch
1644 1644 will be considered closed and no longer listed.
1645 1645
1646 1646 The --amend flag can be used to amend the parent of the
1647 1647 working directory with a new commit that contains the changes
1648 1648 in the parent in addition to those currently reported by :hg:`status`,
1649 1649 if there are any. The old commit is stored in a backup bundle in
1650 1650 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1651 1651 on how to restore it).
1652 1652
1653 1653 Message, user and date are taken from the amended commit unless
1654 1654 specified. When a message isn't specified on the command line,
1655 1655 the editor will open with the message of the amended commit.
1656 1656
1657 1657 It is not possible to amend public changesets (see :hg:`help phases`)
1658 1658 or changesets that have children.
1659 1659
1660 1660 See :hg:`help dates` for a list of formats valid for -d/--date.
1661 1661
1662 1662 Returns 0 on success, 1 if nothing changed.
1663 1663
1664 1664 .. container:: verbose
1665 1665
1666 1666 Examples:
1667 1667
1668 1668 - commit all files ending in .py::
1669 1669
1670 1670 hg commit --include "set:**.py"
1671 1671
1672 1672 - commit all non-binary files::
1673 1673
1674 1674 hg commit --exclude "set:binary()"
1675 1675
1676 1676 - amend the current commit and set the date to now::
1677 1677
1678 1678 hg commit --amend --date now
1679 1679 """
1680 1680 wlock = lock = None
1681 1681 try:
1682 1682 wlock = repo.wlock()
1683 1683 lock = repo.lock()
1684 1684 return _docommit(ui, repo, *pats, **opts)
1685 1685 finally:
1686 1686 release(lock, wlock)
1687 1687
1688 1688 def _docommit(ui, repo, *pats, **opts):
1689 1689 if opts.get('interactive'):
1690 1690 opts.pop('interactive')
1691 1691 cmdutil.dorecord(ui, repo, commit, None, False,
1692 1692 cmdutil.recordfilter, *pats, **opts)
1693 1693 return
1694 1694
1695 1695 if opts.get('subrepos'):
1696 1696 if opts.get('amend'):
1697 1697 raise error.Abort(_('cannot amend with --subrepos'))
1698 1698 # Let --subrepos on the command line override config setting.
1699 1699 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1700 1700
1701 1701 cmdutil.checkunfinished(repo, commit=True)
1702 1702
1703 1703 branch = repo[None].branch()
1704 1704 bheads = repo.branchheads(branch)
1705 1705
1706 1706 extra = {}
1707 1707 if opts.get('close_branch'):
1708 1708 extra['close'] = 1
1709 1709
1710 1710 if not bheads:
1711 1711 raise error.Abort(_('can only close branch heads'))
1712 1712 elif opts.get('amend'):
1713 1713 if repo[None].parents()[0].p1().branch() != branch and \
1714 1714 repo[None].parents()[0].p2().branch() != branch:
1715 1715 raise error.Abort(_('can only close branch heads'))
1716 1716
1717 1717 if opts.get('amend'):
1718 1718 if ui.configbool('ui', 'commitsubrepos'):
1719 1719 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1720 1720
1721 1721 old = repo['.']
1722 1722 if not old.mutable():
1723 1723 raise error.Abort(_('cannot amend public changesets'))
1724 1724 if len(repo[None].parents()) > 1:
1725 1725 raise error.Abort(_('cannot amend while merging'))
1726 1726 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1727 1727 if not allowunstable and old.children():
1728 1728 raise error.Abort(_('cannot amend changeset with children'))
1729 1729
1730 1730 # Currently histedit gets confused if an amend happens while histedit
1731 1731 # is in progress. Since we have a checkunfinished command, we are
1732 1732 # temporarily honoring it.
1733 1733 #
1734 1734 # Note: eventually this guard will be removed. Please do not expect
1735 1735 # this behavior to remain.
1736 1736 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1737 1737 cmdutil.checkunfinished(repo)
1738 1738
1739 1739 # commitfunc is used only for temporary amend commit by cmdutil.amend
1740 1740 def commitfunc(ui, repo, message, match, opts):
1741 1741 return repo.commit(message,
1742 1742 opts.get('user') or old.user(),
1743 1743 opts.get('date') or old.date(),
1744 1744 match,
1745 1745 extra=extra)
1746 1746
1747 1747 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1748 1748 if node == old.node():
1749 1749 ui.status(_("nothing changed\n"))
1750 1750 return 1
1751 1751 else:
1752 1752 def commitfunc(ui, repo, message, match, opts):
1753 1753 backup = ui.backupconfig('phases', 'new-commit')
1754 1754 baseui = repo.baseui
1755 1755 basebackup = baseui.backupconfig('phases', 'new-commit')
1756 1756 try:
1757 1757 if opts.get('secret'):
1758 1758 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1759 1759 # Propagate to subrepos
1760 1760 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1761 1761
1762 1762 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1763 1763 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1764 1764 return repo.commit(message, opts.get('user'), opts.get('date'),
1765 1765 match,
1766 1766 editor=editor,
1767 1767 extra=extra)
1768 1768 finally:
1769 1769 ui.restoreconfig(backup)
1770 1770 repo.baseui.restoreconfig(basebackup)
1771 1771
1772 1772
1773 1773 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1774 1774
1775 1775 if not node:
1776 1776 stat = cmdutil.postcommitstatus(repo, pats, opts)
1777 1777 if stat[3]:
1778 1778 ui.status(_("nothing changed (%d missing files, see "
1779 1779 "'hg status')\n") % len(stat[3]))
1780 1780 else:
1781 1781 ui.status(_("nothing changed\n"))
1782 1782 return 1
1783 1783
1784 1784 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1785 1785
1786 1786 @command('config|showconfig|debugconfig',
1787 1787 [('u', 'untrusted', None, _('show untrusted configuration options')),
1788 1788 ('e', 'edit', None, _('edit user config')),
1789 1789 ('l', 'local', None, _('edit repository config')),
1790 1790 ('g', 'global', None, _('edit global config'))],
1791 1791 _('[-u] [NAME]...'),
1792 1792 optionalrepo=True)
1793 1793 def config(ui, repo, *values, **opts):
1794 1794 """show combined config settings from all hgrc files
1795 1795
1796 1796 With no arguments, print names and values of all config items.
1797 1797
1798 1798 With one argument of the form section.name, print just the value
1799 1799 of that config item.
1800 1800
1801 1801 With multiple arguments, print names and values of all config
1802 1802 items with matching section names.
1803 1803
1804 1804 With --edit, start an editor on the user-level config file. With
1805 1805 --global, edit the system-wide config file. With --local, edit the
1806 1806 repository-level config file.
1807 1807
1808 1808 With --debug, the source (filename and line number) is printed
1809 1809 for each config item.
1810 1810
1811 1811 See :hg:`help config` for more information about config files.
1812 1812
1813 1813 Returns 0 on success, 1 if NAME does not exist.
1814 1814
1815 1815 """
1816 1816
1817 1817 if opts.get('edit') or opts.get('local') or opts.get('global'):
1818 1818 if opts.get('local') and opts.get('global'):
1819 1819 raise error.Abort(_("can't use --local and --global together"))
1820 1820
1821 1821 if opts.get('local'):
1822 1822 if not repo:
1823 1823 raise error.Abort(_("can't use --local outside a repository"))
1824 1824 paths = [repo.join('hgrc')]
1825 1825 elif opts.get('global'):
1826 1826 paths = scmutil.systemrcpath()
1827 1827 else:
1828 1828 paths = scmutil.userrcpath()
1829 1829
1830 1830 for f in paths:
1831 1831 if os.path.exists(f):
1832 1832 break
1833 1833 else:
1834 1834 if opts.get('global'):
1835 1835 samplehgrc = uimod.samplehgrcs['global']
1836 1836 elif opts.get('local'):
1837 1837 samplehgrc = uimod.samplehgrcs['local']
1838 1838 else:
1839 1839 samplehgrc = uimod.samplehgrcs['user']
1840 1840
1841 1841 f = paths[0]
1842 1842 fp = open(f, "w")
1843 1843 fp.write(samplehgrc)
1844 1844 fp.close()
1845 1845
1846 1846 editor = ui.geteditor()
1847 1847 ui.system("%s \"%s\"" % (editor, f),
1848 1848 onerr=error.Abort, errprefix=_("edit failed"))
1849 1849 return
1850 1850
1851 1851 for f in scmutil.rcpath():
1852 1852 ui.debug('read config from: %s\n' % f)
1853 1853 untrusted = bool(opts.get('untrusted'))
1854 1854 if values:
1855 1855 sections = [v for v in values if '.' not in v]
1856 1856 items = [v for v in values if '.' in v]
1857 1857 if len(items) > 1 or items and sections:
1858 1858 raise error.Abort(_('only one config item permitted'))
1859 1859 matched = False
1860 1860 for section, name, value in ui.walkconfig(untrusted=untrusted):
1861 1861 value = str(value).replace('\n', '\\n')
1862 1862 sectname = section + '.' + name
1863 1863 if values:
1864 1864 for v in values:
1865 1865 if v == section:
1866 1866 ui.debug('%s: ' %
1867 1867 ui.configsource(section, name, untrusted))
1868 1868 ui.write('%s=%s\n' % (sectname, value))
1869 1869 matched = True
1870 1870 elif v == sectname:
1871 1871 ui.debug('%s: ' %
1872 1872 ui.configsource(section, name, untrusted))
1873 1873 ui.write(value, '\n')
1874 1874 matched = True
1875 1875 else:
1876 1876 ui.debug('%s: ' %
1877 1877 ui.configsource(section, name, untrusted))
1878 1878 ui.write('%s=%s\n' % (sectname, value))
1879 1879 matched = True
1880 1880 if matched:
1881 1881 return 0
1882 1882 return 1
1883 1883
1884 1884 @command('copy|cp',
1885 1885 [('A', 'after', None, _('record a copy that has already occurred')),
1886 1886 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1887 1887 ] + walkopts + dryrunopts,
1888 1888 _('[OPTION]... [SOURCE]... DEST'))
1889 1889 def copy(ui, repo, *pats, **opts):
1890 1890 """mark files as copied for the next commit
1891 1891
1892 1892 Mark dest as having copies of source files. If dest is a
1893 1893 directory, copies are put in that directory. If dest is a file,
1894 1894 the source must be a single file.
1895 1895
1896 1896 By default, this command copies the contents of files as they
1897 1897 exist in the working directory. If invoked with -A/--after, the
1898 1898 operation is recorded, but no copying is performed.
1899 1899
1900 1900 This command takes effect with the next commit. To undo a copy
1901 1901 before that, see :hg:`revert`.
1902 1902
1903 1903 Returns 0 on success, 1 if errors are encountered.
1904 1904 """
1905 1905 with repo.wlock(False):
1906 1906 return cmdutil.copy(ui, repo, pats, opts)
1907 1907
1908 1908 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1909 1909 def debugancestor(ui, repo, *args):
1910 1910 """find the ancestor revision of two revisions in a given index"""
1911 1911 if len(args) == 3:
1912 1912 index, rev1, rev2 = args
1913 1913 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1914 1914 lookup = r.lookup
1915 1915 elif len(args) == 2:
1916 1916 if not repo:
1917 1917 raise error.Abort(_("there is no Mercurial repository here "
1918 1918 "(.hg not found)"))
1919 1919 rev1, rev2 = args
1920 1920 r = repo.changelog
1921 1921 lookup = repo.lookup
1922 1922 else:
1923 1923 raise error.Abort(_('either two or three arguments required'))
1924 1924 a = r.ancestor(lookup(rev1), lookup(rev2))
1925 1925 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1926 1926
1927 1927 @command('debugbuilddag',
1928 1928 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1929 1929 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1930 1930 ('n', 'new-file', None, _('add new file at each rev'))],
1931 1931 _('[OPTION]... [TEXT]'))
1932 1932 def debugbuilddag(ui, repo, text=None,
1933 1933 mergeable_file=False,
1934 1934 overwritten_file=False,
1935 1935 new_file=False):
1936 1936 """builds a repo with a given DAG from scratch in the current empty repo
1937 1937
1938 1938 The description of the DAG is read from stdin if not given on the
1939 1939 command line.
1940 1940
1941 1941 Elements:
1942 1942
1943 1943 - "+n" is a linear run of n nodes based on the current default parent
1944 1944 - "." is a single node based on the current default parent
1945 1945 - "$" resets the default parent to null (implied at the start);
1946 1946 otherwise the default parent is always the last node created
1947 1947 - "<p" sets the default parent to the backref p
1948 1948 - "*p" is a fork at parent p, which is a backref
1949 1949 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1950 1950 - "/p2" is a merge of the preceding node and p2
1951 1951 - ":tag" defines a local tag for the preceding node
1952 1952 - "@branch" sets the named branch for subsequent nodes
1953 1953 - "#...\\n" is a comment up to the end of the line
1954 1954
1955 1955 Whitespace between the above elements is ignored.
1956 1956
1957 1957 A backref is either
1958 1958
1959 1959 - a number n, which references the node curr-n, where curr is the current
1960 1960 node, or
1961 1961 - the name of a local tag you placed earlier using ":tag", or
1962 1962 - empty to denote the default parent.
1963 1963
1964 1964 All string valued-elements are either strictly alphanumeric, or must
1965 1965 be enclosed in double quotes ("..."), with "\\" as escape character.
1966 1966 """
1967 1967
1968 1968 if text is None:
1969 1969 ui.status(_("reading DAG from stdin\n"))
1970 1970 text = ui.fin.read()
1971 1971
1972 1972 cl = repo.changelog
1973 1973 if len(cl) > 0:
1974 1974 raise error.Abort(_('repository is not empty'))
1975 1975
1976 1976 # determine number of revs in DAG
1977 1977 total = 0
1978 1978 for type, data in dagparser.parsedag(text):
1979 1979 if type == 'n':
1980 1980 total += 1
1981 1981
1982 1982 if mergeable_file:
1983 1983 linesperrev = 2
1984 1984 # make a file with k lines per rev
1985 1985 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1986 1986 initialmergedlines.append("")
1987 1987
1988 1988 tags = []
1989 1989
1990 1990 lock = tr = None
1991 1991 try:
1992 1992 lock = repo.lock()
1993 1993 tr = repo.transaction("builddag")
1994 1994
1995 1995 at = -1
1996 1996 atbranch = 'default'
1997 1997 nodeids = []
1998 1998 id = 0
1999 1999 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2000 2000 for type, data in dagparser.parsedag(text):
2001 2001 if type == 'n':
2002 2002 ui.note(('node %s\n' % str(data)))
2003 2003 id, ps = data
2004 2004
2005 2005 files = []
2006 2006 fctxs = {}
2007 2007
2008 2008 p2 = None
2009 2009 if mergeable_file:
2010 2010 fn = "mf"
2011 2011 p1 = repo[ps[0]]
2012 2012 if len(ps) > 1:
2013 2013 p2 = repo[ps[1]]
2014 2014 pa = p1.ancestor(p2)
2015 2015 base, local, other = [x[fn].data() for x in (pa, p1,
2016 2016 p2)]
2017 2017 m3 = simplemerge.Merge3Text(base, local, other)
2018 2018 ml = [l.strip() for l in m3.merge_lines()]
2019 2019 ml.append("")
2020 2020 elif at > 0:
2021 2021 ml = p1[fn].data().split("\n")
2022 2022 else:
2023 2023 ml = initialmergedlines
2024 2024 ml[id * linesperrev] += " r%i" % id
2025 2025 mergedtext = "\n".join(ml)
2026 2026 files.append(fn)
2027 2027 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2028 2028
2029 2029 if overwritten_file:
2030 2030 fn = "of"
2031 2031 files.append(fn)
2032 2032 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2033 2033
2034 2034 if new_file:
2035 2035 fn = "nf%i" % id
2036 2036 files.append(fn)
2037 2037 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2038 2038 if len(ps) > 1:
2039 2039 if not p2:
2040 2040 p2 = repo[ps[1]]
2041 2041 for fn in p2:
2042 2042 if fn.startswith("nf"):
2043 2043 files.append(fn)
2044 2044 fctxs[fn] = p2[fn]
2045 2045
2046 2046 def fctxfn(repo, cx, path):
2047 2047 return fctxs.get(path)
2048 2048
2049 2049 if len(ps) == 0 or ps[0] < 0:
2050 2050 pars = [None, None]
2051 2051 elif len(ps) == 1:
2052 2052 pars = [nodeids[ps[0]], None]
2053 2053 else:
2054 2054 pars = [nodeids[p] for p in ps]
2055 2055 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2056 2056 date=(id, 0),
2057 2057 user="debugbuilddag",
2058 2058 extra={'branch': atbranch})
2059 2059 nodeid = repo.commitctx(cx)
2060 2060 nodeids.append(nodeid)
2061 2061 at = id
2062 2062 elif type == 'l':
2063 2063 id, name = data
2064 2064 ui.note(('tag %s\n' % name))
2065 2065 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2066 2066 elif type == 'a':
2067 2067 ui.note(('branch %s\n' % data))
2068 2068 atbranch = data
2069 2069 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2070 2070 tr.close()
2071 2071
2072 2072 if tags:
2073 2073 repo.vfs.write("localtags", "".join(tags))
2074 2074 finally:
2075 2075 ui.progress(_('building'), None)
2076 2076 release(tr, lock)
2077 2077
2078 2078 @command('debugbundle',
2079 2079 [('a', 'all', None, _('show all details')),
2080 2080 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2081 2081 _('FILE'),
2082 2082 norepo=True)
2083 2083 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2084 2084 """lists the contents of a bundle"""
2085 2085 with hg.openpath(ui, bundlepath) as f:
2086 2086 if spec:
2087 2087 spec = exchange.getbundlespec(ui, f)
2088 2088 ui.write('%s\n' % spec)
2089 2089 return
2090 2090
2091 2091 gen = exchange.readbundle(ui, f, bundlepath)
2092 2092 if isinstance(gen, bundle2.unbundle20):
2093 2093 return _debugbundle2(ui, gen, all=all, **opts)
2094 2094 _debugchangegroup(ui, gen, all=all, **opts)
2095 2095
2096 2096 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2097 2097 indent_string = ' ' * indent
2098 2098 if all:
2099 2099 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2100 2100 % indent_string)
2101 2101
2102 2102 def showchunks(named):
2103 2103 ui.write("\n%s%s\n" % (indent_string, named))
2104 2104 chain = None
2105 2105 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2106 2106 node = chunkdata['node']
2107 2107 p1 = chunkdata['p1']
2108 2108 p2 = chunkdata['p2']
2109 2109 cs = chunkdata['cs']
2110 2110 deltabase = chunkdata['deltabase']
2111 2111 delta = chunkdata['delta']
2112 2112 ui.write("%s%s %s %s %s %s %s\n" %
2113 2113 (indent_string, hex(node), hex(p1), hex(p2),
2114 2114 hex(cs), hex(deltabase), len(delta)))
2115 2115 chain = node
2116 2116
2117 2117 chunkdata = gen.changelogheader()
2118 2118 showchunks("changelog")
2119 2119 chunkdata = gen.manifestheader()
2120 2120 showchunks("manifest")
2121 2121 for chunkdata in iter(gen.filelogheader, {}):
2122 2122 fname = chunkdata['filename']
2123 2123 showchunks(fname)
2124 2124 else:
2125 2125 if isinstance(gen, bundle2.unbundle20):
2126 2126 raise error.Abort(_('use debugbundle2 for this file'))
2127 2127 chunkdata = gen.changelogheader()
2128 2128 chain = None
2129 2129 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2130 2130 node = chunkdata['node']
2131 2131 ui.write("%s%s\n" % (indent_string, hex(node)))
2132 2132 chain = node
2133 2133
2134 2134 def _debugbundle2(ui, gen, all=None, **opts):
2135 2135 """lists the contents of a bundle2"""
2136 2136 if not isinstance(gen, bundle2.unbundle20):
2137 2137 raise error.Abort(_('not a bundle2 file'))
2138 2138 ui.write(('Stream params: %s\n' % repr(gen.params)))
2139 2139 for part in gen.iterparts():
2140 2140 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2141 2141 if part.type == 'changegroup':
2142 2142 version = part.params.get('version', '01')
2143 2143 cg = changegroup.getunbundler(version, part, 'UN')
2144 2144 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2145 2145
2146 2146 @command('debugcreatestreamclonebundle', [], 'FILE')
2147 2147 def debugcreatestreamclonebundle(ui, repo, fname):
2148 2148 """create a stream clone bundle file
2149 2149
2150 2150 Stream bundles are special bundles that are essentially archives of
2151 2151 revlog files. They are commonly used for cloning very quickly.
2152 2152 """
2153 2153 requirements, gen = streamclone.generatebundlev1(repo)
2154 2154 changegroup.writechunks(ui, gen, fname)
2155 2155
2156 2156 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2157 2157
2158 2158 @command('debugapplystreamclonebundle', [], 'FILE')
2159 2159 def debugapplystreamclonebundle(ui, repo, fname):
2160 2160 """apply a stream clone bundle file"""
2161 2161 f = hg.openpath(ui, fname)
2162 2162 gen = exchange.readbundle(ui, f, fname)
2163 2163 gen.apply(repo)
2164 2164
2165 2165 @command('debugcheckstate', [], '')
2166 2166 def debugcheckstate(ui, repo):
2167 2167 """validate the correctness of the current dirstate"""
2168 2168 parent1, parent2 = repo.dirstate.parents()
2169 2169 m1 = repo[parent1].manifest()
2170 2170 m2 = repo[parent2].manifest()
2171 2171 errors = 0
2172 2172 for f in repo.dirstate:
2173 2173 state = repo.dirstate[f]
2174 2174 if state in "nr" and f not in m1:
2175 2175 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2176 2176 errors += 1
2177 2177 if state in "a" and f in m1:
2178 2178 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2179 2179 errors += 1
2180 2180 if state in "m" and f not in m1 and f not in m2:
2181 2181 ui.warn(_("%s in state %s, but not in either manifest\n") %
2182 2182 (f, state))
2183 2183 errors += 1
2184 2184 for f in m1:
2185 2185 state = repo.dirstate[f]
2186 2186 if state not in "nrm":
2187 2187 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2188 2188 errors += 1
2189 2189 if errors:
2190 2190 error = _(".hg/dirstate inconsistent with current parent's manifest")
2191 2191 raise error.Abort(error)
2192 2192
2193 2193 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2194 2194 def debugcommands(ui, cmd='', *args):
2195 2195 """list all available commands and options"""
2196 2196 for cmd, vals in sorted(table.iteritems()):
2197 2197 cmd = cmd.split('|')[0].strip('^')
2198 2198 opts = ', '.join([i[1] for i in vals[1]])
2199 2199 ui.write('%s: %s\n' % (cmd, opts))
2200 2200
2201 2201 @command('debugcomplete',
2202 2202 [('o', 'options', None, _('show the command options'))],
2203 2203 _('[-o] CMD'),
2204 2204 norepo=True)
2205 2205 def debugcomplete(ui, cmd='', **opts):
2206 2206 """returns the completion list associated with the given command"""
2207 2207
2208 2208 if opts.get('options'):
2209 2209 options = []
2210 2210 otables = [globalopts]
2211 2211 if cmd:
2212 2212 aliases, entry = cmdutil.findcmd(cmd, table, False)
2213 2213 otables.append(entry[1])
2214 2214 for t in otables:
2215 2215 for o in t:
2216 2216 if "(DEPRECATED)" in o[3]:
2217 2217 continue
2218 2218 if o[0]:
2219 2219 options.append('-%s' % o[0])
2220 2220 options.append('--%s' % o[1])
2221 2221 ui.write("%s\n" % "\n".join(options))
2222 2222 return
2223 2223
2224 2224 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2225 2225 if ui.verbose:
2226 2226 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2227 2227 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2228 2228
2229 2229 @command('debugdag',
2230 2230 [('t', 'tags', None, _('use tags as labels')),
2231 2231 ('b', 'branches', None, _('annotate with branch names')),
2232 2232 ('', 'dots', None, _('use dots for runs')),
2233 2233 ('s', 'spaces', None, _('separate elements by spaces'))],
2234 2234 _('[OPTION]... [FILE [REV]...]'),
2235 2235 optionalrepo=True)
2236 2236 def debugdag(ui, repo, file_=None, *revs, **opts):
2237 2237 """format the changelog or an index DAG as a concise textual description
2238 2238
2239 2239 If you pass a revlog index, the revlog's DAG is emitted. If you list
2240 2240 revision numbers, they get labeled in the output as rN.
2241 2241
2242 2242 Otherwise, the changelog DAG of the current repo is emitted.
2243 2243 """
2244 2244 spaces = opts.get('spaces')
2245 2245 dots = opts.get('dots')
2246 2246 if file_:
2247 2247 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2248 2248 revs = set((int(r) for r in revs))
2249 2249 def events():
2250 2250 for r in rlog:
2251 2251 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2252 2252 if p != -1))
2253 2253 if r in revs:
2254 2254 yield 'l', (r, "r%i" % r)
2255 2255 elif repo:
2256 2256 cl = repo.changelog
2257 2257 tags = opts.get('tags')
2258 2258 branches = opts.get('branches')
2259 2259 if tags:
2260 2260 labels = {}
2261 2261 for l, n in repo.tags().items():
2262 2262 labels.setdefault(cl.rev(n), []).append(l)
2263 2263 def events():
2264 2264 b = "default"
2265 2265 for r in cl:
2266 2266 if branches:
2267 2267 newb = cl.read(cl.node(r))[5]['branch']
2268 2268 if newb != b:
2269 2269 yield 'a', newb
2270 2270 b = newb
2271 2271 yield 'n', (r, list(p for p in cl.parentrevs(r)
2272 2272 if p != -1))
2273 2273 if tags:
2274 2274 ls = labels.get(r)
2275 2275 if ls:
2276 2276 for l in ls:
2277 2277 yield 'l', (r, l)
2278 2278 else:
2279 2279 raise error.Abort(_('need repo for changelog dag'))
2280 2280
2281 2281 for line in dagparser.dagtextlines(events(),
2282 2282 addspaces=spaces,
2283 2283 wraplabels=True,
2284 2284 wrapannotations=True,
2285 2285 wrapnonlinear=dots,
2286 2286 usedots=dots,
2287 2287 maxlinewidth=70):
2288 2288 ui.write(line)
2289 2289 ui.write("\n")
2290 2290
2291 2291 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2292 2292 def debugdata(ui, repo, file_, rev=None, **opts):
2293 2293 """dump the contents of a data file revision"""
2294 2294 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2295 2295 if rev is not None:
2296 2296 raise error.CommandError('debugdata', _('invalid arguments'))
2297 2297 file_, rev = None, file_
2298 2298 elif rev is None:
2299 2299 raise error.CommandError('debugdata', _('invalid arguments'))
2300 2300 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2301 2301 try:
2302 2302 ui.write(r.revision(r.lookup(rev)))
2303 2303 except KeyError:
2304 2304 raise error.Abort(_('invalid revision identifier %s') % rev)
2305 2305
2306 2306 @command('debugdate',
2307 2307 [('e', 'extended', None, _('try extended date formats'))],
2308 2308 _('[-e] DATE [RANGE]'),
2309 2309 norepo=True, optionalrepo=True)
2310 2310 def debugdate(ui, date, range=None, **opts):
2311 2311 """parse and display a date"""
2312 2312 if opts["extended"]:
2313 2313 d = util.parsedate(date, util.extendeddateformats)
2314 2314 else:
2315 2315 d = util.parsedate(date)
2316 2316 ui.write(("internal: %s %s\n") % d)
2317 2317 ui.write(("standard: %s\n") % util.datestr(d))
2318 2318 if range:
2319 2319 m = util.matchdate(range)
2320 2320 ui.write(("match: %s\n") % m(d[0]))
2321 2321
2322 2322 @command('debugdiscovery',
2323 2323 [('', 'old', None, _('use old-style discovery')),
2324 2324 ('', 'nonheads', None,
2325 2325 _('use old-style discovery with non-heads included')),
2326 2326 ] + remoteopts,
2327 2327 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2328 2328 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2329 2329 """runs the changeset discovery protocol in isolation"""
2330 2330 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2331 2331 opts.get('branch'))
2332 2332 remote = hg.peer(repo, opts, remoteurl)
2333 2333 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2334 2334
2335 2335 # make sure tests are repeatable
2336 2336 random.seed(12323)
2337 2337
2338 2338 def doit(localheads, remoteheads, remote=remote):
2339 2339 if opts.get('old'):
2340 2340 if localheads:
2341 2341 raise error.Abort('cannot use localheads with old style '
2342 2342 'discovery')
2343 2343 if not util.safehasattr(remote, 'branches'):
2344 2344 # enable in-client legacy support
2345 2345 remote = localrepo.locallegacypeer(remote.local())
2346 2346 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2347 2347 force=True)
2348 2348 common = set(common)
2349 2349 if not opts.get('nonheads'):
2350 2350 ui.write(("unpruned common: %s\n") %
2351 2351 " ".join(sorted(short(n) for n in common)))
2352 2352 dag = dagutil.revlogdag(repo.changelog)
2353 2353 all = dag.ancestorset(dag.internalizeall(common))
2354 2354 common = dag.externalizeall(dag.headsetofconnecteds(all))
2355 2355 else:
2356 2356 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2357 2357 common = set(common)
2358 2358 rheads = set(hds)
2359 2359 lheads = set(repo.heads())
2360 2360 ui.write(("common heads: %s\n") %
2361 2361 " ".join(sorted(short(n) for n in common)))
2362 2362 if lheads <= common:
2363 2363 ui.write(("local is subset\n"))
2364 2364 elif rheads <= common:
2365 2365 ui.write(("remote is subset\n"))
2366 2366
2367 2367 serverlogs = opts.get('serverlog')
2368 2368 if serverlogs:
2369 2369 for filename in serverlogs:
2370 2370 with open(filename, 'r') as logfile:
2371 2371 line = logfile.readline()
2372 2372 while line:
2373 2373 parts = line.strip().split(';')
2374 2374 op = parts[1]
2375 2375 if op == 'cg':
2376 2376 pass
2377 2377 elif op == 'cgss':
2378 2378 doit(parts[2].split(' '), parts[3].split(' '))
2379 2379 elif op == 'unb':
2380 2380 doit(parts[3].split(' '), parts[2].split(' '))
2381 2381 line = logfile.readline()
2382 2382 else:
2383 2383 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2384 2384 opts.get('remote_head'))
2385 2385 localrevs = opts.get('local_head')
2386 2386 doit(localrevs, remoterevs)
2387 2387
2388 2388 @command('debugextensions', formatteropts, [], norepo=True)
2389 2389 def debugextensions(ui, **opts):
2390 2390 '''show information about active extensions'''
2391 2391 exts = extensions.extensions(ui)
2392 2392 hgver = util.version()
2393 2393 fm = ui.formatter('debugextensions', opts)
2394 2394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2395 2395 extsource = extmod.__file__
2396 2396 exttestedwith = getattr(extmod, 'testedwith', '').split()
2397 2397 extbuglink = getattr(extmod, 'buglink', None)
2398 2398
2399 2399 fm.startitem()
2400 2400
2401 2401 if ui.quiet or ui.verbose:
2402 2402 fm.write('name', '%s\n', extname)
2403 2403 else:
2404 2404 fm.write('name', '%s', extname)
2405 2405 if not exttestedwith:
2406 2406 fm.plain(_(' (untested!)\n'))
2407 2407 elif exttestedwith == ['internal'] or hgver in exttestedwith:
2408 2408 fm.plain('\n')
2409 2409 else:
2410 2410 lasttestedversion = exttestedwith[-1]
2411 2411 fm.plain(' (%s!)\n' % lasttestedversion)
2412 2412
2413 2413 fm.condwrite(ui.verbose and extsource, 'source',
2414 2414 _(' location: %s\n'), extsource or "")
2415 2415
2416 2416 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2417 2417 _(' tested with: %s\n'),
2418 2418 fm.formatlist(exttestedwith, name='ver'))
2419 2419
2420 2420 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2421 2421 _(' bug reporting: %s\n'), extbuglink or "")
2422 2422
2423 2423 fm.end()
2424 2424
2425 2425 @command('debugfileset',
2426 2426 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2427 2427 _('[-r REV] FILESPEC'))
2428 2428 def debugfileset(ui, repo, expr, **opts):
2429 2429 '''parse and apply a fileset specification'''
2430 2430 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2431 2431 if ui.verbose:
2432 2432 tree = fileset.parse(expr)
2433 2433 ui.note(fileset.prettyformat(tree), "\n")
2434 2434
2435 2435 for f in ctx.getfileset(expr):
2436 2436 ui.write("%s\n" % f)
2437 2437
2438 2438 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2439 2439 def debugfsinfo(ui, path="."):
2440 2440 """show information detected about current filesystem"""
2441 2441 util.writefile('.debugfsinfo', '')
2442 2442 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2443 2443 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2444 2444 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2445 2445 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2446 2446 and 'yes' or 'no'))
2447 2447 os.unlink('.debugfsinfo')
2448 2448
2449 2449 @command('debuggetbundle',
2450 2450 [('H', 'head', [], _('id of head node'), _('ID')),
2451 2451 ('C', 'common', [], _('id of common node'), _('ID')),
2452 2452 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2453 2453 _('REPO FILE [-H|-C ID]...'),
2454 2454 norepo=True)
2455 2455 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2456 2456 """retrieves a bundle from a repo
2457 2457
2458 2458 Every ID must be a full-length hex node id string. Saves the bundle to the
2459 2459 given file.
2460 2460 """
2461 2461 repo = hg.peer(ui, opts, repopath)
2462 2462 if not repo.capable('getbundle'):
2463 2463 raise error.Abort("getbundle() not supported by target repository")
2464 2464 args = {}
2465 2465 if common:
2466 2466 args['common'] = [bin(s) for s in common]
2467 2467 if head:
2468 2468 args['heads'] = [bin(s) for s in head]
2469 2469 # TODO: get desired bundlecaps from command line.
2470 2470 args['bundlecaps'] = None
2471 2471 bundle = repo.getbundle('debug', **args)
2472 2472
2473 2473 bundletype = opts.get('type', 'bzip2').lower()
2474 2474 btypes = {'none': 'HG10UN',
2475 2475 'bzip2': 'HG10BZ',
2476 2476 'gzip': 'HG10GZ',
2477 2477 'bundle2': 'HG20'}
2478 2478 bundletype = btypes.get(bundletype)
2479 2479 if bundletype not in bundle2.bundletypes:
2480 2480 raise error.Abort(_('unknown bundle type specified with --type'))
2481 2481 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2482 2482
2483 2483 @command('debugignore', [], '[FILE]')
2484 2484 def debugignore(ui, repo, *files, **opts):
2485 2485 """display the combined ignore pattern and information about ignored files
2486 2486
2487 2487 With no argument display the combined ignore pattern.
2488 2488
2489 2489 Given space separated file names, shows if the given file is ignored and
2490 2490 if so, show the ignore rule (file and line number) that matched it.
2491 2491 """
2492 2492 ignore = repo.dirstate._ignore
2493 2493 if not files:
2494 2494 # Show all the patterns
2495 2495 includepat = getattr(ignore, 'includepat', None)
2496 2496 if includepat is not None:
2497 2497 ui.write("%s\n" % includepat)
2498 2498 else:
2499 2499 raise error.Abort(_("no ignore patterns found"))
2500 2500 else:
2501 2501 for f in files:
2502 2502 nf = util.normpath(f)
2503 2503 ignored = None
2504 2504 ignoredata = None
2505 2505 if nf != '.':
2506 2506 if ignore(nf):
2507 2507 ignored = nf
2508 2508 ignoredata = repo.dirstate._ignorefileandline(nf)
2509 2509 else:
2510 2510 for p in util.finddirs(nf):
2511 2511 if ignore(p):
2512 2512 ignored = p
2513 2513 ignoredata = repo.dirstate._ignorefileandline(p)
2514 2514 break
2515 2515 if ignored:
2516 2516 if ignored == nf:
2517 2517 ui.write(_("%s is ignored\n") % f)
2518 2518 else:
2519 2519 ui.write(_("%s is ignored because of "
2520 2520 "containing folder %s\n")
2521 2521 % (f, ignored))
2522 2522 ignorefile, lineno, line = ignoredata
2523 2523 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2524 2524 % (ignorefile, lineno, line))
2525 2525 else:
2526 2526 ui.write(_("%s is not ignored\n") % f)
2527 2527
2528 2528 @command('debugindex', debugrevlogopts +
2529 2529 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2530 2530 _('[-f FORMAT] -c|-m|FILE'),
2531 2531 optionalrepo=True)
2532 2532 def debugindex(ui, repo, file_=None, **opts):
2533 2533 """dump the contents of an index file"""
2534 2534 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2535 2535 format = opts.get('format', 0)
2536 2536 if format not in (0, 1):
2537 2537 raise error.Abort(_("unknown format %d") % format)
2538 2538
2539 2539 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2540 2540 if generaldelta:
2541 2541 basehdr = ' delta'
2542 2542 else:
2543 2543 basehdr = ' base'
2544 2544
2545 2545 if ui.debugflag:
2546 2546 shortfn = hex
2547 2547 else:
2548 2548 shortfn = short
2549 2549
2550 2550 # There might not be anything in r, so have a sane default
2551 2551 idlen = 12
2552 2552 for i in r:
2553 2553 idlen = len(shortfn(r.node(i)))
2554 2554 break
2555 2555
2556 2556 if format == 0:
2557 2557 ui.write((" rev offset length " + basehdr + " linkrev"
2558 2558 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2559 2559 elif format == 1:
2560 2560 ui.write((" rev flag offset length"
2561 2561 " size " + basehdr + " link p1 p2"
2562 2562 " %s\n") % "nodeid".rjust(idlen))
2563 2563
2564 2564 for i in r:
2565 2565 node = r.node(i)
2566 2566 if generaldelta:
2567 2567 base = r.deltaparent(i)
2568 2568 else:
2569 2569 base = r.chainbase(i)
2570 2570 if format == 0:
2571 2571 try:
2572 2572 pp = r.parents(node)
2573 2573 except Exception:
2574 2574 pp = [nullid, nullid]
2575 2575 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2576 2576 i, r.start(i), r.length(i), base, r.linkrev(i),
2577 2577 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2578 2578 elif format == 1:
2579 2579 pr = r.parentrevs(i)
2580 2580 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2581 2581 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2582 2582 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2583 2583
2584 2584 @command('debugindexdot', debugrevlogopts,
2585 2585 _('-c|-m|FILE'), optionalrepo=True)
2586 2586 def debugindexdot(ui, repo, file_=None, **opts):
2587 2587 """dump an index DAG as a graphviz dot file"""
2588 2588 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2589 2589 ui.write(("digraph G {\n"))
2590 2590 for i in r:
2591 2591 node = r.node(i)
2592 2592 pp = r.parents(node)
2593 2593 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2594 2594 if pp[1] != nullid:
2595 2595 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2596 2596 ui.write("}\n")
2597 2597
2598 2598 @command('debugdeltachain',
2599 2599 debugrevlogopts + formatteropts,
2600 2600 _('-c|-m|FILE'),
2601 2601 optionalrepo=True)
2602 2602 def debugdeltachain(ui, repo, file_=None, **opts):
2603 2603 """dump information about delta chains in a revlog
2604 2604
2605 2605 Output can be templatized. Available template keywords are:
2606 2606
2607 2607 :``rev``: revision number
2608 2608 :``chainid``: delta chain identifier (numbered by unique base)
2609 2609 :``chainlen``: delta chain length to this revision
2610 2610 :``prevrev``: previous revision in delta chain
2611 2611 :``deltatype``: role of delta / how it was computed
2612 2612 :``compsize``: compressed size of revision
2613 2613 :``uncompsize``: uncompressed size of revision
2614 2614 :``chainsize``: total size of compressed revisions in chain
2615 2615 :``chainratio``: total chain size divided by uncompressed revision size
2616 2616 (new delta chains typically start at ratio 2.00)
2617 2617 :``lindist``: linear distance from base revision in delta chain to end
2618 2618 of this revision
2619 2619 :``extradist``: total size of revisions not part of this delta chain from
2620 2620 base of delta chain to end of this revision; a measurement
2621 2621 of how much extra data we need to read/seek across to read
2622 2622 the delta chain for this revision
2623 2623 :``extraratio``: extradist divided by chainsize; another representation of
2624 2624 how much unrelated data is needed to load this delta chain
2625 2625 """
2626 2626 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2627 2627 index = r.index
2628 2628 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2629 2629
2630 2630 def revinfo(rev):
2631 2631 e = index[rev]
2632 2632 compsize = e[1]
2633 2633 uncompsize = e[2]
2634 2634 chainsize = 0
2635 2635
2636 2636 if generaldelta:
2637 2637 if e[3] == e[5]:
2638 2638 deltatype = 'p1'
2639 2639 elif e[3] == e[6]:
2640 2640 deltatype = 'p2'
2641 2641 elif e[3] == rev - 1:
2642 2642 deltatype = 'prev'
2643 2643 elif e[3] == rev:
2644 2644 deltatype = 'base'
2645 2645 else:
2646 2646 deltatype = 'other'
2647 2647 else:
2648 2648 if e[3] == rev:
2649 2649 deltatype = 'base'
2650 2650 else:
2651 2651 deltatype = 'prev'
2652 2652
2653 2653 chain = r._deltachain(rev)[0]
2654 2654 for iterrev in chain:
2655 2655 e = index[iterrev]
2656 2656 chainsize += e[1]
2657 2657
2658 2658 return compsize, uncompsize, deltatype, chain, chainsize
2659 2659
2660 2660 fm = ui.formatter('debugdeltachain', opts)
2661 2661
2662 2662 fm.plain(' rev chain# chainlen prev delta '
2663 2663 'size rawsize chainsize ratio lindist extradist '
2664 2664 'extraratio\n')
2665 2665
2666 2666 chainbases = {}
2667 2667 for rev in r:
2668 2668 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2669 2669 chainbase = chain[0]
2670 2670 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2671 2671 basestart = r.start(chainbase)
2672 2672 revstart = r.start(rev)
2673 2673 lineardist = revstart + comp - basestart
2674 2674 extradist = lineardist - chainsize
2675 2675 try:
2676 2676 prevrev = chain[-2]
2677 2677 except IndexError:
2678 2678 prevrev = -1
2679 2679
2680 2680 chainratio = float(chainsize) / float(uncomp)
2681 2681 extraratio = float(extradist) / float(chainsize)
2682 2682
2683 2683 fm.startitem()
2684 2684 fm.write('rev chainid chainlen prevrev deltatype compsize '
2685 2685 'uncompsize chainsize chainratio lindist extradist '
2686 2686 'extraratio',
2687 2687 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2688 2688 rev, chainid, len(chain), prevrev, deltatype, comp,
2689 2689 uncomp, chainsize, chainratio, lineardist, extradist,
2690 2690 extraratio,
2691 2691 rev=rev, chainid=chainid, chainlen=len(chain),
2692 2692 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2693 2693 uncompsize=uncomp, chainsize=chainsize,
2694 2694 chainratio=chainratio, lindist=lineardist,
2695 2695 extradist=extradist, extraratio=extraratio)
2696 2696
2697 2697 fm.end()
2698 2698
2699 2699 @command('debuginstall', [] + formatteropts, '', norepo=True)
2700 2700 def debuginstall(ui, **opts):
2701 2701 '''test Mercurial installation
2702 2702
2703 2703 Returns 0 on success.
2704 2704 '''
2705 2705
2706 2706 def writetemp(contents):
2707 2707 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2708 2708 f = os.fdopen(fd, "wb")
2709 2709 f.write(contents)
2710 2710 f.close()
2711 2711 return name
2712 2712
2713 2713 problems = 0
2714 2714
2715 2715 fm = ui.formatter('debuginstall', opts)
2716 2716 fm.startitem()
2717 2717
2718 2718 # encoding
2719 2719 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2720 2720 err = None
2721 2721 try:
2722 2722 encoding.fromlocal("test")
2723 2723 except error.Abort as inst:
2724 2724 err = inst
2725 2725 problems += 1
2726 2726 fm.condwrite(err, 'encodingerror', _(" %s\n"
2727 2727 " (check that your locale is properly set)\n"), err)
2728 2728
2729 2729 # Python
2730 2730 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2731 2731 sys.executable)
2732 2732 fm.write('pythonver', _("checking Python version (%s)\n"),
2733 2733 ("%s.%s.%s" % sys.version_info[:3]))
2734 2734 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2735 2735 os.path.dirname(os.__file__))
2736 2736
2737 2737 # hg version
2738 2738 hgver = util.version()
2739 2739 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2740 2740 hgver.split('+')[0])
2741 2741 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2742 2742 '+'.join(hgver.split('+')[1:]))
2743 2743
2744 2744 # compiled modules
2745 2745 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2746 2746 policy.policy)
2747 2747 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2748 2748 os.path.dirname(__file__))
2749 2749
2750 2750 err = None
2751 2751 try:
2752 2752 from . import (
2753 2753 base85,
2754 2754 bdiff,
2755 2755 mpatch,
2756 2756 osutil,
2757 2757 )
2758 2758 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2759 2759 except Exception as inst:
2760 2760 err = inst
2761 2761 problems += 1
2762 2762 fm.condwrite(err, 'extensionserror', " %s\n", err)
2763 2763
2764 2764 # templates
2765 2765 p = templater.templatepaths()
2766 2766 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2767 2767 fm.condwrite(not p, '', _(" no template directories found\n"))
2768 2768 if p:
2769 2769 m = templater.templatepath("map-cmdline.default")
2770 2770 if m:
2771 2771 # template found, check if it is working
2772 2772 err = None
2773 2773 try:
2774 2774 templater.templater.frommapfile(m)
2775 2775 except Exception as inst:
2776 2776 err = inst
2777 2777 p = None
2778 2778 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2779 2779 else:
2780 2780 p = None
2781 2781 fm.condwrite(p, 'defaulttemplate',
2782 2782 _("checking default template (%s)\n"), m)
2783 2783 fm.condwrite(not m, 'defaulttemplatenotfound',
2784 2784 _(" template '%s' not found\n"), "default")
2785 2785 if not p:
2786 2786 problems += 1
2787 2787 fm.condwrite(not p, '',
2788 2788 _(" (templates seem to have been installed incorrectly)\n"))
2789 2789
2790 2790 # editor
2791 2791 editor = ui.geteditor()
2792 2792 editor = util.expandpath(editor)
2793 2793 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2794 2794 cmdpath = util.findexe(shlex.split(editor)[0])
2795 2795 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2796 2796 _(" No commit editor set and can't find %s in PATH\n"
2797 2797 " (specify a commit editor in your configuration"
2798 2798 " file)\n"), not cmdpath and editor == 'vi' and editor)
2799 2799 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2800 2800 _(" Can't find editor '%s' in PATH\n"
2801 2801 " (specify a commit editor in your configuration"
2802 2802 " file)\n"), not cmdpath and editor)
2803 2803 if not cmdpath and editor != 'vi':
2804 2804 problems += 1
2805 2805
2806 2806 # check username
2807 2807 username = None
2808 2808 err = None
2809 2809 try:
2810 2810 username = ui.username()
2811 2811 except error.Abort as e:
2812 2812 err = e
2813 2813 problems += 1
2814 2814
2815 2815 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2816 2816 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2817 2817 " (specify a username in your configuration file)\n"), err)
2818 2818
2819 2819 fm.condwrite(not problems, '',
2820 2820 _("no problems detected\n"))
2821 2821 if not problems:
2822 2822 fm.data(problems=problems)
2823 2823 fm.condwrite(problems, 'problems',
2824 2824 _("%s problems detected,"
2825 2825 " please check your install!\n"), problems)
2826 2826 fm.end()
2827 2827
2828 2828 return problems
2829 2829
2830 2830 @command('debugknown', [], _('REPO ID...'), norepo=True)
2831 2831 def debugknown(ui, repopath, *ids, **opts):
2832 2832 """test whether node ids are known to a repo
2833 2833
2834 2834 Every ID must be a full-length hex node id string. Returns a list of 0s
2835 2835 and 1s indicating unknown/known.
2836 2836 """
2837 2837 repo = hg.peer(ui, opts, repopath)
2838 2838 if not repo.capable('known'):
2839 2839 raise error.Abort("known() not supported by target repository")
2840 2840 flags = repo.known([bin(s) for s in ids])
2841 2841 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2842 2842
2843 2843 @command('debuglabelcomplete', [], _('LABEL...'))
2844 2844 def debuglabelcomplete(ui, repo, *args):
2845 2845 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2846 2846 debugnamecomplete(ui, repo, *args)
2847 2847
2848 2848 @command('debugmergestate', [], '')
2849 2849 def debugmergestate(ui, repo, *args):
2850 2850 """print merge state
2851 2851
2852 2852 Use --verbose to print out information about whether v1 or v2 merge state
2853 2853 was chosen."""
2854 2854 def _hashornull(h):
2855 2855 if h == nullhex:
2856 2856 return 'null'
2857 2857 else:
2858 2858 return h
2859 2859
2860 2860 def printrecords(version):
2861 2861 ui.write(('* version %s records\n') % version)
2862 2862 if version == 1:
2863 2863 records = v1records
2864 2864 else:
2865 2865 records = v2records
2866 2866
2867 2867 for rtype, record in records:
2868 2868 # pretty print some record types
2869 2869 if rtype == 'L':
2870 2870 ui.write(('local: %s\n') % record)
2871 2871 elif rtype == 'O':
2872 2872 ui.write(('other: %s\n') % record)
2873 2873 elif rtype == 'm':
2874 2874 driver, mdstate = record.split('\0', 1)
2875 2875 ui.write(('merge driver: %s (state "%s")\n')
2876 2876 % (driver, mdstate))
2877 2877 elif rtype in 'FDC':
2878 2878 r = record.split('\0')
2879 2879 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2880 2880 if version == 1:
2881 2881 onode = 'not stored in v1 format'
2882 2882 flags = r[7]
2883 2883 else:
2884 2884 onode, flags = r[7:9]
2885 2885 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2886 2886 % (f, rtype, state, _hashornull(hash)))
2887 2887 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2888 2888 ui.write((' ancestor path: %s (node %s)\n')
2889 2889 % (afile, _hashornull(anode)))
2890 2890 ui.write((' other path: %s (node %s)\n')
2891 2891 % (ofile, _hashornull(onode)))
2892 2892 elif rtype == 'f':
2893 2893 filename, rawextras = record.split('\0', 1)
2894 2894 extras = rawextras.split('\0')
2895 2895 i = 0
2896 2896 extrastrings = []
2897 2897 while i < len(extras):
2898 2898 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2899 2899 i += 2
2900 2900
2901 2901 ui.write(('file extras: %s (%s)\n')
2902 2902 % (filename, ', '.join(extrastrings)))
2903 2903 elif rtype == 'l':
2904 2904 labels = record.split('\0', 2)
2905 2905 labels = [l for l in labels if len(l) > 0]
2906 2906 ui.write(('labels:\n'))
2907 2907 ui.write((' local: %s\n' % labels[0]))
2908 2908 ui.write((' other: %s\n' % labels[1]))
2909 2909 if len(labels) > 2:
2910 2910 ui.write((' base: %s\n' % labels[2]))
2911 2911 else:
2912 2912 ui.write(('unrecognized entry: %s\t%s\n')
2913 2913 % (rtype, record.replace('\0', '\t')))
2914 2914
2915 2915 # Avoid mergestate.read() since it may raise an exception for unsupported
2916 2916 # merge state records. We shouldn't be doing this, but this is OK since this
2917 2917 # command is pretty low-level.
2918 2918 ms = mergemod.mergestate(repo)
2919 2919
2920 2920 # sort so that reasonable information is on top
2921 2921 v1records = ms._readrecordsv1()
2922 2922 v2records = ms._readrecordsv2()
2923 2923 order = 'LOml'
2924 2924 def key(r):
2925 2925 idx = order.find(r[0])
2926 2926 if idx == -1:
2927 2927 return (1, r[1])
2928 2928 else:
2929 2929 return (0, idx)
2930 2930 v1records.sort(key=key)
2931 2931 v2records.sort(key=key)
2932 2932
2933 2933 if not v1records and not v2records:
2934 2934 ui.write(('no merge state found\n'))
2935 2935 elif not v2records:
2936 2936 ui.note(('no version 2 merge state\n'))
2937 2937 printrecords(1)
2938 2938 elif ms._v1v2match(v1records, v2records):
2939 2939 ui.note(('v1 and v2 states match: using v2\n'))
2940 2940 printrecords(2)
2941 2941 else:
2942 2942 ui.note(('v1 and v2 states mismatch: using v1\n'))
2943 2943 printrecords(1)
2944 2944 if ui.verbose:
2945 2945 printrecords(2)
2946 2946
2947 2947 @command('debugnamecomplete', [], _('NAME...'))
2948 2948 def debugnamecomplete(ui, repo, *args):
2949 2949 '''complete "names" - tags, open branch names, bookmark names'''
2950 2950
2951 2951 names = set()
2952 2952 # since we previously only listed open branches, we will handle that
2953 2953 # specially (after this for loop)
2954 2954 for name, ns in repo.names.iteritems():
2955 2955 if name != 'branches':
2956 2956 names.update(ns.listnames(repo))
2957 2957 names.update(tag for (tag, heads, tip, closed)
2958 2958 in repo.branchmap().iterbranches() if not closed)
2959 2959 completions = set()
2960 2960 if not args:
2961 2961 args = ['']
2962 2962 for a in args:
2963 2963 completions.update(n for n in names if n.startswith(a))
2964 2964 ui.write('\n'.join(sorted(completions)))
2965 2965 ui.write('\n')
2966 2966
2967 2967 @command('debuglocks',
2968 2968 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2969 2969 ('W', 'force-wlock', None,
2970 2970 _('free the working state lock (DANGEROUS)'))],
2971 2971 _('[OPTION]...'))
2972 2972 def debuglocks(ui, repo, **opts):
2973 2973 """show or modify state of locks
2974 2974
2975 2975 By default, this command will show which locks are held. This
2976 2976 includes the user and process holding the lock, the amount of time
2977 2977 the lock has been held, and the machine name where the process is
2978 2978 running if it's not local.
2979 2979
2980 2980 Locks protect the integrity of Mercurial's data, so should be
2981 2981 treated with care. System crashes or other interruptions may cause
2982 2982 locks to not be properly released, though Mercurial will usually
2983 2983 detect and remove such stale locks automatically.
2984 2984
2985 2985 However, detecting stale locks may not always be possible (for
2986 2986 instance, on a shared filesystem). Removing locks may also be
2987 2987 blocked by filesystem permissions.
2988 2988
2989 2989 Returns 0 if no locks are held.
2990 2990
2991 2991 """
2992 2992
2993 2993 if opts.get('force_lock'):
2994 2994 repo.svfs.unlink('lock')
2995 2995 if opts.get('force_wlock'):
2996 2996 repo.vfs.unlink('wlock')
2997 2997 if opts.get('force_lock') or opts.get('force_lock'):
2998 2998 return 0
2999 2999
3000 3000 now = time.time()
3001 3001 held = 0
3002 3002
3003 3003 def report(vfs, name, method):
3004 3004 # this causes stale locks to get reaped for more accurate reporting
3005 3005 try:
3006 3006 l = method(False)
3007 3007 except error.LockHeld:
3008 3008 l = None
3009 3009
3010 3010 if l:
3011 3011 l.release()
3012 3012 else:
3013 3013 try:
3014 3014 stat = vfs.lstat(name)
3015 3015 age = now - stat.st_mtime
3016 3016 user = util.username(stat.st_uid)
3017 3017 locker = vfs.readlock(name)
3018 3018 if ":" in locker:
3019 3019 host, pid = locker.split(':')
3020 3020 if host == socket.gethostname():
3021 3021 locker = 'user %s, process %s' % (user, pid)
3022 3022 else:
3023 3023 locker = 'user %s, process %s, host %s' \
3024 3024 % (user, pid, host)
3025 3025 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3026 3026 return 1
3027 3027 except OSError as e:
3028 3028 if e.errno != errno.ENOENT:
3029 3029 raise
3030 3030
3031 3031 ui.write(("%-6s free\n") % (name + ":"))
3032 3032 return 0
3033 3033
3034 3034 held += report(repo.svfs, "lock", repo.lock)
3035 3035 held += report(repo.vfs, "wlock", repo.wlock)
3036 3036
3037 3037 return held
3038 3038
3039 3039 @command('debugobsolete',
3040 3040 [('', 'flags', 0, _('markers flag')),
3041 3041 ('', 'record-parents', False,
3042 3042 _('record parent information for the precursor')),
3043 3043 ('r', 'rev', [], _('display markers relevant to REV')),
3044 3044 ('', 'index', False, _('display index of the marker')),
3045 3045 ('', 'delete', [], _('delete markers specified by indices')),
3046 3046 ] + commitopts2,
3047 3047 _('[OBSOLETED [REPLACEMENT ...]]'))
3048 3048 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3049 3049 """create arbitrary obsolete marker
3050 3050
3051 3051 With no arguments, displays the list of obsolescence markers."""
3052 3052
3053 3053 def parsenodeid(s):
3054 3054 try:
3055 3055 # We do not use revsingle/revrange functions here to accept
3056 3056 # arbitrary node identifiers, possibly not present in the
3057 3057 # local repository.
3058 3058 n = bin(s)
3059 3059 if len(n) != len(nullid):
3060 3060 raise TypeError()
3061 3061 return n
3062 3062 except TypeError:
3063 3063 raise error.Abort('changeset references must be full hexadecimal '
3064 3064 'node identifiers')
3065 3065
3066 3066 if opts.get('delete'):
3067 3067 indices = []
3068 3068 for v in opts.get('delete'):
3069 3069 try:
3070 3070 indices.append(int(v))
3071 3071 except ValueError:
3072 3072 raise error.Abort(_('invalid index value: %r') % v,
3073 3073 hint=_('use integers for indices'))
3074 3074
3075 3075 if repo.currenttransaction():
3076 3076 raise error.Abort(_('cannot delete obsmarkers in the middle '
3077 3077 'of transaction.'))
3078 3078
3079 3079 with repo.lock():
3080 3080 n = repair.deleteobsmarkers(repo.obsstore, indices)
3081 3081 ui.write(_('deleted %i obsolescense markers\n') % n)
3082 3082
3083 3083 return
3084 3084
3085 3085 if precursor is not None:
3086 3086 if opts['rev']:
3087 3087 raise error.Abort('cannot select revision when creating marker')
3088 3088 metadata = {}
3089 3089 metadata['user'] = opts['user'] or ui.username()
3090 3090 succs = tuple(parsenodeid(succ) for succ in successors)
3091 3091 l = repo.lock()
3092 3092 try:
3093 3093 tr = repo.transaction('debugobsolete')
3094 3094 try:
3095 3095 date = opts.get('date')
3096 3096 if date:
3097 3097 date = util.parsedate(date)
3098 3098 else:
3099 3099 date = None
3100 3100 prec = parsenodeid(precursor)
3101 3101 parents = None
3102 3102 if opts['record_parents']:
3103 3103 if prec not in repo.unfiltered():
3104 3104 raise error.Abort('cannot used --record-parents on '
3105 3105 'unknown changesets')
3106 3106 parents = repo.unfiltered()[prec].parents()
3107 3107 parents = tuple(p.node() for p in parents)
3108 3108 repo.obsstore.create(tr, prec, succs, opts['flags'],
3109 3109 parents=parents, date=date,
3110 3110 metadata=metadata)
3111 3111 tr.close()
3112 3112 except ValueError as exc:
3113 3113 raise error.Abort(_('bad obsmarker input: %s') % exc)
3114 3114 finally:
3115 3115 tr.release()
3116 3116 finally:
3117 3117 l.release()
3118 3118 else:
3119 3119 if opts['rev']:
3120 3120 revs = scmutil.revrange(repo, opts['rev'])
3121 3121 nodes = [repo[r].node() for r in revs]
3122 3122 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3123 3123 markers.sort(key=lambda x: x._data)
3124 3124 else:
3125 3125 markers = obsolete.getmarkers(repo)
3126 3126
3127 3127 markerstoiter = markers
3128 3128 isrelevant = lambda m: True
3129 3129 if opts.get('rev') and opts.get('index'):
3130 3130 markerstoiter = obsolete.getmarkers(repo)
3131 3131 markerset = set(markers)
3132 3132 isrelevant = lambda m: m in markerset
3133 3133
3134 3134 for i, m in enumerate(markerstoiter):
3135 3135 if not isrelevant(m):
3136 3136 # marker can be irrelevant when we're iterating over a set
3137 3137 # of markers (markerstoiter) which is bigger than the set
3138 3138 # of markers we want to display (markers)
3139 3139 # this can happen if both --index and --rev options are
3140 3140 # provided and thus we need to iterate over all of the markers
3141 3141 # to get the correct indices, but only display the ones that
3142 3142 # are relevant to --rev value
3143 3143 continue
3144 3144 ind = i if opts.get('index') else None
3145 3145 cmdutil.showmarker(ui, m, index=ind)
3146 3146
3147 3147 @command('debugpathcomplete',
3148 3148 [('f', 'full', None, _('complete an entire path')),
3149 3149 ('n', 'normal', None, _('show only normal files')),
3150 3150 ('a', 'added', None, _('show only added files')),
3151 3151 ('r', 'removed', None, _('show only removed files'))],
3152 3152 _('FILESPEC...'))
3153 3153 def debugpathcomplete(ui, repo, *specs, **opts):
3154 3154 '''complete part or all of a tracked path
3155 3155
3156 3156 This command supports shells that offer path name completion. It
3157 3157 currently completes only files already known to the dirstate.
3158 3158
3159 3159 Completion extends only to the next path segment unless
3160 3160 --full is specified, in which case entire paths are used.'''
3161 3161
3162 3162 def complete(path, acceptable):
3163 3163 dirstate = repo.dirstate
3164 3164 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3165 3165 rootdir = repo.root + os.sep
3166 3166 if spec != repo.root and not spec.startswith(rootdir):
3167 3167 return [], []
3168 3168 if os.path.isdir(spec):
3169 3169 spec += '/'
3170 3170 spec = spec[len(rootdir):]
3171 3171 fixpaths = os.sep != '/'
3172 3172 if fixpaths:
3173 3173 spec = spec.replace(os.sep, '/')
3174 3174 speclen = len(spec)
3175 3175 fullpaths = opts['full']
3176 3176 files, dirs = set(), set()
3177 3177 adddir, addfile = dirs.add, files.add
3178 3178 for f, st in dirstate.iteritems():
3179 3179 if f.startswith(spec) and st[0] in acceptable:
3180 3180 if fixpaths:
3181 3181 f = f.replace('/', os.sep)
3182 3182 if fullpaths:
3183 3183 addfile(f)
3184 3184 continue
3185 3185 s = f.find(os.sep, speclen)
3186 3186 if s >= 0:
3187 3187 adddir(f[:s])
3188 3188 else:
3189 3189 addfile(f)
3190 3190 return files, dirs
3191 3191
3192 3192 acceptable = ''
3193 3193 if opts['normal']:
3194 3194 acceptable += 'nm'
3195 3195 if opts['added']:
3196 3196 acceptable += 'a'
3197 3197 if opts['removed']:
3198 3198 acceptable += 'r'
3199 3199 cwd = repo.getcwd()
3200 3200 if not specs:
3201 3201 specs = ['.']
3202 3202
3203 3203 files, dirs = set(), set()
3204 3204 for spec in specs:
3205 3205 f, d = complete(spec, acceptable or 'nmar')
3206 3206 files.update(f)
3207 3207 dirs.update(d)
3208 3208 files.update(dirs)
3209 3209 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3210 3210 ui.write('\n')
3211 3211
3212 3212 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3213 3213 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3214 3214 '''access the pushkey key/value protocol
3215 3215
3216 3216 With two args, list the keys in the given namespace.
3217 3217
3218 3218 With five args, set a key to new if it currently is set to old.
3219 3219 Reports success or failure.
3220 3220 '''
3221 3221
3222 3222 target = hg.peer(ui, {}, repopath)
3223 3223 if keyinfo:
3224 3224 key, old, new = keyinfo
3225 3225 r = target.pushkey(namespace, key, old, new)
3226 3226 ui.status(str(r) + '\n')
3227 3227 return not r
3228 3228 else:
3229 3229 for k, v in sorted(target.listkeys(namespace).iteritems()):
3230 3230 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3231 3231 v.encode('string-escape')))
3232 3232
3233 3233 @command('debugpvec', [], _('A B'))
3234 3234 def debugpvec(ui, repo, a, b=None):
3235 3235 ca = scmutil.revsingle(repo, a)
3236 3236 cb = scmutil.revsingle(repo, b)
3237 3237 pa = pvec.ctxpvec(ca)
3238 3238 pb = pvec.ctxpvec(cb)
3239 3239 if pa == pb:
3240 3240 rel = "="
3241 3241 elif pa > pb:
3242 3242 rel = ">"
3243 3243 elif pa < pb:
3244 3244 rel = "<"
3245 3245 elif pa | pb:
3246 3246 rel = "|"
3247 3247 ui.write(_("a: %s\n") % pa)
3248 3248 ui.write(_("b: %s\n") % pb)
3249 3249 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3250 3250 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3251 3251 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3252 3252 pa.distance(pb), rel))
3253 3253
3254 3254 @command('debugrebuilddirstate|debugrebuildstate',
3255 3255 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3256 3256 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3257 3257 'the working copy parent')),
3258 3258 ],
3259 3259 _('[-r REV]'))
3260 3260 def debugrebuilddirstate(ui, repo, rev, **opts):
3261 3261 """rebuild the dirstate as it would look like for the given revision
3262 3262
3263 3263 If no revision is specified the first current parent will be used.
3264 3264
3265 3265 The dirstate will be set to the files of the given revision.
3266 3266 The actual working directory content or existing dirstate
3267 3267 information such as adds or removes is not considered.
3268 3268
3269 3269 ``minimal`` will only rebuild the dirstate status for files that claim to be
3270 3270 tracked but are not in the parent manifest, or that exist in the parent
3271 3271 manifest but are not in the dirstate. It will not change adds, removes, or
3272 3272 modified files that are in the working copy parent.
3273 3273
3274 3274 One use of this command is to make the next :hg:`status` invocation
3275 3275 check the actual file content.
3276 3276 """
3277 3277 ctx = scmutil.revsingle(repo, rev)
3278 3278 with repo.wlock():
3279 3279 dirstate = repo.dirstate
3280 3280 changedfiles = None
3281 3281 # See command doc for what minimal does.
3282 3282 if opts.get('minimal'):
3283 3283 manifestfiles = set(ctx.manifest().keys())
3284 3284 dirstatefiles = set(dirstate)
3285 3285 manifestonly = manifestfiles - dirstatefiles
3286 3286 dsonly = dirstatefiles - manifestfiles
3287 3287 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3288 3288 changedfiles = manifestonly | dsnotadded
3289 3289
3290 3290 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3291 3291
3292 3292 @command('debugrebuildfncache', [], '')
3293 3293 def debugrebuildfncache(ui, repo):
3294 3294 """rebuild the fncache file"""
3295 3295 repair.rebuildfncache(ui, repo)
3296 3296
3297 3297 @command('debugrename',
3298 3298 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3299 3299 _('[-r REV] FILE'))
3300 3300 def debugrename(ui, repo, file1, *pats, **opts):
3301 3301 """dump rename information"""
3302 3302
3303 3303 ctx = scmutil.revsingle(repo, opts.get('rev'))
3304 3304 m = scmutil.match(ctx, (file1,) + pats, opts)
3305 3305 for abs in ctx.walk(m):
3306 3306 fctx = ctx[abs]
3307 3307 o = fctx.filelog().renamed(fctx.filenode())
3308 3308 rel = m.rel(abs)
3309 3309 if o:
3310 3310 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3311 3311 else:
3312 3312 ui.write(_("%s not renamed\n") % rel)
3313 3313
3314 3314 @command('debugrevlog', debugrevlogopts +
3315 3315 [('d', 'dump', False, _('dump index data'))],
3316 3316 _('-c|-m|FILE'),
3317 3317 optionalrepo=True)
3318 3318 def debugrevlog(ui, repo, file_=None, **opts):
3319 3319 """show data and statistics about a revlog"""
3320 3320 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3321 3321
3322 3322 if opts.get("dump"):
3323 3323 numrevs = len(r)
3324 3324 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3325 3325 " rawsize totalsize compression heads chainlen\n"))
3326 3326 ts = 0
3327 3327 heads = set()
3328 3328
3329 3329 for rev in xrange(numrevs):
3330 3330 dbase = r.deltaparent(rev)
3331 3331 if dbase == -1:
3332 3332 dbase = rev
3333 3333 cbase = r.chainbase(rev)
3334 3334 clen = r.chainlen(rev)
3335 3335 p1, p2 = r.parentrevs(rev)
3336 3336 rs = r.rawsize(rev)
3337 3337 ts = ts + rs
3338 3338 heads -= set(r.parentrevs(rev))
3339 3339 heads.add(rev)
3340 3340 try:
3341 3341 compression = ts / r.end(rev)
3342 3342 except ZeroDivisionError:
3343 3343 compression = 0
3344 3344 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3345 3345 "%11d %5d %8d\n" %
3346 3346 (rev, p1, p2, r.start(rev), r.end(rev),
3347 3347 r.start(dbase), r.start(cbase),
3348 3348 r.start(p1), r.start(p2),
3349 3349 rs, ts, compression, len(heads), clen))
3350 3350 return 0
3351 3351
3352 3352 v = r.version
3353 3353 format = v & 0xFFFF
3354 3354 flags = []
3355 3355 gdelta = False
3356 3356 if v & revlog.REVLOGNGINLINEDATA:
3357 3357 flags.append('inline')
3358 3358 if v & revlog.REVLOGGENERALDELTA:
3359 3359 gdelta = True
3360 3360 flags.append('generaldelta')
3361 3361 if not flags:
3362 3362 flags = ['(none)']
3363 3363
3364 3364 nummerges = 0
3365 3365 numfull = 0
3366 3366 numprev = 0
3367 3367 nump1 = 0
3368 3368 nump2 = 0
3369 3369 numother = 0
3370 3370 nump1prev = 0
3371 3371 nump2prev = 0
3372 3372 chainlengths = []
3373 3373
3374 3374 datasize = [None, 0, 0L]
3375 3375 fullsize = [None, 0, 0L]
3376 3376 deltasize = [None, 0, 0L]
3377 3377
3378 3378 def addsize(size, l):
3379 3379 if l[0] is None or size < l[0]:
3380 3380 l[0] = size
3381 3381 if size > l[1]:
3382 3382 l[1] = size
3383 3383 l[2] += size
3384 3384
3385 3385 numrevs = len(r)
3386 3386 for rev in xrange(numrevs):
3387 3387 p1, p2 = r.parentrevs(rev)
3388 3388 delta = r.deltaparent(rev)
3389 3389 if format > 0:
3390 3390 addsize(r.rawsize(rev), datasize)
3391 3391 if p2 != nullrev:
3392 3392 nummerges += 1
3393 3393 size = r.length(rev)
3394 3394 if delta == nullrev:
3395 3395 chainlengths.append(0)
3396 3396 numfull += 1
3397 3397 addsize(size, fullsize)
3398 3398 else:
3399 3399 chainlengths.append(chainlengths[delta] + 1)
3400 3400 addsize(size, deltasize)
3401 3401 if delta == rev - 1:
3402 3402 numprev += 1
3403 3403 if delta == p1:
3404 3404 nump1prev += 1
3405 3405 elif delta == p2:
3406 3406 nump2prev += 1
3407 3407 elif delta == p1:
3408 3408 nump1 += 1
3409 3409 elif delta == p2:
3410 3410 nump2 += 1
3411 3411 elif delta != nullrev:
3412 3412 numother += 1
3413 3413
3414 3414 # Adjust size min value for empty cases
3415 3415 for size in (datasize, fullsize, deltasize):
3416 3416 if size[0] is None:
3417 3417 size[0] = 0
3418 3418
3419 3419 numdeltas = numrevs - numfull
3420 3420 numoprev = numprev - nump1prev - nump2prev
3421 3421 totalrawsize = datasize[2]
3422 3422 datasize[2] /= numrevs
3423 3423 fulltotal = fullsize[2]
3424 3424 fullsize[2] /= numfull
3425 3425 deltatotal = deltasize[2]
3426 3426 if numrevs - numfull > 0:
3427 3427 deltasize[2] /= numrevs - numfull
3428 3428 totalsize = fulltotal + deltatotal
3429 3429 avgchainlen = sum(chainlengths) / numrevs
3430 3430 maxchainlen = max(chainlengths)
3431 3431 compratio = 1
3432 3432 if totalsize:
3433 3433 compratio = totalrawsize / totalsize
3434 3434
3435 3435 basedfmtstr = '%%%dd\n'
3436 3436 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3437 3437
3438 3438 def dfmtstr(max):
3439 3439 return basedfmtstr % len(str(max))
3440 3440 def pcfmtstr(max, padding=0):
3441 3441 return basepcfmtstr % (len(str(max)), ' ' * padding)
3442 3442
3443 3443 def pcfmt(value, total):
3444 3444 if total:
3445 3445 return (value, 100 * float(value) / total)
3446 3446 else:
3447 3447 return value, 100.0
3448 3448
3449 3449 ui.write(('format : %d\n') % format)
3450 3450 ui.write(('flags : %s\n') % ', '.join(flags))
3451 3451
3452 3452 ui.write('\n')
3453 3453 fmt = pcfmtstr(totalsize)
3454 3454 fmt2 = dfmtstr(totalsize)
3455 3455 ui.write(('revisions : ') + fmt2 % numrevs)
3456 3456 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3457 3457 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3458 3458 ui.write(('revisions : ') + fmt2 % numrevs)
3459 3459 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3460 3460 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3461 3461 ui.write(('revision size : ') + fmt2 % totalsize)
3462 3462 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3463 3463 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3464 3464
3465 3465 ui.write('\n')
3466 3466 fmt = dfmtstr(max(avgchainlen, compratio))
3467 3467 ui.write(('avg chain length : ') + fmt % avgchainlen)
3468 3468 ui.write(('max chain length : ') + fmt % maxchainlen)
3469 3469 ui.write(('compression ratio : ') + fmt % compratio)
3470 3470
3471 3471 if format > 0:
3472 3472 ui.write('\n')
3473 3473 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3474 3474 % tuple(datasize))
3475 3475 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3476 3476 % tuple(fullsize))
3477 3477 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3478 3478 % tuple(deltasize))
3479 3479
3480 3480 if numdeltas > 0:
3481 3481 ui.write('\n')
3482 3482 fmt = pcfmtstr(numdeltas)
3483 3483 fmt2 = pcfmtstr(numdeltas, 4)
3484 3484 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3485 3485 if numprev > 0:
3486 3486 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3487 3487 numprev))
3488 3488 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3489 3489 numprev))
3490 3490 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3491 3491 numprev))
3492 3492 if gdelta:
3493 3493 ui.write(('deltas against p1 : ')
3494 3494 + fmt % pcfmt(nump1, numdeltas))
3495 3495 ui.write(('deltas against p2 : ')
3496 3496 + fmt % pcfmt(nump2, numdeltas))
3497 3497 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3498 3498 numdeltas))
3499 3499
3500 3500 @command('debugrevspec',
3501 3501 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3502 3502 ('REVSPEC'))
3503 3503 def debugrevspec(ui, repo, expr, **opts):
3504 3504 """parse and apply a revision specification
3505 3505
3506 3506 Use --verbose to print the parsed tree before and after aliases
3507 3507 expansion.
3508 3508 """
3509 3509 if ui.verbose:
3510 3510 tree = revset.parse(expr, lookup=repo.__contains__)
3511 3511 ui.note(revset.prettyformat(tree), "\n")
3512 3512 newtree = revset.expandaliases(ui, tree)
3513 3513 if newtree != tree:
3514 3514 ui.note(("* expanded:\n"), revset.prettyformat(newtree), "\n")
3515 3515 tree = newtree
3516 3516 newtree = revset.foldconcat(tree)
3517 3517 if newtree != tree:
3518 3518 ui.note(("* concatenated:\n"), revset.prettyformat(newtree), "\n")
3519 3519 if opts["optimize"]:
3520 3520 optimizedtree = revset.optimize(newtree)
3521 3521 ui.note(("* optimized:\n"),
3522 3522 revset.prettyformat(optimizedtree), "\n")
3523 3523 func = revset.match(ui, expr, repo)
3524 3524 revs = func(repo)
3525 3525 if ui.verbose:
3526 3526 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3527 3527 for c in revs:
3528 3528 ui.write("%s\n" % c)
3529 3529
3530 3530 @command('debugsetparents', [], _('REV1 [REV2]'))
3531 3531 def debugsetparents(ui, repo, rev1, rev2=None):
3532 3532 """manually set the parents of the current working directory
3533 3533
3534 3534 This is useful for writing repository conversion tools, but should
3535 3535 be used with care. For example, neither the working directory nor the
3536 3536 dirstate is updated, so file status may be incorrect after running this
3537 3537 command.
3538 3538
3539 3539 Returns 0 on success.
3540 3540 """
3541 3541
3542 3542 r1 = scmutil.revsingle(repo, rev1).node()
3543 3543 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3544 3544
3545 3545 with repo.wlock():
3546 3546 repo.setparents(r1, r2)
3547 3547
3548 3548 @command('debugdirstate|debugstate',
3549 3549 [('', 'nodates', None, _('do not display the saved mtime')),
3550 3550 ('', 'datesort', None, _('sort by saved mtime'))],
3551 3551 _('[OPTION]...'))
3552 3552 def debugstate(ui, repo, **opts):
3553 3553 """show the contents of the current dirstate"""
3554 3554
3555 3555 nodates = opts.get('nodates')
3556 3556 datesort = opts.get('datesort')
3557 3557
3558 3558 timestr = ""
3559 3559 if datesort:
3560 3560 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3561 3561 else:
3562 3562 keyfunc = None # sort by filename
3563 3563 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3564 3564 if ent[3] == -1:
3565 3565 timestr = 'unset '
3566 3566 elif nodates:
3567 3567 timestr = 'set '
3568 3568 else:
3569 3569 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3570 3570 time.localtime(ent[3]))
3571 3571 if ent[1] & 0o20000:
3572 3572 mode = 'lnk'
3573 3573 else:
3574 3574 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3575 3575 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3576 3576 for f in repo.dirstate.copies():
3577 3577 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3578 3578
3579 3579 @command('debugsub',
3580 3580 [('r', 'rev', '',
3581 3581 _('revision to check'), _('REV'))],
3582 3582 _('[-r REV] [REV]'))
3583 3583 def debugsub(ui, repo, rev=None):
3584 3584 ctx = scmutil.revsingle(repo, rev, None)
3585 3585 for k, v in sorted(ctx.substate.items()):
3586 3586 ui.write(('path %s\n') % k)
3587 3587 ui.write((' source %s\n') % v[0])
3588 3588 ui.write((' revision %s\n') % v[1])
3589 3589
3590 3590 @command('debugsuccessorssets',
3591 3591 [],
3592 3592 _('[REV]'))
3593 3593 def debugsuccessorssets(ui, repo, *revs):
3594 3594 """show set of successors for revision
3595 3595
3596 3596 A successors set of changeset A is a consistent group of revisions that
3597 3597 succeed A. It contains non-obsolete changesets only.
3598 3598
3599 3599 In most cases a changeset A has a single successors set containing a single
3600 3600 successor (changeset A replaced by A').
3601 3601
3602 3602 A changeset that is made obsolete with no successors are called "pruned".
3603 3603 Such changesets have no successors sets at all.
3604 3604
3605 3605 A changeset that has been "split" will have a successors set containing
3606 3606 more than one successor.
3607 3607
3608 3608 A changeset that has been rewritten in multiple different ways is called
3609 3609 "divergent". Such changesets have multiple successor sets (each of which
3610 3610 may also be split, i.e. have multiple successors).
3611 3611
3612 3612 Results are displayed as follows::
3613 3613
3614 3614 <rev1>
3615 3615 <successors-1A>
3616 3616 <rev2>
3617 3617 <successors-2A>
3618 3618 <successors-2B1> <successors-2B2> <successors-2B3>
3619 3619
3620 3620 Here rev2 has two possible (i.e. divergent) successors sets. The first
3621 3621 holds one element, whereas the second holds three (i.e. the changeset has
3622 3622 been split).
3623 3623 """
3624 3624 # passed to successorssets caching computation from one call to another
3625 3625 cache = {}
3626 3626 ctx2str = str
3627 3627 node2str = short
3628 3628 if ui.debug():
3629 3629 def ctx2str(ctx):
3630 3630 return ctx.hex()
3631 3631 node2str = hex
3632 3632 for rev in scmutil.revrange(repo, revs):
3633 3633 ctx = repo[rev]
3634 3634 ui.write('%s\n'% ctx2str(ctx))
3635 3635 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3636 3636 if succsset:
3637 3637 ui.write(' ')
3638 3638 ui.write(node2str(succsset[0]))
3639 3639 for node in succsset[1:]:
3640 3640 ui.write(' ')
3641 3641 ui.write(node2str(node))
3642 3642 ui.write('\n')
3643 3643
3644 3644 @command('debugtemplate',
3645 3645 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3646 3646 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3647 3647 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3648 3648 optionalrepo=True)
3649 3649 def debugtemplate(ui, repo, tmpl, **opts):
3650 3650 """parse and apply a template
3651 3651
3652 3652 If -r/--rev is given, the template is processed as a log template and
3653 3653 applied to the given changesets. Otherwise, it is processed as a generic
3654 3654 template.
3655 3655
3656 3656 Use --verbose to print the parsed tree.
3657 3657 """
3658 3658 revs = None
3659 3659 if opts['rev']:
3660 3660 if repo is None:
3661 3661 raise error.RepoError(_('there is no Mercurial repository here '
3662 3662 '(.hg not found)'))
3663 3663 revs = scmutil.revrange(repo, opts['rev'])
3664 3664
3665 3665 props = {}
3666 3666 for d in opts['define']:
3667 3667 try:
3668 3668 k, v = (e.strip() for e in d.split('=', 1))
3669 3669 if not k:
3670 3670 raise ValueError
3671 3671 props[k] = v
3672 3672 except ValueError:
3673 3673 raise error.Abort(_('malformed keyword definition: %s') % d)
3674 3674
3675 3675 if ui.verbose:
3676 3676 aliases = ui.configitems('templatealias')
3677 3677 tree = templater.parse(tmpl)
3678 3678 ui.note(templater.prettyformat(tree), '\n')
3679 3679 newtree = templater.expandaliases(tree, aliases)
3680 3680 if newtree != tree:
3681 3681 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3682 3682
3683 3683 mapfile = None
3684 3684 if revs is None:
3685 3685 k = 'debugtemplate'
3686 3686 t = formatter.maketemplater(ui, k, tmpl)
3687 3687 ui.write(templater.stringify(t(k, **props)))
3688 3688 else:
3689 3689 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3690 3690 mapfile, buffered=False)
3691 3691 for r in revs:
3692 3692 displayer.show(repo[r], **props)
3693 3693 displayer.close()
3694 3694
3695 3695 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3696 3696 def debugwalk(ui, repo, *pats, **opts):
3697 3697 """show how files match on given patterns"""
3698 3698 m = scmutil.match(repo[None], pats, opts)
3699 3699 items = list(repo.walk(m))
3700 3700 if not items:
3701 3701 return
3702 3702 f = lambda fn: fn
3703 3703 if ui.configbool('ui', 'slash') and os.sep != '/':
3704 3704 f = lambda fn: util.normpath(fn)
3705 3705 fmt = 'f %%-%ds %%-%ds %%s' % (
3706 3706 max([len(abs) for abs in items]),
3707 3707 max([len(m.rel(abs)) for abs in items]))
3708 3708 for abs in items:
3709 3709 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3710 3710 ui.write("%s\n" % line.rstrip())
3711 3711
3712 3712 @command('debugwireargs',
3713 3713 [('', 'three', '', 'three'),
3714 3714 ('', 'four', '', 'four'),
3715 3715 ('', 'five', '', 'five'),
3716 3716 ] + remoteopts,
3717 3717 _('REPO [OPTIONS]... [ONE [TWO]]'),
3718 3718 norepo=True)
3719 3719 def debugwireargs(ui, repopath, *vals, **opts):
3720 3720 repo = hg.peer(ui, opts, repopath)
3721 3721 for opt in remoteopts:
3722 3722 del opts[opt[1]]
3723 3723 args = {}
3724 3724 for k, v in opts.iteritems():
3725 3725 if v:
3726 3726 args[k] = v
3727 3727 # run twice to check that we don't mess up the stream for the next command
3728 3728 res1 = repo.debugwireargs(*vals, **args)
3729 3729 res2 = repo.debugwireargs(*vals, **args)
3730 3730 ui.write("%s\n" % res1)
3731 3731 if res1 != res2:
3732 3732 ui.warn("%s\n" % res2)
3733 3733
3734 3734 @command('^diff',
3735 3735 [('r', 'rev', [], _('revision'), _('REV')),
3736 3736 ('c', 'change', '', _('change made by revision'), _('REV'))
3737 3737 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3738 3738 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3739 3739 inferrepo=True)
3740 3740 def diff(ui, repo, *pats, **opts):
3741 3741 """diff repository (or selected files)
3742 3742
3743 3743 Show differences between revisions for the specified files.
3744 3744
3745 3745 Differences between files are shown using the unified diff format.
3746 3746
3747 3747 .. note::
3748 3748
3749 3749 :hg:`diff` may generate unexpected results for merges, as it will
3750 3750 default to comparing against the working directory's first
3751 3751 parent changeset if no revisions are specified.
3752 3752
3753 3753 When two revision arguments are given, then changes are shown
3754 3754 between those revisions. If only one revision is specified then
3755 3755 that revision is compared to the working directory, and, when no
3756 3756 revisions are specified, the working directory files are compared
3757 3757 to its first parent.
3758 3758
3759 3759 Alternatively you can specify -c/--change with a revision to see
3760 3760 the changes in that changeset relative to its first parent.
3761 3761
3762 3762 Without the -a/--text option, diff will avoid generating diffs of
3763 3763 files it detects as binary. With -a, diff will generate a diff
3764 3764 anyway, probably with undesirable results.
3765 3765
3766 3766 Use the -g/--git option to generate diffs in the git extended diff
3767 3767 format. For more information, read :hg:`help diffs`.
3768 3768
3769 3769 .. container:: verbose
3770 3770
3771 3771 Examples:
3772 3772
3773 3773 - compare a file in the current working directory to its parent::
3774 3774
3775 3775 hg diff foo.c
3776 3776
3777 3777 - compare two historical versions of a directory, with rename info::
3778 3778
3779 3779 hg diff --git -r 1.0:1.2 lib/
3780 3780
3781 3781 - get change stats relative to the last change on some date::
3782 3782
3783 3783 hg diff --stat -r "date('may 2')"
3784 3784
3785 3785 - diff all newly-added files that contain a keyword::
3786 3786
3787 3787 hg diff "set:added() and grep(GNU)"
3788 3788
3789 3789 - compare a revision and its parents::
3790 3790
3791 3791 hg diff -c 9353 # compare against first parent
3792 3792 hg diff -r 9353^:9353 # same using revset syntax
3793 3793 hg diff -r 9353^2:9353 # compare against the second parent
3794 3794
3795 3795 Returns 0 on success.
3796 3796 """
3797 3797
3798 3798 revs = opts.get('rev')
3799 3799 change = opts.get('change')
3800 3800 stat = opts.get('stat')
3801 3801 reverse = opts.get('reverse')
3802 3802
3803 3803 if revs and change:
3804 3804 msg = _('cannot specify --rev and --change at the same time')
3805 3805 raise error.Abort(msg)
3806 3806 elif change:
3807 3807 node2 = scmutil.revsingle(repo, change, None).node()
3808 3808 node1 = repo[node2].p1().node()
3809 3809 else:
3810 3810 node1, node2 = scmutil.revpair(repo, revs)
3811 3811
3812 3812 if reverse:
3813 3813 node1, node2 = node2, node1
3814 3814
3815 3815 diffopts = patch.diffallopts(ui, opts)
3816 3816 m = scmutil.match(repo[node2], pats, opts)
3817 3817 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3818 3818 listsubrepos=opts.get('subrepos'),
3819 3819 root=opts.get('root'))
3820 3820
3821 3821 @command('^export',
3822 3822 [('o', 'output', '',
3823 3823 _('print output to file with formatted name'), _('FORMAT')),
3824 3824 ('', 'switch-parent', None, _('diff against the second parent')),
3825 3825 ('r', 'rev', [], _('revisions to export'), _('REV')),
3826 3826 ] + diffopts,
3827 3827 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3828 3828 def export(ui, repo, *changesets, **opts):
3829 3829 """dump the header and diffs for one or more changesets
3830 3830
3831 3831 Print the changeset header and diffs for one or more revisions.
3832 3832 If no revision is given, the parent of the working directory is used.
3833 3833
3834 3834 The information shown in the changeset header is: author, date,
3835 3835 branch name (if non-default), changeset hash, parent(s) and commit
3836 3836 comment.
3837 3837
3838 3838 .. note::
3839 3839
3840 3840 :hg:`export` may generate unexpected diff output for merge
3841 3841 changesets, as it will compare the merge changeset against its
3842 3842 first parent only.
3843 3843
3844 3844 Output may be to a file, in which case the name of the file is
3845 3845 given using a format string. The formatting rules are as follows:
3846 3846
3847 3847 :``%%``: literal "%" character
3848 3848 :``%H``: changeset hash (40 hexadecimal digits)
3849 3849 :``%N``: number of patches being generated
3850 3850 :``%R``: changeset revision number
3851 3851 :``%b``: basename of the exporting repository
3852 3852 :``%h``: short-form changeset hash (12 hexadecimal digits)
3853 3853 :``%m``: first line of the commit message (only alphanumeric characters)
3854 3854 :``%n``: zero-padded sequence number, starting at 1
3855 3855 :``%r``: zero-padded changeset revision number
3856 3856
3857 3857 Without the -a/--text option, export will avoid generating diffs
3858 3858 of files it detects as binary. With -a, export will generate a
3859 3859 diff anyway, probably with undesirable results.
3860 3860
3861 3861 Use the -g/--git option to generate diffs in the git extended diff
3862 3862 format. See :hg:`help diffs` for more information.
3863 3863
3864 3864 With the --switch-parent option, the diff will be against the
3865 3865 second parent. It can be useful to review a merge.
3866 3866
3867 3867 .. container:: verbose
3868 3868
3869 3869 Examples:
3870 3870
3871 3871 - use export and import to transplant a bugfix to the current
3872 3872 branch::
3873 3873
3874 3874 hg export -r 9353 | hg import -
3875 3875
3876 3876 - export all the changesets between two revisions to a file with
3877 3877 rename information::
3878 3878
3879 3879 hg export --git -r 123:150 > changes.txt
3880 3880
3881 3881 - split outgoing changes into a series of patches with
3882 3882 descriptive names::
3883 3883
3884 3884 hg export -r "outgoing()" -o "%n-%m.patch"
3885 3885
3886 3886 Returns 0 on success.
3887 3887 """
3888 3888 changesets += tuple(opts.get('rev', []))
3889 3889 if not changesets:
3890 3890 changesets = ['.']
3891 3891 revs = scmutil.revrange(repo, changesets)
3892 3892 if not revs:
3893 3893 raise error.Abort(_("export requires at least one changeset"))
3894 3894 if len(revs) > 1:
3895 3895 ui.note(_('exporting patches:\n'))
3896 3896 else:
3897 3897 ui.note(_('exporting patch:\n'))
3898 3898 cmdutil.export(repo, revs, template=opts.get('output'),
3899 3899 switch_parent=opts.get('switch_parent'),
3900 3900 opts=patch.diffallopts(ui, opts))
3901 3901
3902 3902 @command('files',
3903 3903 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3904 3904 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3905 3905 ] + walkopts + formatteropts + subrepoopts,
3906 3906 _('[OPTION]... [PATTERN]...'))
3907 3907 def files(ui, repo, *pats, **opts):
3908 3908 """list tracked files
3909 3909
3910 3910 Print files under Mercurial control in the working directory or
3911 3911 specified revision whose names match the given patterns (excluding
3912 3912 removed files).
3913 3913
3914 3914 If no patterns are given to match, this command prints the names
3915 3915 of all files under Mercurial control in the working directory.
3916 3916
3917 3917 .. container:: verbose
3918 3918
3919 3919 Examples:
3920 3920
3921 3921 - list all files under the current directory::
3922 3922
3923 3923 hg files .
3924 3924
3925 3925 - shows sizes and flags for current revision::
3926 3926
3927 3927 hg files -vr .
3928 3928
3929 3929 - list all files named README::
3930 3930
3931 3931 hg files -I "**/README"
3932 3932
3933 3933 - list all binary files::
3934 3934
3935 3935 hg files "set:binary()"
3936 3936
3937 3937 - find files containing a regular expression::
3938 3938
3939 3939 hg files "set:grep('bob')"
3940 3940
3941 3941 - search tracked file contents with xargs and grep::
3942 3942
3943 3943 hg files -0 | xargs -0 grep foo
3944 3944
3945 3945 See :hg:`help patterns` and :hg:`help filesets` for more information
3946 3946 on specifying file patterns.
3947 3947
3948 3948 Returns 0 if a match is found, 1 otherwise.
3949 3949
3950 3950 """
3951 3951 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3952 3952
3953 3953 end = '\n'
3954 3954 if opts.get('print0'):
3955 3955 end = '\0'
3956 3956 fm = ui.formatter('files', opts)
3957 3957 fmt = '%s' + end
3958 3958
3959 3959 m = scmutil.match(ctx, pats, opts)
3960 3960 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3961 3961
3962 3962 fm.end()
3963 3963
3964 3964 return ret
3965 3965
3966 3966 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3967 3967 def forget(ui, repo, *pats, **opts):
3968 3968 """forget the specified files on the next commit
3969 3969
3970 3970 Mark the specified files so they will no longer be tracked
3971 3971 after the next commit.
3972 3972
3973 3973 This only removes files from the current branch, not from the
3974 3974 entire project history, and it does not delete them from the
3975 3975 working directory.
3976 3976
3977 3977 To delete the file from the working directory, see :hg:`remove`.
3978 3978
3979 3979 To undo a forget before the next commit, see :hg:`add`.
3980 3980
3981 3981 .. container:: verbose
3982 3982
3983 3983 Examples:
3984 3984
3985 3985 - forget newly-added binary files::
3986 3986
3987 3987 hg forget "set:added() and binary()"
3988 3988
3989 3989 - forget files that would be excluded by .hgignore::
3990 3990
3991 3991 hg forget "set:hgignore()"
3992 3992
3993 3993 Returns 0 on success.
3994 3994 """
3995 3995
3996 3996 if not pats:
3997 3997 raise error.Abort(_('no files specified'))
3998 3998
3999 3999 m = scmutil.match(repo[None], pats, opts)
4000 4000 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4001 4001 return rejected and 1 or 0
4002 4002
4003 4003 @command(
4004 4004 'graft',
4005 4005 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4006 4006 ('c', 'continue', False, _('resume interrupted graft')),
4007 4007 ('e', 'edit', False, _('invoke editor on commit messages')),
4008 4008 ('', 'log', None, _('append graft info to log message')),
4009 4009 ('f', 'force', False, _('force graft')),
4010 4010 ('D', 'currentdate', False,
4011 4011 _('record the current date as commit date')),
4012 4012 ('U', 'currentuser', False,
4013 4013 _('record the current user as committer'), _('DATE'))]
4014 4014 + commitopts2 + mergetoolopts + dryrunopts,
4015 4015 _('[OPTION]... [-r REV]... REV...'))
4016 4016 def graft(ui, repo, *revs, **opts):
4017 4017 '''copy changes from other branches onto the current branch
4018 4018
4019 4019 This command uses Mercurial's merge logic to copy individual
4020 4020 changes from other branches without merging branches in the
4021 4021 history graph. This is sometimes known as 'backporting' or
4022 4022 'cherry-picking'. By default, graft will copy user, date, and
4023 4023 description from the source changesets.
4024 4024
4025 4025 Changesets that are ancestors of the current revision, that have
4026 4026 already been grafted, or that are merges will be skipped.
4027 4027
4028 4028 If --log is specified, log messages will have a comment appended
4029 4029 of the form::
4030 4030
4031 4031 (grafted from CHANGESETHASH)
4032 4032
4033 4033 If --force is specified, revisions will be grafted even if they
4034 4034 are already ancestors of or have been grafted to the destination.
4035 4035 This is useful when the revisions have since been backed out.
4036 4036
4037 4037 If a graft merge results in conflicts, the graft process is
4038 4038 interrupted so that the current merge can be manually resolved.
4039 4039 Once all conflicts are addressed, the graft process can be
4040 4040 continued with the -c/--continue option.
4041 4041
4042 4042 .. note::
4043 4043
4044 4044 The -c/--continue option does not reapply earlier options, except
4045 4045 for --force.
4046 4046
4047 4047 .. container:: verbose
4048 4048
4049 4049 Examples:
4050 4050
4051 4051 - copy a single change to the stable branch and edit its description::
4052 4052
4053 4053 hg update stable
4054 4054 hg graft --edit 9393
4055 4055
4056 4056 - graft a range of changesets with one exception, updating dates::
4057 4057
4058 4058 hg graft -D "2085::2093 and not 2091"
4059 4059
4060 4060 - continue a graft after resolving conflicts::
4061 4061
4062 4062 hg graft -c
4063 4063
4064 4064 - show the source of a grafted changeset::
4065 4065
4066 4066 hg log --debug -r .
4067 4067
4068 4068 - show revisions sorted by date::
4069 4069
4070 4070 hg log -r "sort(all(), date)"
4071 4071
4072 4072 See :hg:`help revisions` and :hg:`help revsets` for more about
4073 4073 specifying revisions.
4074 4074
4075 4075 Returns 0 on successful completion.
4076 4076 '''
4077 4077 with repo.wlock():
4078 4078 return _dograft(ui, repo, *revs, **opts)
4079 4079
4080 4080 def _dograft(ui, repo, *revs, **opts):
4081 4081 if revs and opts.get('rev'):
4082 4082 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4083 4083 'revision ordering!\n'))
4084 4084
4085 4085 revs = list(revs)
4086 4086 revs.extend(opts.get('rev'))
4087 4087
4088 4088 if not opts.get('user') and opts.get('currentuser'):
4089 4089 opts['user'] = ui.username()
4090 4090 if not opts.get('date') and opts.get('currentdate'):
4091 4091 opts['date'] = "%d %d" % util.makedate()
4092 4092
4093 4093 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4094 4094
4095 4095 cont = False
4096 4096 if opts.get('continue'):
4097 4097 cont = True
4098 4098 if revs:
4099 4099 raise error.Abort(_("can't specify --continue and revisions"))
4100 4100 # read in unfinished revisions
4101 4101 try:
4102 4102 nodes = repo.vfs.read('graftstate').splitlines()
4103 4103 revs = [repo[node].rev() for node in nodes]
4104 4104 except IOError as inst:
4105 4105 if inst.errno != errno.ENOENT:
4106 4106 raise
4107 4107 cmdutil.wrongtooltocontinue(repo, _('graft'))
4108 4108 else:
4109 4109 cmdutil.checkunfinished(repo)
4110 4110 cmdutil.bailifchanged(repo)
4111 4111 if not revs:
4112 4112 raise error.Abort(_('no revisions specified'))
4113 4113 revs = scmutil.revrange(repo, revs)
4114 4114
4115 4115 skipped = set()
4116 4116 # check for merges
4117 4117 for rev in repo.revs('%ld and merge()', revs):
4118 4118 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4119 4119 skipped.add(rev)
4120 4120 revs = [r for r in revs if r not in skipped]
4121 4121 if not revs:
4122 4122 return -1
4123 4123
4124 4124 # Don't check in the --continue case, in effect retaining --force across
4125 4125 # --continues. That's because without --force, any revisions we decided to
4126 4126 # skip would have been filtered out here, so they wouldn't have made their
4127 4127 # way to the graftstate. With --force, any revisions we would have otherwise
4128 4128 # skipped would not have been filtered out, and if they hadn't been applied
4129 4129 # already, they'd have been in the graftstate.
4130 4130 if not (cont or opts.get('force')):
4131 4131 # check for ancestors of dest branch
4132 4132 crev = repo['.'].rev()
4133 4133 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4134 4134 # Cannot use x.remove(y) on smart set, this has to be a list.
4135 4135 # XXX make this lazy in the future
4136 4136 revs = list(revs)
4137 4137 # don't mutate while iterating, create a copy
4138 4138 for rev in list(revs):
4139 4139 if rev in ancestors:
4140 4140 ui.warn(_('skipping ancestor revision %d:%s\n') %
4141 4141 (rev, repo[rev]))
4142 4142 # XXX remove on list is slow
4143 4143 revs.remove(rev)
4144 4144 if not revs:
4145 4145 return -1
4146 4146
4147 4147 # analyze revs for earlier grafts
4148 4148 ids = {}
4149 4149 for ctx in repo.set("%ld", revs):
4150 4150 ids[ctx.hex()] = ctx.rev()
4151 4151 n = ctx.extra().get('source')
4152 4152 if n:
4153 4153 ids[n] = ctx.rev()
4154 4154
4155 4155 # check ancestors for earlier grafts
4156 4156 ui.debug('scanning for duplicate grafts\n')
4157 4157
4158 4158 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4159 4159 ctx = repo[rev]
4160 4160 n = ctx.extra().get('source')
4161 4161 if n in ids:
4162 4162 try:
4163 4163 r = repo[n].rev()
4164 4164 except error.RepoLookupError:
4165 4165 r = None
4166 4166 if r in revs:
4167 4167 ui.warn(_('skipping revision %d:%s '
4168 4168 '(already grafted to %d:%s)\n')
4169 4169 % (r, repo[r], rev, ctx))
4170 4170 revs.remove(r)
4171 4171 elif ids[n] in revs:
4172 4172 if r is None:
4173 4173 ui.warn(_('skipping already grafted revision %d:%s '
4174 4174 '(%d:%s also has unknown origin %s)\n')
4175 4175 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4176 4176 else:
4177 4177 ui.warn(_('skipping already grafted revision %d:%s '
4178 4178 '(%d:%s also has origin %d:%s)\n')
4179 4179 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4180 4180 revs.remove(ids[n])
4181 4181 elif ctx.hex() in ids:
4182 4182 r = ids[ctx.hex()]
4183 4183 ui.warn(_('skipping already grafted revision %d:%s '
4184 4184 '(was grafted from %d:%s)\n') %
4185 4185 (r, repo[r], rev, ctx))
4186 4186 revs.remove(r)
4187 4187 if not revs:
4188 4188 return -1
4189 4189
4190 4190 for pos, ctx in enumerate(repo.set("%ld", revs)):
4191 4191 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4192 4192 ctx.description().split('\n', 1)[0])
4193 4193 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4194 4194 if names:
4195 4195 desc += ' (%s)' % ' '.join(names)
4196 4196 ui.status(_('grafting %s\n') % desc)
4197 4197 if opts.get('dry_run'):
4198 4198 continue
4199 4199
4200 4200 source = ctx.extra().get('source')
4201 4201 extra = {}
4202 4202 if source:
4203 4203 extra['source'] = source
4204 4204 extra['intermediate-source'] = ctx.hex()
4205 4205 else:
4206 4206 extra['source'] = ctx.hex()
4207 4207 user = ctx.user()
4208 4208 if opts.get('user'):
4209 4209 user = opts['user']
4210 4210 date = ctx.date()
4211 4211 if opts.get('date'):
4212 4212 date = opts['date']
4213 4213 message = ctx.description()
4214 4214 if opts.get('log'):
4215 4215 message += '\n(grafted from %s)' % ctx.hex()
4216 4216
4217 4217 # we don't merge the first commit when continuing
4218 4218 if not cont:
4219 4219 # perform the graft merge with p1(rev) as 'ancestor'
4220 4220 try:
4221 4221 # ui.forcemerge is an internal variable, do not document
4222 4222 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4223 4223 'graft')
4224 4224 stats = mergemod.graft(repo, ctx, ctx.p1(),
4225 4225 ['local', 'graft'])
4226 4226 finally:
4227 4227 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4228 4228 # report any conflicts
4229 4229 if stats and stats[3] > 0:
4230 4230 # write out state for --continue
4231 4231 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4232 4232 repo.vfs.write('graftstate', ''.join(nodelines))
4233 4233 extra = ''
4234 4234 if opts.get('user'):
4235 4235 extra += ' --user %s' % util.shellquote(opts['user'])
4236 4236 if opts.get('date'):
4237 4237 extra += ' --date %s' % util.shellquote(opts['date'])
4238 4238 if opts.get('log'):
4239 4239 extra += ' --log'
4240 4240 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4241 4241 raise error.Abort(
4242 4242 _("unresolved conflicts, can't continue"),
4243 4243 hint=hint)
4244 4244 else:
4245 4245 cont = False
4246 4246
4247 4247 # commit
4248 4248 node = repo.commit(text=message, user=user,
4249 4249 date=date, extra=extra, editor=editor)
4250 4250 if node is None:
4251 4251 ui.warn(
4252 4252 _('note: graft of %d:%s created no changes to commit\n') %
4253 4253 (ctx.rev(), ctx))
4254 4254
4255 4255 # remove state when we complete successfully
4256 4256 if not opts.get('dry_run'):
4257 4257 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4258 4258
4259 4259 return 0
4260 4260
4261 4261 @command('grep',
4262 4262 [('0', 'print0', None, _('end fields with NUL')),
4263 4263 ('', 'all', None, _('print all revisions that match')),
4264 4264 ('a', 'text', None, _('treat all files as text')),
4265 4265 ('f', 'follow', None,
4266 4266 _('follow changeset history,'
4267 4267 ' or file history across copies and renames')),
4268 4268 ('i', 'ignore-case', None, _('ignore case when matching')),
4269 4269 ('l', 'files-with-matches', None,
4270 4270 _('print only filenames and revisions that match')),
4271 4271 ('n', 'line-number', None, _('print matching line numbers')),
4272 4272 ('r', 'rev', [],
4273 4273 _('only search files changed within revision range'), _('REV')),
4274 4274 ('u', 'user', None, _('list the author (long with -v)')),
4275 4275 ('d', 'date', None, _('list the date (short with -q)')),
4276 4276 ] + walkopts,
4277 4277 _('[OPTION]... PATTERN [FILE]...'),
4278 4278 inferrepo=True)
4279 4279 def grep(ui, repo, pattern, *pats, **opts):
4280 4280 """search for a pattern in specified files and revisions
4281 4281
4282 4282 Search revisions of files for a regular expression.
4283 4283
4284 4284 This command behaves differently than Unix grep. It only accepts
4285 4285 Python/Perl regexps. It searches repository history, not the
4286 4286 working directory. It always prints the revision number in which a
4287 4287 match appears.
4288 4288
4289 4289 By default, grep only prints output for the first revision of a
4290 4290 file in which it finds a match. To get it to print every revision
4291 4291 that contains a change in match status ("-" for a match that
4292 4292 becomes a non-match, or "+" for a non-match that becomes a match),
4293 4293 use the --all flag.
4294 4294
4295 4295 Returns 0 if a match is found, 1 otherwise.
4296 4296 """
4297 4297 reflags = re.M
4298 4298 if opts.get('ignore_case'):
4299 4299 reflags |= re.I
4300 4300 try:
4301 4301 regexp = util.re.compile(pattern, reflags)
4302 4302 except re.error as inst:
4303 4303 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4304 4304 return 1
4305 4305 sep, eol = ':', '\n'
4306 4306 if opts.get('print0'):
4307 4307 sep = eol = '\0'
4308 4308
4309 4309 getfile = util.lrucachefunc(repo.file)
4310 4310
4311 4311 def matchlines(body):
4312 4312 begin = 0
4313 4313 linenum = 0
4314 4314 while begin < len(body):
4315 4315 match = regexp.search(body, begin)
4316 4316 if not match:
4317 4317 break
4318 4318 mstart, mend = match.span()
4319 4319 linenum += body.count('\n', begin, mstart) + 1
4320 4320 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4321 4321 begin = body.find('\n', mend) + 1 or len(body) + 1
4322 4322 lend = begin - 1
4323 4323 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4324 4324
4325 4325 class linestate(object):
4326 4326 def __init__(self, line, linenum, colstart, colend):
4327 4327 self.line = line
4328 4328 self.linenum = linenum
4329 4329 self.colstart = colstart
4330 4330 self.colend = colend
4331 4331
4332 4332 def __hash__(self):
4333 4333 return hash((self.linenum, self.line))
4334 4334
4335 4335 def __eq__(self, other):
4336 4336 return self.line == other.line
4337 4337
4338 4338 def __iter__(self):
4339 4339 yield (self.line[:self.colstart], '')
4340 4340 yield (self.line[self.colstart:self.colend], 'grep.match')
4341 4341 rest = self.line[self.colend:]
4342 4342 while rest != '':
4343 4343 match = regexp.search(rest)
4344 4344 if not match:
4345 4345 yield (rest, '')
4346 4346 break
4347 4347 mstart, mend = match.span()
4348 4348 yield (rest[:mstart], '')
4349 4349 yield (rest[mstart:mend], 'grep.match')
4350 4350 rest = rest[mend:]
4351 4351
4352 4352 matches = {}
4353 4353 copies = {}
4354 4354 def grepbody(fn, rev, body):
4355 4355 matches[rev].setdefault(fn, [])
4356 4356 m = matches[rev][fn]
4357 4357 for lnum, cstart, cend, line in matchlines(body):
4358 4358 s = linestate(line, lnum, cstart, cend)
4359 4359 m.append(s)
4360 4360
4361 4361 def difflinestates(a, b):
4362 4362 sm = difflib.SequenceMatcher(None, a, b)
4363 4363 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4364 4364 if tag == 'insert':
4365 4365 for i in xrange(blo, bhi):
4366 4366 yield ('+', b[i])
4367 4367 elif tag == 'delete':
4368 4368 for i in xrange(alo, ahi):
4369 4369 yield ('-', a[i])
4370 4370 elif tag == 'replace':
4371 4371 for i in xrange(alo, ahi):
4372 4372 yield ('-', a[i])
4373 4373 for i in xrange(blo, bhi):
4374 4374 yield ('+', b[i])
4375 4375
4376 4376 def display(fn, ctx, pstates, states):
4377 4377 rev = ctx.rev()
4378 4378 if ui.quiet:
4379 4379 datefunc = util.shortdate
4380 4380 else:
4381 4381 datefunc = util.datestr
4382 4382 found = False
4383 4383 @util.cachefunc
4384 4384 def binary():
4385 4385 flog = getfile(fn)
4386 4386 return util.binary(flog.read(ctx.filenode(fn)))
4387 4387
4388 4388 if opts.get('all'):
4389 4389 iter = difflinestates(pstates, states)
4390 4390 else:
4391 4391 iter = [('', l) for l in states]
4392 4392 for change, l in iter:
4393 4393 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4394 4394
4395 4395 if opts.get('line_number'):
4396 4396 cols.append((str(l.linenum), 'grep.linenumber'))
4397 4397 if opts.get('all'):
4398 4398 cols.append((change, 'grep.change'))
4399 4399 if opts.get('user'):
4400 4400 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4401 4401 if opts.get('date'):
4402 4402 cols.append((datefunc(ctx.date()), 'grep.date'))
4403 4403 for col, label in cols[:-1]:
4404 4404 ui.write(col, label=label)
4405 4405 ui.write(sep, label='grep.sep')
4406 4406 ui.write(cols[-1][0], label=cols[-1][1])
4407 4407 if not opts.get('files_with_matches'):
4408 4408 ui.write(sep, label='grep.sep')
4409 4409 if not opts.get('text') and binary():
4410 4410 ui.write(_(" Binary file matches"))
4411 4411 else:
4412 4412 for s, label in l:
4413 4413 ui.write(s, label=label)
4414 4414 ui.write(eol)
4415 4415 found = True
4416 4416 if opts.get('files_with_matches'):
4417 4417 break
4418 4418 return found
4419 4419
4420 4420 skip = {}
4421 4421 revfiles = {}
4422 4422 matchfn = scmutil.match(repo[None], pats, opts)
4423 4423 found = False
4424 4424 follow = opts.get('follow')
4425 4425
4426 4426 def prep(ctx, fns):
4427 4427 rev = ctx.rev()
4428 4428 pctx = ctx.p1()
4429 4429 parent = pctx.rev()
4430 4430 matches.setdefault(rev, {})
4431 4431 matches.setdefault(parent, {})
4432 4432 files = revfiles.setdefault(rev, [])
4433 4433 for fn in fns:
4434 4434 flog = getfile(fn)
4435 4435 try:
4436 4436 fnode = ctx.filenode(fn)
4437 4437 except error.LookupError:
4438 4438 continue
4439 4439
4440 4440 copied = flog.renamed(fnode)
4441 4441 copy = follow and copied and copied[0]
4442 4442 if copy:
4443 4443 copies.setdefault(rev, {})[fn] = copy
4444 4444 if fn in skip:
4445 4445 if copy:
4446 4446 skip[copy] = True
4447 4447 continue
4448 4448 files.append(fn)
4449 4449
4450 4450 if fn not in matches[rev]:
4451 4451 grepbody(fn, rev, flog.read(fnode))
4452 4452
4453 4453 pfn = copy or fn
4454 4454 if pfn not in matches[parent]:
4455 4455 try:
4456 4456 fnode = pctx.filenode(pfn)
4457 4457 grepbody(pfn, parent, flog.read(fnode))
4458 4458 except error.LookupError:
4459 4459 pass
4460 4460
4461 4461 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4462 4462 rev = ctx.rev()
4463 4463 parent = ctx.p1().rev()
4464 4464 for fn in sorted(revfiles.get(rev, [])):
4465 4465 states = matches[rev][fn]
4466 4466 copy = copies.get(rev, {}).get(fn)
4467 4467 if fn in skip:
4468 4468 if copy:
4469 4469 skip[copy] = True
4470 4470 continue
4471 4471 pstates = matches.get(parent, {}).get(copy or fn, [])
4472 4472 if pstates or states:
4473 4473 r = display(fn, ctx, pstates, states)
4474 4474 found = found or r
4475 4475 if r and not opts.get('all'):
4476 4476 skip[fn] = True
4477 4477 if copy:
4478 4478 skip[copy] = True
4479 4479 del matches[rev]
4480 4480 del revfiles[rev]
4481 4481
4482 4482 return not found
4483 4483
4484 4484 @command('heads',
4485 4485 [('r', 'rev', '',
4486 4486 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4487 4487 ('t', 'topo', False, _('show topological heads only')),
4488 4488 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4489 4489 ('c', 'closed', False, _('show normal and closed branch heads')),
4490 4490 ] + templateopts,
4491 4491 _('[-ct] [-r STARTREV] [REV]...'))
4492 4492 def heads(ui, repo, *branchrevs, **opts):
4493 4493 """show branch heads
4494 4494
4495 4495 With no arguments, show all open branch heads in the repository.
4496 4496 Branch heads are changesets that have no descendants on the
4497 4497 same branch. They are where development generally takes place and
4498 4498 are the usual targets for update and merge operations.
4499 4499
4500 4500 If one or more REVs are given, only open branch heads on the
4501 4501 branches associated with the specified changesets are shown. This
4502 4502 means that you can use :hg:`heads .` to see the heads on the
4503 4503 currently checked-out branch.
4504 4504
4505 4505 If -c/--closed is specified, also show branch heads marked closed
4506 4506 (see :hg:`commit --close-branch`).
4507 4507
4508 4508 If STARTREV is specified, only those heads that are descendants of
4509 4509 STARTREV will be displayed.
4510 4510
4511 4511 If -t/--topo is specified, named branch mechanics will be ignored and only
4512 4512 topological heads (changesets with no children) will be shown.
4513 4513
4514 4514 Returns 0 if matching heads are found, 1 if not.
4515 4515 """
4516 4516
4517 4517 start = None
4518 4518 if 'rev' in opts:
4519 4519 start = scmutil.revsingle(repo, opts['rev'], None).node()
4520 4520
4521 4521 if opts.get('topo'):
4522 4522 heads = [repo[h] for h in repo.heads(start)]
4523 4523 else:
4524 4524 heads = []
4525 4525 for branch in repo.branchmap():
4526 4526 heads += repo.branchheads(branch, start, opts.get('closed'))
4527 4527 heads = [repo[h] for h in heads]
4528 4528
4529 4529 if branchrevs:
4530 4530 branches = set(repo[br].branch() for br in branchrevs)
4531 4531 heads = [h for h in heads if h.branch() in branches]
4532 4532
4533 4533 if opts.get('active') and branchrevs:
4534 4534 dagheads = repo.heads(start)
4535 4535 heads = [h for h in heads if h.node() in dagheads]
4536 4536
4537 4537 if branchrevs:
4538 4538 haveheads = set(h.branch() for h in heads)
4539 4539 if branches - haveheads:
4540 4540 headless = ', '.join(b for b in branches - haveheads)
4541 4541 msg = _('no open branch heads found on branches %s')
4542 4542 if opts.get('rev'):
4543 4543 msg += _(' (started at %s)') % opts['rev']
4544 4544 ui.warn((msg + '\n') % headless)
4545 4545
4546 4546 if not heads:
4547 4547 return 1
4548 4548
4549 4549 heads = sorted(heads, key=lambda x: -x.rev())
4550 4550 displayer = cmdutil.show_changeset(ui, repo, opts)
4551 4551 for ctx in heads:
4552 4552 displayer.show(ctx)
4553 4553 displayer.close()
4554 4554
4555 4555 @command('help',
4556 4556 [('e', 'extension', None, _('show only help for extensions')),
4557 4557 ('c', 'command', None, _('show only help for commands')),
4558 4558 ('k', 'keyword', None, _('show topics matching keyword')),
4559 4559 ('s', 'system', [], _('show help for specific platform(s)')),
4560 4560 ],
4561 4561 _('[-ecks] [TOPIC]'),
4562 4562 norepo=True)
4563 4563 def help_(ui, name=None, **opts):
4564 4564 """show help for a given topic or a help overview
4565 4565
4566 4566 With no arguments, print a list of commands with short help messages.
4567 4567
4568 4568 Given a topic, extension, or command name, print help for that
4569 4569 topic.
4570 4570
4571 4571 Returns 0 if successful.
4572 4572 """
4573 4573
4574 4574 textwidth = ui.configint('ui', 'textwidth', 78)
4575 4575 termwidth = ui.termwidth() - 2
4576 4576 if textwidth <= 0 or termwidth < textwidth:
4577 4577 textwidth = termwidth
4578 4578
4579 4579 keep = opts.get('system') or []
4580 4580 if len(keep) == 0:
4581 4581 if sys.platform.startswith('win'):
4582 4582 keep.append('windows')
4583 4583 elif sys.platform == 'OpenVMS':
4584 4584 keep.append('vms')
4585 4585 elif sys.platform == 'plan9':
4586 4586 keep.append('plan9')
4587 4587 else:
4588 4588 keep.append('unix')
4589 4589 keep.append(sys.platform.lower())
4590 4590 if ui.verbose:
4591 4591 keep.append('verbose')
4592 4592
4593 4593 section = None
4594 4594 subtopic = None
4595 4595 if name and '.' in name:
4596 name, section = name.split('.', 1)
4597 section = encoding.lower(section)
4598 if '.' in section:
4599 subtopic, section = section.split('.', 1)
4596 name, remaining = name.split('.', 1)
4597 remaining = encoding.lower(remaining)
4598 if '.' in remaining:
4599 subtopic, section = remaining.split('.', 1)
4600 4600 else:
4601 subtopic = section
4601 if name in help.subtopics:
4602 subtopic = remaining
4603 else:
4604 section = remaining
4602 4605
4603 4606 text = help.help_(ui, name, subtopic=subtopic, **opts)
4604 4607
4605 4608 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4606 4609 section=section)
4607 4610
4608 4611 # We could have been given a weird ".foo" section without a name
4609 4612 # to look for, or we could have simply failed to found "foo.bar"
4610 4613 # because bar isn't a section of foo
4611 4614 if section and not (formatted and name):
4612 4615 raise error.Abort(_("help section not found"))
4613 4616
4614 4617 if 'verbose' in pruned:
4615 4618 keep.append('omitted')
4616 4619 else:
4617 4620 keep.append('notomitted')
4618 4621 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4619 4622 section=section)
4620 4623 ui.write(formatted)
4621 4624
4622 4625
4623 4626 @command('identify|id',
4624 4627 [('r', 'rev', '',
4625 4628 _('identify the specified revision'), _('REV')),
4626 4629 ('n', 'num', None, _('show local revision number')),
4627 4630 ('i', 'id', None, _('show global revision id')),
4628 4631 ('b', 'branch', None, _('show branch')),
4629 4632 ('t', 'tags', None, _('show tags')),
4630 4633 ('B', 'bookmarks', None, _('show bookmarks')),
4631 4634 ] + remoteopts,
4632 4635 _('[-nibtB] [-r REV] [SOURCE]'),
4633 4636 optionalrepo=True)
4634 4637 def identify(ui, repo, source=None, rev=None,
4635 4638 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4636 4639 """identify the working directory or specified revision
4637 4640
4638 4641 Print a summary identifying the repository state at REV using one or
4639 4642 two parent hash identifiers, followed by a "+" if the working
4640 4643 directory has uncommitted changes, the branch name (if not default),
4641 4644 a list of tags, and a list of bookmarks.
4642 4645
4643 4646 When REV is not given, print a summary of the current state of the
4644 4647 repository.
4645 4648
4646 4649 Specifying a path to a repository root or Mercurial bundle will
4647 4650 cause lookup to operate on that repository/bundle.
4648 4651
4649 4652 .. container:: verbose
4650 4653
4651 4654 Examples:
4652 4655
4653 4656 - generate a build identifier for the working directory::
4654 4657
4655 4658 hg id --id > build-id.dat
4656 4659
4657 4660 - find the revision corresponding to a tag::
4658 4661
4659 4662 hg id -n -r 1.3
4660 4663
4661 4664 - check the most recent revision of a remote repository::
4662 4665
4663 4666 hg id -r tip http://selenic.com/hg/
4664 4667
4665 4668 See :hg:`log` for generating more information about specific revisions,
4666 4669 including full hash identifiers.
4667 4670
4668 4671 Returns 0 if successful.
4669 4672 """
4670 4673
4671 4674 if not repo and not source:
4672 4675 raise error.Abort(_("there is no Mercurial repository here "
4673 4676 "(.hg not found)"))
4674 4677
4675 4678 if ui.debugflag:
4676 4679 hexfunc = hex
4677 4680 else:
4678 4681 hexfunc = short
4679 4682 default = not (num or id or branch or tags or bookmarks)
4680 4683 output = []
4681 4684 revs = []
4682 4685
4683 4686 if source:
4684 4687 source, branches = hg.parseurl(ui.expandpath(source))
4685 4688 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4686 4689 repo = peer.local()
4687 4690 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4688 4691
4689 4692 if not repo:
4690 4693 if num or branch or tags:
4691 4694 raise error.Abort(
4692 4695 _("can't query remote revision number, branch, or tags"))
4693 4696 if not rev and revs:
4694 4697 rev = revs[0]
4695 4698 if not rev:
4696 4699 rev = "tip"
4697 4700
4698 4701 remoterev = peer.lookup(rev)
4699 4702 if default or id:
4700 4703 output = [hexfunc(remoterev)]
4701 4704
4702 4705 def getbms():
4703 4706 bms = []
4704 4707
4705 4708 if 'bookmarks' in peer.listkeys('namespaces'):
4706 4709 hexremoterev = hex(remoterev)
4707 4710 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4708 4711 if bmr == hexremoterev]
4709 4712
4710 4713 return sorted(bms)
4711 4714
4712 4715 if bookmarks:
4713 4716 output.extend(getbms())
4714 4717 elif default and not ui.quiet:
4715 4718 # multiple bookmarks for a single parent separated by '/'
4716 4719 bm = '/'.join(getbms())
4717 4720 if bm:
4718 4721 output.append(bm)
4719 4722 else:
4720 4723 ctx = scmutil.revsingle(repo, rev, None)
4721 4724
4722 4725 if ctx.rev() is None:
4723 4726 ctx = repo[None]
4724 4727 parents = ctx.parents()
4725 4728 taglist = []
4726 4729 for p in parents:
4727 4730 taglist.extend(p.tags())
4728 4731
4729 4732 changed = ""
4730 4733 if default or id or num:
4731 4734 if (any(repo.status())
4732 4735 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4733 4736 changed = '+'
4734 4737 if default or id:
4735 4738 output = ["%s%s" %
4736 4739 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4737 4740 if num:
4738 4741 output.append("%s%s" %
4739 4742 ('+'.join([str(p.rev()) for p in parents]), changed))
4740 4743 else:
4741 4744 if default or id:
4742 4745 output = [hexfunc(ctx.node())]
4743 4746 if num:
4744 4747 output.append(str(ctx.rev()))
4745 4748 taglist = ctx.tags()
4746 4749
4747 4750 if default and not ui.quiet:
4748 4751 b = ctx.branch()
4749 4752 if b != 'default':
4750 4753 output.append("(%s)" % b)
4751 4754
4752 4755 # multiple tags for a single parent separated by '/'
4753 4756 t = '/'.join(taglist)
4754 4757 if t:
4755 4758 output.append(t)
4756 4759
4757 4760 # multiple bookmarks for a single parent separated by '/'
4758 4761 bm = '/'.join(ctx.bookmarks())
4759 4762 if bm:
4760 4763 output.append(bm)
4761 4764 else:
4762 4765 if branch:
4763 4766 output.append(ctx.branch())
4764 4767
4765 4768 if tags:
4766 4769 output.extend(taglist)
4767 4770
4768 4771 if bookmarks:
4769 4772 output.extend(ctx.bookmarks())
4770 4773
4771 4774 ui.write("%s\n" % ' '.join(output))
4772 4775
4773 4776 @command('import|patch',
4774 4777 [('p', 'strip', 1,
4775 4778 _('directory strip option for patch. This has the same '
4776 4779 'meaning as the corresponding patch option'), _('NUM')),
4777 4780 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4778 4781 ('e', 'edit', False, _('invoke editor on commit messages')),
4779 4782 ('f', 'force', None,
4780 4783 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4781 4784 ('', 'no-commit', None,
4782 4785 _("don't commit, just update the working directory")),
4783 4786 ('', 'bypass', None,
4784 4787 _("apply patch without touching the working directory")),
4785 4788 ('', 'partial', None,
4786 4789 _('commit even if some hunks fail')),
4787 4790 ('', 'exact', None,
4788 4791 _('abort if patch would apply lossily')),
4789 4792 ('', 'prefix', '',
4790 4793 _('apply patch to subdirectory'), _('DIR')),
4791 4794 ('', 'import-branch', None,
4792 4795 _('use any branch information in patch (implied by --exact)'))] +
4793 4796 commitopts + commitopts2 + similarityopts,
4794 4797 _('[OPTION]... PATCH...'))
4795 4798 def import_(ui, repo, patch1=None, *patches, **opts):
4796 4799 """import an ordered set of patches
4797 4800
4798 4801 Import a list of patches and commit them individually (unless
4799 4802 --no-commit is specified).
4800 4803
4801 4804 To read a patch from standard input, use "-" as the patch name. If
4802 4805 a URL is specified, the patch will be downloaded from there.
4803 4806
4804 4807 Import first applies changes to the working directory (unless
4805 4808 --bypass is specified), import will abort if there are outstanding
4806 4809 changes.
4807 4810
4808 4811 Use --bypass to apply and commit patches directly to the
4809 4812 repository, without affecting the working directory. Without
4810 4813 --exact, patches will be applied on top of the working directory
4811 4814 parent revision.
4812 4815
4813 4816 You can import a patch straight from a mail message. Even patches
4814 4817 as attachments work (to use the body part, it must have type
4815 4818 text/plain or text/x-patch). From and Subject headers of email
4816 4819 message are used as default committer and commit message. All
4817 4820 text/plain body parts before first diff are added to the commit
4818 4821 message.
4819 4822
4820 4823 If the imported patch was generated by :hg:`export`, user and
4821 4824 description from patch override values from message headers and
4822 4825 body. Values given on command line with -m/--message and -u/--user
4823 4826 override these.
4824 4827
4825 4828 If --exact is specified, import will set the working directory to
4826 4829 the parent of each patch before applying it, and will abort if the
4827 4830 resulting changeset has a different ID than the one recorded in
4828 4831 the patch. This will guard against various ways that portable
4829 4832 patch formats and mail systems might fail to transfer Mercurial
4830 4833 data or metadata. See :hg:`bundle` for lossless transmission.
4831 4834
4832 4835 Use --partial to ensure a changeset will be created from the patch
4833 4836 even if some hunks fail to apply. Hunks that fail to apply will be
4834 4837 written to a <target-file>.rej file. Conflicts can then be resolved
4835 4838 by hand before :hg:`commit --amend` is run to update the created
4836 4839 changeset. This flag exists to let people import patches that
4837 4840 partially apply without losing the associated metadata (author,
4838 4841 date, description, ...).
4839 4842
4840 4843 .. note::
4841 4844
4842 4845 When no hunks apply cleanly, :hg:`import --partial` will create
4843 4846 an empty changeset, importing only the patch metadata.
4844 4847
4845 4848 With -s/--similarity, hg will attempt to discover renames and
4846 4849 copies in the patch in the same way as :hg:`addremove`.
4847 4850
4848 4851 It is possible to use external patch programs to perform the patch
4849 4852 by setting the ``ui.patch`` configuration option. For the default
4850 4853 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4851 4854 See :hg:`help config` for more information about configuration
4852 4855 files and how to use these options.
4853 4856
4854 4857 See :hg:`help dates` for a list of formats valid for -d/--date.
4855 4858
4856 4859 .. container:: verbose
4857 4860
4858 4861 Examples:
4859 4862
4860 4863 - import a traditional patch from a website and detect renames::
4861 4864
4862 4865 hg import -s 80 http://example.com/bugfix.patch
4863 4866
4864 4867 - import a changeset from an hgweb server::
4865 4868
4866 4869 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4867 4870
4868 4871 - import all the patches in an Unix-style mbox::
4869 4872
4870 4873 hg import incoming-patches.mbox
4871 4874
4872 4875 - attempt to exactly restore an exported changeset (not always
4873 4876 possible)::
4874 4877
4875 4878 hg import --exact proposed-fix.patch
4876 4879
4877 4880 - use an external tool to apply a patch which is too fuzzy for
4878 4881 the default internal tool.
4879 4882
4880 4883 hg import --config ui.patch="patch --merge" fuzzy.patch
4881 4884
4882 4885 - change the default fuzzing from 2 to a less strict 7
4883 4886
4884 4887 hg import --config ui.fuzz=7 fuzz.patch
4885 4888
4886 4889 Returns 0 on success, 1 on partial success (see --partial).
4887 4890 """
4888 4891
4889 4892 if not patch1:
4890 4893 raise error.Abort(_('need at least one patch to import'))
4891 4894
4892 4895 patches = (patch1,) + patches
4893 4896
4894 4897 date = opts.get('date')
4895 4898 if date:
4896 4899 opts['date'] = util.parsedate(date)
4897 4900
4898 4901 exact = opts.get('exact')
4899 4902 update = not opts.get('bypass')
4900 4903 if not update and opts.get('no_commit'):
4901 4904 raise error.Abort(_('cannot use --no-commit with --bypass'))
4902 4905 try:
4903 4906 sim = float(opts.get('similarity') or 0)
4904 4907 except ValueError:
4905 4908 raise error.Abort(_('similarity must be a number'))
4906 4909 if sim < 0 or sim > 100:
4907 4910 raise error.Abort(_('similarity must be between 0 and 100'))
4908 4911 if sim and not update:
4909 4912 raise error.Abort(_('cannot use --similarity with --bypass'))
4910 4913 if exact:
4911 4914 if opts.get('edit'):
4912 4915 raise error.Abort(_('cannot use --exact with --edit'))
4913 4916 if opts.get('prefix'):
4914 4917 raise error.Abort(_('cannot use --exact with --prefix'))
4915 4918
4916 4919 base = opts["base"]
4917 4920 wlock = dsguard = lock = tr = None
4918 4921 msgs = []
4919 4922 ret = 0
4920 4923
4921 4924
4922 4925 try:
4923 4926 wlock = repo.wlock()
4924 4927
4925 4928 if update:
4926 4929 cmdutil.checkunfinished(repo)
4927 4930 if (exact or not opts.get('force')):
4928 4931 cmdutil.bailifchanged(repo)
4929 4932
4930 4933 if not opts.get('no_commit'):
4931 4934 lock = repo.lock()
4932 4935 tr = repo.transaction('import')
4933 4936 else:
4934 4937 dsguard = cmdutil.dirstateguard(repo, 'import')
4935 4938 parents = repo[None].parents()
4936 4939 for patchurl in patches:
4937 4940 if patchurl == '-':
4938 4941 ui.status(_('applying patch from stdin\n'))
4939 4942 patchfile = ui.fin
4940 4943 patchurl = 'stdin' # for error message
4941 4944 else:
4942 4945 patchurl = os.path.join(base, patchurl)
4943 4946 ui.status(_('applying %s\n') % patchurl)
4944 4947 patchfile = hg.openpath(ui, patchurl)
4945 4948
4946 4949 haspatch = False
4947 4950 for hunk in patch.split(patchfile):
4948 4951 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4949 4952 parents, opts,
4950 4953 msgs, hg.clean)
4951 4954 if msg:
4952 4955 haspatch = True
4953 4956 ui.note(msg + '\n')
4954 4957 if update or exact:
4955 4958 parents = repo[None].parents()
4956 4959 else:
4957 4960 parents = [repo[node]]
4958 4961 if rej:
4959 4962 ui.write_err(_("patch applied partially\n"))
4960 4963 ui.write_err(_("(fix the .rej files and run "
4961 4964 "`hg commit --amend`)\n"))
4962 4965 ret = 1
4963 4966 break
4964 4967
4965 4968 if not haspatch:
4966 4969 raise error.Abort(_('%s: no diffs found') % patchurl)
4967 4970
4968 4971 if tr:
4969 4972 tr.close()
4970 4973 if msgs:
4971 4974 repo.savecommitmessage('\n* * *\n'.join(msgs))
4972 4975 if dsguard:
4973 4976 dsguard.close()
4974 4977 return ret
4975 4978 finally:
4976 4979 if tr:
4977 4980 tr.release()
4978 4981 release(lock, dsguard, wlock)
4979 4982
4980 4983 @command('incoming|in',
4981 4984 [('f', 'force', None,
4982 4985 _('run even if remote repository is unrelated')),
4983 4986 ('n', 'newest-first', None, _('show newest record first')),
4984 4987 ('', 'bundle', '',
4985 4988 _('file to store the bundles into'), _('FILE')),
4986 4989 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4987 4990 ('B', 'bookmarks', False, _("compare bookmarks")),
4988 4991 ('b', 'branch', [],
4989 4992 _('a specific branch you would like to pull'), _('BRANCH')),
4990 4993 ] + logopts + remoteopts + subrepoopts,
4991 4994 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4992 4995 def incoming(ui, repo, source="default", **opts):
4993 4996 """show new changesets found in source
4994 4997
4995 4998 Show new changesets found in the specified path/URL or the default
4996 4999 pull location. These are the changesets that would have been pulled
4997 5000 if a pull at the time you issued this command.
4998 5001
4999 5002 See pull for valid source format details.
5000 5003
5001 5004 .. container:: verbose
5002 5005
5003 5006 With -B/--bookmarks, the result of bookmark comparison between
5004 5007 local and remote repositories is displayed. With -v/--verbose,
5005 5008 status is also displayed for each bookmark like below::
5006 5009
5007 5010 BM1 01234567890a added
5008 5011 BM2 1234567890ab advanced
5009 5012 BM3 234567890abc diverged
5010 5013 BM4 34567890abcd changed
5011 5014
5012 5015 The action taken locally when pulling depends on the
5013 5016 status of each bookmark:
5014 5017
5015 5018 :``added``: pull will create it
5016 5019 :``advanced``: pull will update it
5017 5020 :``diverged``: pull will create a divergent bookmark
5018 5021 :``changed``: result depends on remote changesets
5019 5022
5020 5023 From the point of view of pulling behavior, bookmark
5021 5024 existing only in the remote repository are treated as ``added``,
5022 5025 even if it is in fact locally deleted.
5023 5026
5024 5027 .. container:: verbose
5025 5028
5026 5029 For remote repository, using --bundle avoids downloading the
5027 5030 changesets twice if the incoming is followed by a pull.
5028 5031
5029 5032 Examples:
5030 5033
5031 5034 - show incoming changes with patches and full description::
5032 5035
5033 5036 hg incoming -vp
5034 5037
5035 5038 - show incoming changes excluding merges, store a bundle::
5036 5039
5037 5040 hg in -vpM --bundle incoming.hg
5038 5041 hg pull incoming.hg
5039 5042
5040 5043 - briefly list changes inside a bundle::
5041 5044
5042 5045 hg in changes.hg -T "{desc|firstline}\\n"
5043 5046
5044 5047 Returns 0 if there are incoming changes, 1 otherwise.
5045 5048 """
5046 5049 if opts.get('graph'):
5047 5050 cmdutil.checkunsupportedgraphflags([], opts)
5048 5051 def display(other, chlist, displayer):
5049 5052 revdag = cmdutil.graphrevs(other, chlist, opts)
5050 5053 cmdutil.displaygraph(ui, repo, revdag, displayer,
5051 5054 graphmod.asciiedges)
5052 5055
5053 5056 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5054 5057 return 0
5055 5058
5056 5059 if opts.get('bundle') and opts.get('subrepos'):
5057 5060 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5058 5061
5059 5062 if opts.get('bookmarks'):
5060 5063 source, branches = hg.parseurl(ui.expandpath(source),
5061 5064 opts.get('branch'))
5062 5065 other = hg.peer(repo, opts, source)
5063 5066 if 'bookmarks' not in other.listkeys('namespaces'):
5064 5067 ui.warn(_("remote doesn't support bookmarks\n"))
5065 5068 return 0
5066 5069 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5067 5070 return bookmarks.incoming(ui, repo, other)
5068 5071
5069 5072 repo._subtoppath = ui.expandpath(source)
5070 5073 try:
5071 5074 return hg.incoming(ui, repo, source, opts)
5072 5075 finally:
5073 5076 del repo._subtoppath
5074 5077
5075 5078
5076 5079 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5077 5080 norepo=True)
5078 5081 def init(ui, dest=".", **opts):
5079 5082 """create a new repository in the given directory
5080 5083
5081 5084 Initialize a new repository in the given directory. If the given
5082 5085 directory does not exist, it will be created.
5083 5086
5084 5087 If no directory is given, the current directory is used.
5085 5088
5086 5089 It is possible to specify an ``ssh://`` URL as the destination.
5087 5090 See :hg:`help urls` for more information.
5088 5091
5089 5092 Returns 0 on success.
5090 5093 """
5091 5094 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5092 5095
5093 5096 @command('locate',
5094 5097 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5095 5098 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5096 5099 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5097 5100 ] + walkopts,
5098 5101 _('[OPTION]... [PATTERN]...'))
5099 5102 def locate(ui, repo, *pats, **opts):
5100 5103 """locate files matching specific patterns (DEPRECATED)
5101 5104
5102 5105 Print files under Mercurial control in the working directory whose
5103 5106 names match the given patterns.
5104 5107
5105 5108 By default, this command searches all directories in the working
5106 5109 directory. To search just the current directory and its
5107 5110 subdirectories, use "--include .".
5108 5111
5109 5112 If no patterns are given to match, this command prints the names
5110 5113 of all files under Mercurial control in the working directory.
5111 5114
5112 5115 If you want to feed the output of this command into the "xargs"
5113 5116 command, use the -0 option to both this command and "xargs". This
5114 5117 will avoid the problem of "xargs" treating single filenames that
5115 5118 contain whitespace as multiple filenames.
5116 5119
5117 5120 See :hg:`help files` for a more versatile command.
5118 5121
5119 5122 Returns 0 if a match is found, 1 otherwise.
5120 5123 """
5121 5124 if opts.get('print0'):
5122 5125 end = '\0'
5123 5126 else:
5124 5127 end = '\n'
5125 5128 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5126 5129
5127 5130 ret = 1
5128 5131 ctx = repo[rev]
5129 5132 m = scmutil.match(ctx, pats, opts, default='relglob',
5130 5133 badfn=lambda x, y: False)
5131 5134
5132 5135 for abs in ctx.matches(m):
5133 5136 if opts.get('fullpath'):
5134 5137 ui.write(repo.wjoin(abs), end)
5135 5138 else:
5136 5139 ui.write(((pats and m.rel(abs)) or abs), end)
5137 5140 ret = 0
5138 5141
5139 5142 return ret
5140 5143
5141 5144 @command('^log|history',
5142 5145 [('f', 'follow', None,
5143 5146 _('follow changeset history, or file history across copies and renames')),
5144 5147 ('', 'follow-first', None,
5145 5148 _('only follow the first parent of merge changesets (DEPRECATED)')),
5146 5149 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5147 5150 ('C', 'copies', None, _('show copied files')),
5148 5151 ('k', 'keyword', [],
5149 5152 _('do case-insensitive search for a given text'), _('TEXT')),
5150 5153 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5151 5154 ('', 'removed', None, _('include revisions where files were removed')),
5152 5155 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5153 5156 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5154 5157 ('', 'only-branch', [],
5155 5158 _('show only changesets within the given named branch (DEPRECATED)'),
5156 5159 _('BRANCH')),
5157 5160 ('b', 'branch', [],
5158 5161 _('show changesets within the given named branch'), _('BRANCH')),
5159 5162 ('P', 'prune', [],
5160 5163 _('do not display revision or any of its ancestors'), _('REV')),
5161 5164 ] + logopts + walkopts,
5162 5165 _('[OPTION]... [FILE]'),
5163 5166 inferrepo=True)
5164 5167 def log(ui, repo, *pats, **opts):
5165 5168 """show revision history of entire repository or files
5166 5169
5167 5170 Print the revision history of the specified files or the entire
5168 5171 project.
5169 5172
5170 5173 If no revision range is specified, the default is ``tip:0`` unless
5171 5174 --follow is set, in which case the working directory parent is
5172 5175 used as the starting revision.
5173 5176
5174 5177 File history is shown without following rename or copy history of
5175 5178 files. Use -f/--follow with a filename to follow history across
5176 5179 renames and copies. --follow without a filename will only show
5177 5180 ancestors or descendants of the starting revision.
5178 5181
5179 5182 By default this command prints revision number and changeset id,
5180 5183 tags, non-trivial parents, user, date and time, and a summary for
5181 5184 each commit. When the -v/--verbose switch is used, the list of
5182 5185 changed files and full commit message are shown.
5183 5186
5184 5187 With --graph the revisions are shown as an ASCII art DAG with the most
5185 5188 recent changeset at the top.
5186 5189 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5187 5190 and '+' represents a fork where the changeset from the lines below is a
5188 5191 parent of the 'o' merge on the same line.
5189 5192
5190 5193 .. note::
5191 5194
5192 5195 :hg:`log --patch` may generate unexpected diff output for merge
5193 5196 changesets, as it will only compare the merge changeset against
5194 5197 its first parent. Also, only files different from BOTH parents
5195 5198 will appear in files:.
5196 5199
5197 5200 .. note::
5198 5201
5199 5202 For performance reasons, :hg:`log FILE` may omit duplicate changes
5200 5203 made on branches and will not show removals or mode changes. To
5201 5204 see all such changes, use the --removed switch.
5202 5205
5203 5206 .. container:: verbose
5204 5207
5205 5208 Some examples:
5206 5209
5207 5210 - changesets with full descriptions and file lists::
5208 5211
5209 5212 hg log -v
5210 5213
5211 5214 - changesets ancestral to the working directory::
5212 5215
5213 5216 hg log -f
5214 5217
5215 5218 - last 10 commits on the current branch::
5216 5219
5217 5220 hg log -l 10 -b .
5218 5221
5219 5222 - changesets showing all modifications of a file, including removals::
5220 5223
5221 5224 hg log --removed file.c
5222 5225
5223 5226 - all changesets that touch a directory, with diffs, excluding merges::
5224 5227
5225 5228 hg log -Mp lib/
5226 5229
5227 5230 - all revision numbers that match a keyword::
5228 5231
5229 5232 hg log -k bug --template "{rev}\\n"
5230 5233
5231 5234 - the full hash identifier of the working directory parent::
5232 5235
5233 5236 hg log -r . --template "{node}\\n"
5234 5237
5235 5238 - list available log templates::
5236 5239
5237 5240 hg log -T list
5238 5241
5239 5242 - check if a given changeset is included in a tagged release::
5240 5243
5241 5244 hg log -r "a21ccf and ancestor(1.9)"
5242 5245
5243 5246 - find all changesets by some user in a date range::
5244 5247
5245 5248 hg log -k alice -d "may 2008 to jul 2008"
5246 5249
5247 5250 - summary of all changesets after the last tag::
5248 5251
5249 5252 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5250 5253
5251 5254 See :hg:`help dates` for a list of formats valid for -d/--date.
5252 5255
5253 5256 See :hg:`help revisions` and :hg:`help revsets` for more about
5254 5257 specifying and ordering revisions.
5255 5258
5256 5259 See :hg:`help templates` for more about pre-packaged styles and
5257 5260 specifying custom templates.
5258 5261
5259 5262 Returns 0 on success.
5260 5263
5261 5264 """
5262 5265 if opts.get('follow') and opts.get('rev'):
5263 5266 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5264 5267 del opts['follow']
5265 5268
5266 5269 if opts.get('graph'):
5267 5270 return cmdutil.graphlog(ui, repo, *pats, **opts)
5268 5271
5269 5272 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5270 5273 limit = cmdutil.loglimit(opts)
5271 5274 count = 0
5272 5275
5273 5276 getrenamed = None
5274 5277 if opts.get('copies'):
5275 5278 endrev = None
5276 5279 if opts.get('rev'):
5277 5280 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5278 5281 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5279 5282
5280 5283 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5281 5284 for rev in revs:
5282 5285 if count == limit:
5283 5286 break
5284 5287 ctx = repo[rev]
5285 5288 copies = None
5286 5289 if getrenamed is not None and rev:
5287 5290 copies = []
5288 5291 for fn in ctx.files():
5289 5292 rename = getrenamed(fn, rev)
5290 5293 if rename:
5291 5294 copies.append((fn, rename[0]))
5292 5295 if filematcher:
5293 5296 revmatchfn = filematcher(ctx.rev())
5294 5297 else:
5295 5298 revmatchfn = None
5296 5299 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5297 5300 if displayer.flush(ctx):
5298 5301 count += 1
5299 5302
5300 5303 displayer.close()
5301 5304
5302 5305 @command('manifest',
5303 5306 [('r', 'rev', '', _('revision to display'), _('REV')),
5304 5307 ('', 'all', False, _("list files from all revisions"))]
5305 5308 + formatteropts,
5306 5309 _('[-r REV]'))
5307 5310 def manifest(ui, repo, node=None, rev=None, **opts):
5308 5311 """output the current or given revision of the project manifest
5309 5312
5310 5313 Print a list of version controlled files for the given revision.
5311 5314 If no revision is given, the first parent of the working directory
5312 5315 is used, or the null revision if no revision is checked out.
5313 5316
5314 5317 With -v, print file permissions, symlink and executable bits.
5315 5318 With --debug, print file revision hashes.
5316 5319
5317 5320 If option --all is specified, the list of all files from all revisions
5318 5321 is printed. This includes deleted and renamed files.
5319 5322
5320 5323 Returns 0 on success.
5321 5324 """
5322 5325
5323 5326 fm = ui.formatter('manifest', opts)
5324 5327
5325 5328 if opts.get('all'):
5326 5329 if rev or node:
5327 5330 raise error.Abort(_("can't specify a revision with --all"))
5328 5331
5329 5332 res = []
5330 5333 prefix = "data/"
5331 5334 suffix = ".i"
5332 5335 plen = len(prefix)
5333 5336 slen = len(suffix)
5334 5337 with repo.lock():
5335 5338 for fn, b, size in repo.store.datafiles():
5336 5339 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5337 5340 res.append(fn[plen:-slen])
5338 5341 for f in res:
5339 5342 fm.startitem()
5340 5343 fm.write("path", '%s\n', f)
5341 5344 fm.end()
5342 5345 return
5343 5346
5344 5347 if rev and node:
5345 5348 raise error.Abort(_("please specify just one revision"))
5346 5349
5347 5350 if not node:
5348 5351 node = rev
5349 5352
5350 5353 char = {'l': '@', 'x': '*', '': ''}
5351 5354 mode = {'l': '644', 'x': '755', '': '644'}
5352 5355 ctx = scmutil.revsingle(repo, node)
5353 5356 mf = ctx.manifest()
5354 5357 for f in ctx:
5355 5358 fm.startitem()
5356 5359 fl = ctx[f].flags()
5357 5360 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5358 5361 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5359 5362 fm.write('path', '%s\n', f)
5360 5363 fm.end()
5361 5364
5362 5365 @command('^merge',
5363 5366 [('f', 'force', None,
5364 5367 _('force a merge including outstanding changes (DEPRECATED)')),
5365 5368 ('r', 'rev', '', _('revision to merge'), _('REV')),
5366 5369 ('P', 'preview', None,
5367 5370 _('review revisions to merge (no merge is performed)'))
5368 5371 ] + mergetoolopts,
5369 5372 _('[-P] [[-r] REV]'))
5370 5373 def merge(ui, repo, node=None, **opts):
5371 5374 """merge another revision into working directory
5372 5375
5373 5376 The current working directory is updated with all changes made in
5374 5377 the requested revision since the last common predecessor revision.
5375 5378
5376 5379 Files that changed between either parent are marked as changed for
5377 5380 the next commit and a commit must be performed before any further
5378 5381 updates to the repository are allowed. The next commit will have
5379 5382 two parents.
5380 5383
5381 5384 ``--tool`` can be used to specify the merge tool used for file
5382 5385 merges. It overrides the HGMERGE environment variable and your
5383 5386 configuration files. See :hg:`help merge-tools` for options.
5384 5387
5385 5388 If no revision is specified, the working directory's parent is a
5386 5389 head revision, and the current branch contains exactly one other
5387 5390 head, the other head is merged with by default. Otherwise, an
5388 5391 explicit revision with which to merge with must be provided.
5389 5392
5390 5393 See :hg:`help resolve` for information on handling file conflicts.
5391 5394
5392 5395 To undo an uncommitted merge, use :hg:`update --clean .` which
5393 5396 will check out a clean copy of the original merge parent, losing
5394 5397 all changes.
5395 5398
5396 5399 Returns 0 on success, 1 if there are unresolved files.
5397 5400 """
5398 5401
5399 5402 if opts.get('rev') and node:
5400 5403 raise error.Abort(_("please specify just one revision"))
5401 5404 if not node:
5402 5405 node = opts.get('rev')
5403 5406
5404 5407 if node:
5405 5408 node = scmutil.revsingle(repo, node).node()
5406 5409
5407 5410 if not node:
5408 5411 node = repo[destutil.destmerge(repo)].node()
5409 5412
5410 5413 if opts.get('preview'):
5411 5414 # find nodes that are ancestors of p2 but not of p1
5412 5415 p1 = repo.lookup('.')
5413 5416 p2 = repo.lookup(node)
5414 5417 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5415 5418
5416 5419 displayer = cmdutil.show_changeset(ui, repo, opts)
5417 5420 for node in nodes:
5418 5421 displayer.show(repo[node])
5419 5422 displayer.close()
5420 5423 return 0
5421 5424
5422 5425 try:
5423 5426 # ui.forcemerge is an internal variable, do not document
5424 5427 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5425 5428 force = opts.get('force')
5426 5429 return hg.merge(repo, node, force=force, mergeforce=force)
5427 5430 finally:
5428 5431 ui.setconfig('ui', 'forcemerge', '', 'merge')
5429 5432
5430 5433 @command('outgoing|out',
5431 5434 [('f', 'force', None, _('run even when the destination is unrelated')),
5432 5435 ('r', 'rev', [],
5433 5436 _('a changeset intended to be included in the destination'), _('REV')),
5434 5437 ('n', 'newest-first', None, _('show newest record first')),
5435 5438 ('B', 'bookmarks', False, _('compare bookmarks')),
5436 5439 ('b', 'branch', [], _('a specific branch you would like to push'),
5437 5440 _('BRANCH')),
5438 5441 ] + logopts + remoteopts + subrepoopts,
5439 5442 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5440 5443 def outgoing(ui, repo, dest=None, **opts):
5441 5444 """show changesets not found in the destination
5442 5445
5443 5446 Show changesets not found in the specified destination repository
5444 5447 or the default push location. These are the changesets that would
5445 5448 be pushed if a push was requested.
5446 5449
5447 5450 See pull for details of valid destination formats.
5448 5451
5449 5452 .. container:: verbose
5450 5453
5451 5454 With -B/--bookmarks, the result of bookmark comparison between
5452 5455 local and remote repositories is displayed. With -v/--verbose,
5453 5456 status is also displayed for each bookmark like below::
5454 5457
5455 5458 BM1 01234567890a added
5456 5459 BM2 deleted
5457 5460 BM3 234567890abc advanced
5458 5461 BM4 34567890abcd diverged
5459 5462 BM5 4567890abcde changed
5460 5463
5461 5464 The action taken when pushing depends on the
5462 5465 status of each bookmark:
5463 5466
5464 5467 :``added``: push with ``-B`` will create it
5465 5468 :``deleted``: push with ``-B`` will delete it
5466 5469 :``advanced``: push will update it
5467 5470 :``diverged``: push with ``-B`` will update it
5468 5471 :``changed``: push with ``-B`` will update it
5469 5472
5470 5473 From the point of view of pushing behavior, bookmarks
5471 5474 existing only in the remote repository are treated as
5472 5475 ``deleted``, even if it is in fact added remotely.
5473 5476
5474 5477 Returns 0 if there are outgoing changes, 1 otherwise.
5475 5478 """
5476 5479 if opts.get('graph'):
5477 5480 cmdutil.checkunsupportedgraphflags([], opts)
5478 5481 o, other = hg._outgoing(ui, repo, dest, opts)
5479 5482 if not o:
5480 5483 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5481 5484 return
5482 5485
5483 5486 revdag = cmdutil.graphrevs(repo, o, opts)
5484 5487 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5485 5488 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5486 5489 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5487 5490 return 0
5488 5491
5489 5492 if opts.get('bookmarks'):
5490 5493 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5491 5494 dest, branches = hg.parseurl(dest, opts.get('branch'))
5492 5495 other = hg.peer(repo, opts, dest)
5493 5496 if 'bookmarks' not in other.listkeys('namespaces'):
5494 5497 ui.warn(_("remote doesn't support bookmarks\n"))
5495 5498 return 0
5496 5499 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5497 5500 return bookmarks.outgoing(ui, repo, other)
5498 5501
5499 5502 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5500 5503 try:
5501 5504 return hg.outgoing(ui, repo, dest, opts)
5502 5505 finally:
5503 5506 del repo._subtoppath
5504 5507
5505 5508 @command('parents',
5506 5509 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5507 5510 ] + templateopts,
5508 5511 _('[-r REV] [FILE]'),
5509 5512 inferrepo=True)
5510 5513 def parents(ui, repo, file_=None, **opts):
5511 5514 """show the parents of the working directory or revision (DEPRECATED)
5512 5515
5513 5516 Print the working directory's parent revisions. If a revision is
5514 5517 given via -r/--rev, the parent of that revision will be printed.
5515 5518 If a file argument is given, the revision in which the file was
5516 5519 last changed (before the working directory revision or the
5517 5520 argument to --rev if given) is printed.
5518 5521
5519 5522 This command is equivalent to::
5520 5523
5521 5524 hg log -r "p1()+p2()" or
5522 5525 hg log -r "p1(REV)+p2(REV)" or
5523 5526 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5524 5527 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5525 5528
5526 5529 See :hg:`summary` and :hg:`help revsets` for related information.
5527 5530
5528 5531 Returns 0 on success.
5529 5532 """
5530 5533
5531 5534 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5532 5535
5533 5536 if file_:
5534 5537 m = scmutil.match(ctx, (file_,), opts)
5535 5538 if m.anypats() or len(m.files()) != 1:
5536 5539 raise error.Abort(_('can only specify an explicit filename'))
5537 5540 file_ = m.files()[0]
5538 5541 filenodes = []
5539 5542 for cp in ctx.parents():
5540 5543 if not cp:
5541 5544 continue
5542 5545 try:
5543 5546 filenodes.append(cp.filenode(file_))
5544 5547 except error.LookupError:
5545 5548 pass
5546 5549 if not filenodes:
5547 5550 raise error.Abort(_("'%s' not found in manifest!") % file_)
5548 5551 p = []
5549 5552 for fn in filenodes:
5550 5553 fctx = repo.filectx(file_, fileid=fn)
5551 5554 p.append(fctx.node())
5552 5555 else:
5553 5556 p = [cp.node() for cp in ctx.parents()]
5554 5557
5555 5558 displayer = cmdutil.show_changeset(ui, repo, opts)
5556 5559 for n in p:
5557 5560 if n != nullid:
5558 5561 displayer.show(repo[n])
5559 5562 displayer.close()
5560 5563
5561 5564 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5562 5565 def paths(ui, repo, search=None, **opts):
5563 5566 """show aliases for remote repositories
5564 5567
5565 5568 Show definition of symbolic path name NAME. If no name is given,
5566 5569 show definition of all available names.
5567 5570
5568 5571 Option -q/--quiet suppresses all output when searching for NAME
5569 5572 and shows only the path names when listing all definitions.
5570 5573
5571 5574 Path names are defined in the [paths] section of your
5572 5575 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5573 5576 repository, ``.hg/hgrc`` is used, too.
5574 5577
5575 5578 The path names ``default`` and ``default-push`` have a special
5576 5579 meaning. When performing a push or pull operation, they are used
5577 5580 as fallbacks if no location is specified on the command-line.
5578 5581 When ``default-push`` is set, it will be used for push and
5579 5582 ``default`` will be used for pull; otherwise ``default`` is used
5580 5583 as the fallback for both. When cloning a repository, the clone
5581 5584 source is written as ``default`` in ``.hg/hgrc``.
5582 5585
5583 5586 .. note::
5584 5587
5585 5588 ``default`` and ``default-push`` apply to all inbound (e.g.
5586 5589 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5587 5590 and :hg:`bundle`) operations.
5588 5591
5589 5592 See :hg:`help urls` for more information.
5590 5593
5591 5594 Returns 0 on success.
5592 5595 """
5593 5596 if search:
5594 5597 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5595 5598 if name == search]
5596 5599 else:
5597 5600 pathitems = sorted(ui.paths.iteritems())
5598 5601
5599 5602 fm = ui.formatter('paths', opts)
5600 5603 if fm:
5601 5604 hidepassword = str
5602 5605 else:
5603 5606 hidepassword = util.hidepassword
5604 5607 if ui.quiet:
5605 5608 namefmt = '%s\n'
5606 5609 else:
5607 5610 namefmt = '%s = '
5608 5611 showsubopts = not search and not ui.quiet
5609 5612
5610 5613 for name, path in pathitems:
5611 5614 fm.startitem()
5612 5615 fm.condwrite(not search, 'name', namefmt, name)
5613 5616 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5614 5617 for subopt, value in sorted(path.suboptions.items()):
5615 5618 assert subopt not in ('name', 'url')
5616 5619 if showsubopts:
5617 5620 fm.plain('%s:%s = ' % (name, subopt))
5618 5621 fm.condwrite(showsubopts, subopt, '%s\n', value)
5619 5622
5620 5623 fm.end()
5621 5624
5622 5625 if search and not pathitems:
5623 5626 if not ui.quiet:
5624 5627 ui.warn(_("not found!\n"))
5625 5628 return 1
5626 5629 else:
5627 5630 return 0
5628 5631
5629 5632 @command('phase',
5630 5633 [('p', 'public', False, _('set changeset phase to public')),
5631 5634 ('d', 'draft', False, _('set changeset phase to draft')),
5632 5635 ('s', 'secret', False, _('set changeset phase to secret')),
5633 5636 ('f', 'force', False, _('allow to move boundary backward')),
5634 5637 ('r', 'rev', [], _('target revision'), _('REV')),
5635 5638 ],
5636 5639 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5637 5640 def phase(ui, repo, *revs, **opts):
5638 5641 """set or show the current phase name
5639 5642
5640 5643 With no argument, show the phase name of the current revision(s).
5641 5644
5642 5645 With one of -p/--public, -d/--draft or -s/--secret, change the
5643 5646 phase value of the specified revisions.
5644 5647
5645 5648 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5646 5649 lower phase to an higher phase. Phases are ordered as follows::
5647 5650
5648 5651 public < draft < secret
5649 5652
5650 5653 Returns 0 on success, 1 if some phases could not be changed.
5651 5654
5652 5655 (For more information about the phases concept, see :hg:`help phases`.)
5653 5656 """
5654 5657 # search for a unique phase argument
5655 5658 targetphase = None
5656 5659 for idx, name in enumerate(phases.phasenames):
5657 5660 if opts[name]:
5658 5661 if targetphase is not None:
5659 5662 raise error.Abort(_('only one phase can be specified'))
5660 5663 targetphase = idx
5661 5664
5662 5665 # look for specified revision
5663 5666 revs = list(revs)
5664 5667 revs.extend(opts['rev'])
5665 5668 if not revs:
5666 5669 # display both parents as the second parent phase can influence
5667 5670 # the phase of a merge commit
5668 5671 revs = [c.rev() for c in repo[None].parents()]
5669 5672
5670 5673 revs = scmutil.revrange(repo, revs)
5671 5674
5672 5675 lock = None
5673 5676 ret = 0
5674 5677 if targetphase is None:
5675 5678 # display
5676 5679 for r in revs:
5677 5680 ctx = repo[r]
5678 5681 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5679 5682 else:
5680 5683 tr = None
5681 5684 lock = repo.lock()
5682 5685 try:
5683 5686 tr = repo.transaction("phase")
5684 5687 # set phase
5685 5688 if not revs:
5686 5689 raise error.Abort(_('empty revision set'))
5687 5690 nodes = [repo[r].node() for r in revs]
5688 5691 # moving revision from public to draft may hide them
5689 5692 # We have to check result on an unfiltered repository
5690 5693 unfi = repo.unfiltered()
5691 5694 getphase = unfi._phasecache.phase
5692 5695 olddata = [getphase(unfi, r) for r in unfi]
5693 5696 phases.advanceboundary(repo, tr, targetphase, nodes)
5694 5697 if opts['force']:
5695 5698 phases.retractboundary(repo, tr, targetphase, nodes)
5696 5699 tr.close()
5697 5700 finally:
5698 5701 if tr is not None:
5699 5702 tr.release()
5700 5703 lock.release()
5701 5704 getphase = unfi._phasecache.phase
5702 5705 newdata = [getphase(unfi, r) for r in unfi]
5703 5706 changes = sum(newdata[r] != olddata[r] for r in unfi)
5704 5707 cl = unfi.changelog
5705 5708 rejected = [n for n in nodes
5706 5709 if newdata[cl.rev(n)] < targetphase]
5707 5710 if rejected:
5708 5711 ui.warn(_('cannot move %i changesets to a higher '
5709 5712 'phase, use --force\n') % len(rejected))
5710 5713 ret = 1
5711 5714 if changes:
5712 5715 msg = _('phase changed for %i changesets\n') % changes
5713 5716 if ret:
5714 5717 ui.status(msg)
5715 5718 else:
5716 5719 ui.note(msg)
5717 5720 else:
5718 5721 ui.warn(_('no phases changed\n'))
5719 5722 return ret
5720 5723
5721 5724 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5722 5725 """Run after a changegroup has been added via pull/unbundle
5723 5726
5724 5727 This takes arguments below:
5725 5728
5726 5729 :modheads: change of heads by pull/unbundle
5727 5730 :optupdate: updating working directory is needed or not
5728 5731 :checkout: update destination revision (or None to default destination)
5729 5732 :brev: a name, which might be a bookmark to be activated after updating
5730 5733 """
5731 5734 if modheads == 0:
5732 5735 return
5733 5736 if optupdate:
5734 5737 try:
5735 5738 return hg.updatetotally(ui, repo, checkout, brev)
5736 5739 except error.UpdateAbort as inst:
5737 5740 msg = _("not updating: %s") % str(inst)
5738 5741 hint = inst.hint
5739 5742 raise error.UpdateAbort(msg, hint=hint)
5740 5743 if modheads > 1:
5741 5744 currentbranchheads = len(repo.branchheads())
5742 5745 if currentbranchheads == modheads:
5743 5746 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5744 5747 elif currentbranchheads > 1:
5745 5748 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5746 5749 "merge)\n"))
5747 5750 else:
5748 5751 ui.status(_("(run 'hg heads' to see heads)\n"))
5749 5752 else:
5750 5753 ui.status(_("(run 'hg update' to get a working copy)\n"))
5751 5754
5752 5755 @command('^pull',
5753 5756 [('u', 'update', None,
5754 5757 _('update to new branch head if changesets were pulled')),
5755 5758 ('f', 'force', None, _('run even when remote repository is unrelated')),
5756 5759 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5757 5760 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5758 5761 ('b', 'branch', [], _('a specific branch you would like to pull'),
5759 5762 _('BRANCH')),
5760 5763 ] + remoteopts,
5761 5764 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5762 5765 def pull(ui, repo, source="default", **opts):
5763 5766 """pull changes from the specified source
5764 5767
5765 5768 Pull changes from a remote repository to a local one.
5766 5769
5767 5770 This finds all changes from the repository at the specified path
5768 5771 or URL and adds them to a local repository (the current one unless
5769 5772 -R is specified). By default, this does not update the copy of the
5770 5773 project in the working directory.
5771 5774
5772 5775 Use :hg:`incoming` if you want to see what would have been added
5773 5776 by a pull at the time you issued this command. If you then decide
5774 5777 to add those changes to the repository, you should use :hg:`pull
5775 5778 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5776 5779
5777 5780 If SOURCE is omitted, the 'default' path will be used.
5778 5781 See :hg:`help urls` for more information.
5779 5782
5780 5783 Specifying bookmark as ``.`` is equivalent to specifying the active
5781 5784 bookmark's name.
5782 5785
5783 5786 Returns 0 on success, 1 if an update had unresolved files.
5784 5787 """
5785 5788 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5786 5789 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5787 5790 other = hg.peer(repo, opts, source)
5788 5791 try:
5789 5792 revs, checkout = hg.addbranchrevs(repo, other, branches,
5790 5793 opts.get('rev'))
5791 5794
5792 5795
5793 5796 pullopargs = {}
5794 5797 if opts.get('bookmark'):
5795 5798 if not revs:
5796 5799 revs = []
5797 5800 # The list of bookmark used here is not the one used to actually
5798 5801 # update the bookmark name. This can result in the revision pulled
5799 5802 # not ending up with the name of the bookmark because of a race
5800 5803 # condition on the server. (See issue 4689 for details)
5801 5804 remotebookmarks = other.listkeys('bookmarks')
5802 5805 pullopargs['remotebookmarks'] = remotebookmarks
5803 5806 for b in opts['bookmark']:
5804 5807 b = repo._bookmarks.expandname(b)
5805 5808 if b not in remotebookmarks:
5806 5809 raise error.Abort(_('remote bookmark %s not found!') % b)
5807 5810 revs.append(remotebookmarks[b])
5808 5811
5809 5812 if revs:
5810 5813 try:
5811 5814 # When 'rev' is a bookmark name, we cannot guarantee that it
5812 5815 # will be updated with that name because of a race condition
5813 5816 # server side. (See issue 4689 for details)
5814 5817 oldrevs = revs
5815 5818 revs = [] # actually, nodes
5816 5819 for r in oldrevs:
5817 5820 node = other.lookup(r)
5818 5821 revs.append(node)
5819 5822 if r == checkout:
5820 5823 checkout = node
5821 5824 except error.CapabilityError:
5822 5825 err = _("other repository doesn't support revision lookup, "
5823 5826 "so a rev cannot be specified.")
5824 5827 raise error.Abort(err)
5825 5828
5826 5829 pullopargs.update(opts.get('opargs', {}))
5827 5830 modheads = exchange.pull(repo, other, heads=revs,
5828 5831 force=opts.get('force'),
5829 5832 bookmarks=opts.get('bookmark', ()),
5830 5833 opargs=pullopargs).cgresult
5831 5834
5832 5835 # brev is a name, which might be a bookmark to be activated at
5833 5836 # the end of the update. In other words, it is an explicit
5834 5837 # destination of the update
5835 5838 brev = None
5836 5839
5837 5840 if checkout:
5838 5841 checkout = str(repo.changelog.rev(checkout))
5839 5842
5840 5843 # order below depends on implementation of
5841 5844 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5842 5845 # because 'checkout' is determined without it.
5843 5846 if opts.get('rev'):
5844 5847 brev = opts['rev'][0]
5845 5848 elif opts.get('branch'):
5846 5849 brev = opts['branch'][0]
5847 5850 else:
5848 5851 brev = branches[0]
5849 5852 repo._subtoppath = source
5850 5853 try:
5851 5854 ret = postincoming(ui, repo, modheads, opts.get('update'),
5852 5855 checkout, brev)
5853 5856
5854 5857 finally:
5855 5858 del repo._subtoppath
5856 5859
5857 5860 finally:
5858 5861 other.close()
5859 5862 return ret
5860 5863
5861 5864 @command('^push',
5862 5865 [('f', 'force', None, _('force push')),
5863 5866 ('r', 'rev', [],
5864 5867 _('a changeset intended to be included in the destination'),
5865 5868 _('REV')),
5866 5869 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5867 5870 ('b', 'branch', [],
5868 5871 _('a specific branch you would like to push'), _('BRANCH')),
5869 5872 ('', 'new-branch', False, _('allow pushing a new branch')),
5870 5873 ] + remoteopts,
5871 5874 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5872 5875 def push(ui, repo, dest=None, **opts):
5873 5876 """push changes to the specified destination
5874 5877
5875 5878 Push changesets from the local repository to the specified
5876 5879 destination.
5877 5880
5878 5881 This operation is symmetrical to pull: it is identical to a pull
5879 5882 in the destination repository from the current one.
5880 5883
5881 5884 By default, push will not allow creation of new heads at the
5882 5885 destination, since multiple heads would make it unclear which head
5883 5886 to use. In this situation, it is recommended to pull and merge
5884 5887 before pushing.
5885 5888
5886 5889 Use --new-branch if you want to allow push to create a new named
5887 5890 branch that is not present at the destination. This allows you to
5888 5891 only create a new branch without forcing other changes.
5889 5892
5890 5893 .. note::
5891 5894
5892 5895 Extra care should be taken with the -f/--force option,
5893 5896 which will push all new heads on all branches, an action which will
5894 5897 almost always cause confusion for collaborators.
5895 5898
5896 5899 If -r/--rev is used, the specified revision and all its ancestors
5897 5900 will be pushed to the remote repository.
5898 5901
5899 5902 If -B/--bookmark is used, the specified bookmarked revision, its
5900 5903 ancestors, and the bookmark will be pushed to the remote
5901 5904 repository. Specifying ``.`` is equivalent to specifying the active
5902 5905 bookmark's name.
5903 5906
5904 5907 Please see :hg:`help urls` for important details about ``ssh://``
5905 5908 URLs. If DESTINATION is omitted, a default path will be used.
5906 5909
5907 5910 Returns 0 if push was successful, 1 if nothing to push.
5908 5911 """
5909 5912
5910 5913 if opts.get('bookmark'):
5911 5914 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5912 5915 for b in opts['bookmark']:
5913 5916 # translate -B options to -r so changesets get pushed
5914 5917 b = repo._bookmarks.expandname(b)
5915 5918 if b in repo._bookmarks:
5916 5919 opts.setdefault('rev', []).append(b)
5917 5920 else:
5918 5921 # if we try to push a deleted bookmark, translate it to null
5919 5922 # this lets simultaneous -r, -b options continue working
5920 5923 opts.setdefault('rev', []).append("null")
5921 5924
5922 5925 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5923 5926 if not path:
5924 5927 raise error.Abort(_('default repository not configured!'),
5925 5928 hint=_('see the "path" section in "hg help config"'))
5926 5929 dest = path.pushloc or path.loc
5927 5930 branches = (path.branch, opts.get('branch') or [])
5928 5931 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5929 5932 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5930 5933 other = hg.peer(repo, opts, dest)
5931 5934
5932 5935 if revs:
5933 5936 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5934 5937 if not revs:
5935 5938 raise error.Abort(_("specified revisions evaluate to an empty set"),
5936 5939 hint=_("use different revision arguments"))
5937 5940 elif path.pushrev:
5938 5941 # It doesn't make any sense to specify ancestor revisions. So limit
5939 5942 # to DAG heads to make discovery simpler.
5940 5943 expr = revset.formatspec('heads(%r)', path.pushrev)
5941 5944 revs = scmutil.revrange(repo, [expr])
5942 5945 revs = [repo[rev].node() for rev in revs]
5943 5946 if not revs:
5944 5947 raise error.Abort(_('default push revset for path evaluates to an '
5945 5948 'empty set'))
5946 5949
5947 5950 repo._subtoppath = dest
5948 5951 try:
5949 5952 # push subrepos depth-first for coherent ordering
5950 5953 c = repo['']
5951 5954 subs = c.substate # only repos that are committed
5952 5955 for s in sorted(subs):
5953 5956 result = c.sub(s).push(opts)
5954 5957 if result == 0:
5955 5958 return not result
5956 5959 finally:
5957 5960 del repo._subtoppath
5958 5961 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5959 5962 newbranch=opts.get('new_branch'),
5960 5963 bookmarks=opts.get('bookmark', ()),
5961 5964 opargs=opts.get('opargs'))
5962 5965
5963 5966 result = not pushop.cgresult
5964 5967
5965 5968 if pushop.bkresult is not None:
5966 5969 if pushop.bkresult == 2:
5967 5970 result = 2
5968 5971 elif not result and pushop.bkresult:
5969 5972 result = 2
5970 5973
5971 5974 return result
5972 5975
5973 5976 @command('recover', [])
5974 5977 def recover(ui, repo):
5975 5978 """roll back an interrupted transaction
5976 5979
5977 5980 Recover from an interrupted commit or pull.
5978 5981
5979 5982 This command tries to fix the repository status after an
5980 5983 interrupted operation. It should only be necessary when Mercurial
5981 5984 suggests it.
5982 5985
5983 5986 Returns 0 if successful, 1 if nothing to recover or verify fails.
5984 5987 """
5985 5988 if repo.recover():
5986 5989 return hg.verify(repo)
5987 5990 return 1
5988 5991
5989 5992 @command('^remove|rm',
5990 5993 [('A', 'after', None, _('record delete for missing files')),
5991 5994 ('f', 'force', None,
5992 5995 _('forget added files, delete modified files')),
5993 5996 ] + subrepoopts + walkopts,
5994 5997 _('[OPTION]... FILE...'),
5995 5998 inferrepo=True)
5996 5999 def remove(ui, repo, *pats, **opts):
5997 6000 """remove the specified files on the next commit
5998 6001
5999 6002 Schedule the indicated files for removal from the current branch.
6000 6003
6001 6004 This command schedules the files to be removed at the next commit.
6002 6005 To undo a remove before that, see :hg:`revert`. To undo added
6003 6006 files, see :hg:`forget`.
6004 6007
6005 6008 .. container:: verbose
6006 6009
6007 6010 -A/--after can be used to remove only files that have already
6008 6011 been deleted, -f/--force can be used to force deletion, and -Af
6009 6012 can be used to remove files from the next revision without
6010 6013 deleting them from the working directory.
6011 6014
6012 6015 The following table details the behavior of remove for different
6013 6016 file states (columns) and option combinations (rows). The file
6014 6017 states are Added [A], Clean [C], Modified [M] and Missing [!]
6015 6018 (as reported by :hg:`status`). The actions are Warn, Remove
6016 6019 (from branch) and Delete (from disk):
6017 6020
6018 6021 ========= == == == ==
6019 6022 opt/state A C M !
6020 6023 ========= == == == ==
6021 6024 none W RD W R
6022 6025 -f R RD RD R
6023 6026 -A W W W R
6024 6027 -Af R R R R
6025 6028 ========= == == == ==
6026 6029
6027 6030 .. note::
6028 6031
6029 6032 :hg:`remove` never deletes files in Added [A] state from the
6030 6033 working directory, not even if ``--force`` is specified.
6031 6034
6032 6035 Returns 0 on success, 1 if any warnings encountered.
6033 6036 """
6034 6037
6035 6038 after, force = opts.get('after'), opts.get('force')
6036 6039 if not pats and not after:
6037 6040 raise error.Abort(_('no files specified'))
6038 6041
6039 6042 m = scmutil.match(repo[None], pats, opts)
6040 6043 subrepos = opts.get('subrepos')
6041 6044 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6042 6045
6043 6046 @command('rename|move|mv',
6044 6047 [('A', 'after', None, _('record a rename that has already occurred')),
6045 6048 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6046 6049 ] + walkopts + dryrunopts,
6047 6050 _('[OPTION]... SOURCE... DEST'))
6048 6051 def rename(ui, repo, *pats, **opts):
6049 6052 """rename files; equivalent of copy + remove
6050 6053
6051 6054 Mark dest as copies of sources; mark sources for deletion. If dest
6052 6055 is a directory, copies are put in that directory. If dest is a
6053 6056 file, there can only be one source.
6054 6057
6055 6058 By default, this command copies the contents of files as they
6056 6059 exist in the working directory. If invoked with -A/--after, the
6057 6060 operation is recorded, but no copying is performed.
6058 6061
6059 6062 This command takes effect at the next commit. To undo a rename
6060 6063 before that, see :hg:`revert`.
6061 6064
6062 6065 Returns 0 on success, 1 if errors are encountered.
6063 6066 """
6064 6067 with repo.wlock(False):
6065 6068 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6066 6069
6067 6070 @command('resolve',
6068 6071 [('a', 'all', None, _('select all unresolved files')),
6069 6072 ('l', 'list', None, _('list state of files needing merge')),
6070 6073 ('m', 'mark', None, _('mark files as resolved')),
6071 6074 ('u', 'unmark', None, _('mark files as unresolved')),
6072 6075 ('n', 'no-status', None, _('hide status prefix'))]
6073 6076 + mergetoolopts + walkopts + formatteropts,
6074 6077 _('[OPTION]... [FILE]...'),
6075 6078 inferrepo=True)
6076 6079 def resolve(ui, repo, *pats, **opts):
6077 6080 """redo merges or set/view the merge status of files
6078 6081
6079 6082 Merges with unresolved conflicts are often the result of
6080 6083 non-interactive merging using the ``internal:merge`` configuration
6081 6084 setting, or a command-line merge tool like ``diff3``. The resolve
6082 6085 command is used to manage the files involved in a merge, after
6083 6086 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6084 6087 working directory must have two parents). See :hg:`help
6085 6088 merge-tools` for information on configuring merge tools.
6086 6089
6087 6090 The resolve command can be used in the following ways:
6088 6091
6089 6092 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6090 6093 files, discarding any previous merge attempts. Re-merging is not
6091 6094 performed for files already marked as resolved. Use ``--all/-a``
6092 6095 to select all unresolved files. ``--tool`` can be used to specify
6093 6096 the merge tool used for the given files. It overrides the HGMERGE
6094 6097 environment variable and your configuration files. Previous file
6095 6098 contents are saved with a ``.orig`` suffix.
6096 6099
6097 6100 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6098 6101 (e.g. after having manually fixed-up the files). The default is
6099 6102 to mark all unresolved files.
6100 6103
6101 6104 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6102 6105 default is to mark all resolved files.
6103 6106
6104 6107 - :hg:`resolve -l`: list files which had or still have conflicts.
6105 6108 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6106 6109
6107 6110 .. note::
6108 6111
6109 6112 Mercurial will not let you commit files with unresolved merge
6110 6113 conflicts. You must use :hg:`resolve -m ...` before you can
6111 6114 commit after a conflicting merge.
6112 6115
6113 6116 Returns 0 on success, 1 if any files fail a resolve attempt.
6114 6117 """
6115 6118
6116 6119 flaglist = 'all mark unmark list no_status'.split()
6117 6120 all, mark, unmark, show, nostatus = \
6118 6121 [opts.get(o) for o in flaglist]
6119 6122
6120 6123 if (show and (mark or unmark)) or (mark and unmark):
6121 6124 raise error.Abort(_("too many options specified"))
6122 6125 if pats and all:
6123 6126 raise error.Abort(_("can't specify --all and patterns"))
6124 6127 if not (all or pats or show or mark or unmark):
6125 6128 raise error.Abort(_('no files or directories specified'),
6126 6129 hint=('use --all to re-merge all unresolved files'))
6127 6130
6128 6131 if show:
6129 6132 fm = ui.formatter('resolve', opts)
6130 6133 ms = mergemod.mergestate.read(repo)
6131 6134 m = scmutil.match(repo[None], pats, opts)
6132 6135 for f in ms:
6133 6136 if not m(f):
6134 6137 continue
6135 6138 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6136 6139 'd': 'driverresolved'}[ms[f]]
6137 6140 fm.startitem()
6138 6141 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6139 6142 fm.write('path', '%s\n', f, label=l)
6140 6143 fm.end()
6141 6144 return 0
6142 6145
6143 6146 with repo.wlock():
6144 6147 ms = mergemod.mergestate.read(repo)
6145 6148
6146 6149 if not (ms.active() or repo.dirstate.p2() != nullid):
6147 6150 raise error.Abort(
6148 6151 _('resolve command not applicable when not merging'))
6149 6152
6150 6153 wctx = repo[None]
6151 6154
6152 6155 if ms.mergedriver and ms.mdstate() == 'u':
6153 6156 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6154 6157 ms.commit()
6155 6158 # allow mark and unmark to go through
6156 6159 if not mark and not unmark and not proceed:
6157 6160 return 1
6158 6161
6159 6162 m = scmutil.match(wctx, pats, opts)
6160 6163 ret = 0
6161 6164 didwork = False
6162 6165 runconclude = False
6163 6166
6164 6167 tocomplete = []
6165 6168 for f in ms:
6166 6169 if not m(f):
6167 6170 continue
6168 6171
6169 6172 didwork = True
6170 6173
6171 6174 # don't let driver-resolved files be marked, and run the conclude
6172 6175 # step if asked to resolve
6173 6176 if ms[f] == "d":
6174 6177 exact = m.exact(f)
6175 6178 if mark:
6176 6179 if exact:
6177 6180 ui.warn(_('not marking %s as it is driver-resolved\n')
6178 6181 % f)
6179 6182 elif unmark:
6180 6183 if exact:
6181 6184 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6182 6185 % f)
6183 6186 else:
6184 6187 runconclude = True
6185 6188 continue
6186 6189
6187 6190 if mark:
6188 6191 ms.mark(f, "r")
6189 6192 elif unmark:
6190 6193 ms.mark(f, "u")
6191 6194 else:
6192 6195 # backup pre-resolve (merge uses .orig for its own purposes)
6193 6196 a = repo.wjoin(f)
6194 6197 try:
6195 6198 util.copyfile(a, a + ".resolve")
6196 6199 except (IOError, OSError) as inst:
6197 6200 if inst.errno != errno.ENOENT:
6198 6201 raise
6199 6202
6200 6203 try:
6201 6204 # preresolve file
6202 6205 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6203 6206 'resolve')
6204 6207 complete, r = ms.preresolve(f, wctx)
6205 6208 if not complete:
6206 6209 tocomplete.append(f)
6207 6210 elif r:
6208 6211 ret = 1
6209 6212 finally:
6210 6213 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6211 6214 ms.commit()
6212 6215
6213 6216 # replace filemerge's .orig file with our resolve file, but only
6214 6217 # for merges that are complete
6215 6218 if complete:
6216 6219 try:
6217 6220 util.rename(a + ".resolve",
6218 6221 scmutil.origpath(ui, repo, a))
6219 6222 except OSError as inst:
6220 6223 if inst.errno != errno.ENOENT:
6221 6224 raise
6222 6225
6223 6226 for f in tocomplete:
6224 6227 try:
6225 6228 # resolve file
6226 6229 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6227 6230 'resolve')
6228 6231 r = ms.resolve(f, wctx)
6229 6232 if r:
6230 6233 ret = 1
6231 6234 finally:
6232 6235 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6233 6236 ms.commit()
6234 6237
6235 6238 # replace filemerge's .orig file with our resolve file
6236 6239 a = repo.wjoin(f)
6237 6240 try:
6238 6241 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6239 6242 except OSError as inst:
6240 6243 if inst.errno != errno.ENOENT:
6241 6244 raise
6242 6245
6243 6246 ms.commit()
6244 6247 ms.recordactions()
6245 6248
6246 6249 if not didwork and pats:
6247 6250 hint = None
6248 6251 if not any([p for p in pats if p.find(':') >= 0]):
6249 6252 pats = ['path:%s' % p for p in pats]
6250 6253 m = scmutil.match(wctx, pats, opts)
6251 6254 for f in ms:
6252 6255 if not m(f):
6253 6256 continue
6254 6257 flags = ''.join(['-%s ' % o[0] for o in flaglist
6255 6258 if opts.get(o)])
6256 6259 hint = _("(try: hg resolve %s%s)\n") % (
6257 6260 flags,
6258 6261 ' '.join(pats))
6259 6262 break
6260 6263 ui.warn(_("arguments do not match paths that need resolving\n"))
6261 6264 if hint:
6262 6265 ui.warn(hint)
6263 6266 elif ms.mergedriver and ms.mdstate() != 's':
6264 6267 # run conclude step when either a driver-resolved file is requested
6265 6268 # or there are no driver-resolved files
6266 6269 # we can't use 'ret' to determine whether any files are unresolved
6267 6270 # because we might not have tried to resolve some
6268 6271 if ((runconclude or not list(ms.driverresolved()))
6269 6272 and not list(ms.unresolved())):
6270 6273 proceed = mergemod.driverconclude(repo, ms, wctx)
6271 6274 ms.commit()
6272 6275 if not proceed:
6273 6276 return 1
6274 6277
6275 6278 # Nudge users into finishing an unfinished operation
6276 6279 unresolvedf = list(ms.unresolved())
6277 6280 driverresolvedf = list(ms.driverresolved())
6278 6281 if not unresolvedf and not driverresolvedf:
6279 6282 ui.status(_('(no more unresolved files)\n'))
6280 6283 cmdutil.checkafterresolved(repo)
6281 6284 elif not unresolvedf:
6282 6285 ui.status(_('(no more unresolved files -- '
6283 6286 'run "hg resolve --all" to conclude)\n'))
6284 6287
6285 6288 return ret
6286 6289
6287 6290 @command('revert',
6288 6291 [('a', 'all', None, _('revert all changes when no arguments given')),
6289 6292 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6290 6293 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6291 6294 ('C', 'no-backup', None, _('do not save backup copies of files')),
6292 6295 ('i', 'interactive', None,
6293 6296 _('interactively select the changes (EXPERIMENTAL)')),
6294 6297 ] + walkopts + dryrunopts,
6295 6298 _('[OPTION]... [-r REV] [NAME]...'))
6296 6299 def revert(ui, repo, *pats, **opts):
6297 6300 """restore files to their checkout state
6298 6301
6299 6302 .. note::
6300 6303
6301 6304 To check out earlier revisions, you should use :hg:`update REV`.
6302 6305 To cancel an uncommitted merge (and lose your changes),
6303 6306 use :hg:`update --clean .`.
6304 6307
6305 6308 With no revision specified, revert the specified files or directories
6306 6309 to the contents they had in the parent of the working directory.
6307 6310 This restores the contents of files to an unmodified
6308 6311 state and unschedules adds, removes, copies, and renames. If the
6309 6312 working directory has two parents, you must explicitly specify a
6310 6313 revision.
6311 6314
6312 6315 Using the -r/--rev or -d/--date options, revert the given files or
6313 6316 directories to their states as of a specific revision. Because
6314 6317 revert does not change the working directory parents, this will
6315 6318 cause these files to appear modified. This can be helpful to "back
6316 6319 out" some or all of an earlier change. See :hg:`backout` for a
6317 6320 related method.
6318 6321
6319 6322 Modified files are saved with a .orig suffix before reverting.
6320 6323 To disable these backups, use --no-backup. It is possible to store
6321 6324 the backup files in a custom directory relative to the root of the
6322 6325 repository by setting the ``ui.origbackuppath`` configuration
6323 6326 option.
6324 6327
6325 6328 See :hg:`help dates` for a list of formats valid for -d/--date.
6326 6329
6327 6330 See :hg:`help backout` for a way to reverse the effect of an
6328 6331 earlier changeset.
6329 6332
6330 6333 Returns 0 on success.
6331 6334 """
6332 6335
6333 6336 if opts.get("date"):
6334 6337 if opts.get("rev"):
6335 6338 raise error.Abort(_("you can't specify a revision and a date"))
6336 6339 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6337 6340
6338 6341 parent, p2 = repo.dirstate.parents()
6339 6342 if not opts.get('rev') and p2 != nullid:
6340 6343 # revert after merge is a trap for new users (issue2915)
6341 6344 raise error.Abort(_('uncommitted merge with no revision specified'),
6342 6345 hint=_("use 'hg update' or see 'hg help revert'"))
6343 6346
6344 6347 ctx = scmutil.revsingle(repo, opts.get('rev'))
6345 6348
6346 6349 if (not (pats or opts.get('include') or opts.get('exclude') or
6347 6350 opts.get('all') or opts.get('interactive'))):
6348 6351 msg = _("no files or directories specified")
6349 6352 if p2 != nullid:
6350 6353 hint = _("uncommitted merge, use --all to discard all changes,"
6351 6354 " or 'hg update -C .' to abort the merge")
6352 6355 raise error.Abort(msg, hint=hint)
6353 6356 dirty = any(repo.status())
6354 6357 node = ctx.node()
6355 6358 if node != parent:
6356 6359 if dirty:
6357 6360 hint = _("uncommitted changes, use --all to discard all"
6358 6361 " changes, or 'hg update %s' to update") % ctx.rev()
6359 6362 else:
6360 6363 hint = _("use --all to revert all files,"
6361 6364 " or 'hg update %s' to update") % ctx.rev()
6362 6365 elif dirty:
6363 6366 hint = _("uncommitted changes, use --all to discard all changes")
6364 6367 else:
6365 6368 hint = _("use --all to revert all files")
6366 6369 raise error.Abort(msg, hint=hint)
6367 6370
6368 6371 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6369 6372
6370 6373 @command('rollback', dryrunopts +
6371 6374 [('f', 'force', False, _('ignore safety measures'))])
6372 6375 def rollback(ui, repo, **opts):
6373 6376 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6374 6377
6375 6378 Please use :hg:`commit --amend` instead of rollback to correct
6376 6379 mistakes in the last commit.
6377 6380
6378 6381 This command should be used with care. There is only one level of
6379 6382 rollback, and there is no way to undo a rollback. It will also
6380 6383 restore the dirstate at the time of the last transaction, losing
6381 6384 any dirstate changes since that time. This command does not alter
6382 6385 the working directory.
6383 6386
6384 6387 Transactions are used to encapsulate the effects of all commands
6385 6388 that create new changesets or propagate existing changesets into a
6386 6389 repository.
6387 6390
6388 6391 .. container:: verbose
6389 6392
6390 6393 For example, the following commands are transactional, and their
6391 6394 effects can be rolled back:
6392 6395
6393 6396 - commit
6394 6397 - import
6395 6398 - pull
6396 6399 - push (with this repository as the destination)
6397 6400 - unbundle
6398 6401
6399 6402 To avoid permanent data loss, rollback will refuse to rollback a
6400 6403 commit transaction if it isn't checked out. Use --force to
6401 6404 override this protection.
6402 6405
6403 6406 The rollback command can be entirely disabled by setting the
6404 6407 ``ui.rollback`` configuration setting to false. If you're here
6405 6408 because you want to use rollback and it's disabled, you can
6406 6409 re-enable the command by setting ``ui.rollback`` to true.
6407 6410
6408 6411 This command is not intended for use on public repositories. Once
6409 6412 changes are visible for pull by other users, rolling a transaction
6410 6413 back locally is ineffective (someone else may already have pulled
6411 6414 the changes). Furthermore, a race is possible with readers of the
6412 6415 repository; for example an in-progress pull from the repository
6413 6416 may fail if a rollback is performed.
6414 6417
6415 6418 Returns 0 on success, 1 if no rollback data is available.
6416 6419 """
6417 6420 if not ui.configbool('ui', 'rollback', True):
6418 6421 raise error.Abort(_('rollback is disabled because it is unsafe'),
6419 6422 hint=('see `hg help -v rollback` for information'))
6420 6423 return repo.rollback(dryrun=opts.get('dry_run'),
6421 6424 force=opts.get('force'))
6422 6425
6423 6426 @command('root', [])
6424 6427 def root(ui, repo):
6425 6428 """print the root (top) of the current working directory
6426 6429
6427 6430 Print the root directory of the current repository.
6428 6431
6429 6432 Returns 0 on success.
6430 6433 """
6431 6434 ui.write(repo.root + "\n")
6432 6435
6433 6436 @command('^serve',
6434 6437 [('A', 'accesslog', '', _('name of access log file to write to'),
6435 6438 _('FILE')),
6436 6439 ('d', 'daemon', None, _('run server in background')),
6437 6440 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6438 6441 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6439 6442 # use string type, then we can check if something was passed
6440 6443 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6441 6444 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6442 6445 _('ADDR')),
6443 6446 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6444 6447 _('PREFIX')),
6445 6448 ('n', 'name', '',
6446 6449 _('name to show in web pages (default: working directory)'), _('NAME')),
6447 6450 ('', 'web-conf', '',
6448 6451 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6449 6452 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6450 6453 _('FILE')),
6451 6454 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6452 6455 ('', 'stdio', None, _('for remote clients')),
6453 6456 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6454 6457 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6455 6458 ('', 'style', '', _('template style to use'), _('STYLE')),
6456 6459 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6457 6460 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6458 6461 _('[OPTION]...'),
6459 6462 optionalrepo=True)
6460 6463 def serve(ui, repo, **opts):
6461 6464 """start stand-alone webserver
6462 6465
6463 6466 Start a local HTTP repository browser and pull server. You can use
6464 6467 this for ad-hoc sharing and browsing of repositories. It is
6465 6468 recommended to use a real web server to serve a repository for
6466 6469 longer periods of time.
6467 6470
6468 6471 Please note that the server does not implement access control.
6469 6472 This means that, by default, anybody can read from the server and
6470 6473 nobody can write to it by default. Set the ``web.allow_push``
6471 6474 option to ``*`` to allow everybody to push to the server. You
6472 6475 should use a real web server if you need to authenticate users.
6473 6476
6474 6477 By default, the server logs accesses to stdout and errors to
6475 6478 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6476 6479 files.
6477 6480
6478 6481 To have the server choose a free port number to listen on, specify
6479 6482 a port number of 0; in this case, the server will print the port
6480 6483 number it uses.
6481 6484
6482 6485 Returns 0 on success.
6483 6486 """
6484 6487
6485 6488 if opts["stdio"] and opts["cmdserver"]:
6486 6489 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6487 6490
6488 6491 if opts["stdio"]:
6489 6492 if repo is None:
6490 6493 raise error.RepoError(_("there is no Mercurial repository here"
6491 6494 " (.hg not found)"))
6492 6495 s = sshserver.sshserver(ui, repo)
6493 6496 s.serve_forever()
6494 6497
6495 6498 if opts["cmdserver"]:
6496 6499 service = commandserver.createservice(ui, repo, opts)
6497 6500 else:
6498 6501 service = hgweb.createservice(ui, repo, opts)
6499 6502 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6500 6503
6501 6504 @command('^status|st',
6502 6505 [('A', 'all', None, _('show status of all files')),
6503 6506 ('m', 'modified', None, _('show only modified files')),
6504 6507 ('a', 'added', None, _('show only added files')),
6505 6508 ('r', 'removed', None, _('show only removed files')),
6506 6509 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6507 6510 ('c', 'clean', None, _('show only files without changes')),
6508 6511 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6509 6512 ('i', 'ignored', None, _('show only ignored files')),
6510 6513 ('n', 'no-status', None, _('hide status prefix')),
6511 6514 ('C', 'copies', None, _('show source of copied files')),
6512 6515 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6513 6516 ('', 'rev', [], _('show difference from revision'), _('REV')),
6514 6517 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6515 6518 ] + walkopts + subrepoopts + formatteropts,
6516 6519 _('[OPTION]... [FILE]...'),
6517 6520 inferrepo=True)
6518 6521 def status(ui, repo, *pats, **opts):
6519 6522 """show changed files in the working directory
6520 6523
6521 6524 Show status of files in the repository. If names are given, only
6522 6525 files that match are shown. Files that are clean or ignored or
6523 6526 the source of a copy/move operation, are not listed unless
6524 6527 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6525 6528 Unless options described with "show only ..." are given, the
6526 6529 options -mardu are used.
6527 6530
6528 6531 Option -q/--quiet hides untracked (unknown and ignored) files
6529 6532 unless explicitly requested with -u/--unknown or -i/--ignored.
6530 6533
6531 6534 .. note::
6532 6535
6533 6536 :hg:`status` may appear to disagree with diff if permissions have
6534 6537 changed or a merge has occurred. The standard diff format does
6535 6538 not report permission changes and diff only reports changes
6536 6539 relative to one merge parent.
6537 6540
6538 6541 If one revision is given, it is used as the base revision.
6539 6542 If two revisions are given, the differences between them are
6540 6543 shown. The --change option can also be used as a shortcut to list
6541 6544 the changed files of a revision from its first parent.
6542 6545
6543 6546 The codes used to show the status of files are::
6544 6547
6545 6548 M = modified
6546 6549 A = added
6547 6550 R = removed
6548 6551 C = clean
6549 6552 ! = missing (deleted by non-hg command, but still tracked)
6550 6553 ? = not tracked
6551 6554 I = ignored
6552 6555 = origin of the previous file (with --copies)
6553 6556
6554 6557 .. container:: verbose
6555 6558
6556 6559 Examples:
6557 6560
6558 6561 - show changes in the working directory relative to a
6559 6562 changeset::
6560 6563
6561 6564 hg status --rev 9353
6562 6565
6563 6566 - show changes in the working directory relative to the
6564 6567 current directory (see :hg:`help patterns` for more information)::
6565 6568
6566 6569 hg status re:
6567 6570
6568 6571 - show all changes including copies in an existing changeset::
6569 6572
6570 6573 hg status --copies --change 9353
6571 6574
6572 6575 - get a NUL separated list of added files, suitable for xargs::
6573 6576
6574 6577 hg status -an0
6575 6578
6576 6579 Returns 0 on success.
6577 6580 """
6578 6581
6579 6582 revs = opts.get('rev')
6580 6583 change = opts.get('change')
6581 6584
6582 6585 if revs and change:
6583 6586 msg = _('cannot specify --rev and --change at the same time')
6584 6587 raise error.Abort(msg)
6585 6588 elif change:
6586 6589 node2 = scmutil.revsingle(repo, change, None).node()
6587 6590 node1 = repo[node2].p1().node()
6588 6591 else:
6589 6592 node1, node2 = scmutil.revpair(repo, revs)
6590 6593
6591 6594 if pats:
6592 6595 cwd = repo.getcwd()
6593 6596 else:
6594 6597 cwd = ''
6595 6598
6596 6599 if opts.get('print0'):
6597 6600 end = '\0'
6598 6601 else:
6599 6602 end = '\n'
6600 6603 copy = {}
6601 6604 states = 'modified added removed deleted unknown ignored clean'.split()
6602 6605 show = [k for k in states if opts.get(k)]
6603 6606 if opts.get('all'):
6604 6607 show += ui.quiet and (states[:4] + ['clean']) or states
6605 6608 if not show:
6606 6609 if ui.quiet:
6607 6610 show = states[:4]
6608 6611 else:
6609 6612 show = states[:5]
6610 6613
6611 6614 m = scmutil.match(repo[node2], pats, opts)
6612 6615 stat = repo.status(node1, node2, m,
6613 6616 'ignored' in show, 'clean' in show, 'unknown' in show,
6614 6617 opts.get('subrepos'))
6615 6618 changestates = zip(states, 'MAR!?IC', stat)
6616 6619
6617 6620 if (opts.get('all') or opts.get('copies')
6618 6621 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6619 6622 copy = copies.pathcopies(repo[node1], repo[node2], m)
6620 6623
6621 6624 fm = ui.formatter('status', opts)
6622 6625 fmt = '%s' + end
6623 6626 showchar = not opts.get('no_status')
6624 6627
6625 6628 for state, char, files in changestates:
6626 6629 if state in show:
6627 6630 label = 'status.' + state
6628 6631 for f in files:
6629 6632 fm.startitem()
6630 6633 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6631 6634 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6632 6635 if f in copy:
6633 6636 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6634 6637 label='status.copied')
6635 6638 fm.end()
6636 6639
6637 6640 @command('^summary|sum',
6638 6641 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6639 6642 def summary(ui, repo, **opts):
6640 6643 """summarize working directory state
6641 6644
6642 6645 This generates a brief summary of the working directory state,
6643 6646 including parents, branch, commit status, phase and available updates.
6644 6647
6645 6648 With the --remote option, this will check the default paths for
6646 6649 incoming and outgoing changes. This can be time-consuming.
6647 6650
6648 6651 Returns 0 on success.
6649 6652 """
6650 6653
6651 6654 ctx = repo[None]
6652 6655 parents = ctx.parents()
6653 6656 pnode = parents[0].node()
6654 6657 marks = []
6655 6658
6656 6659 ms = None
6657 6660 try:
6658 6661 ms = mergemod.mergestate.read(repo)
6659 6662 except error.UnsupportedMergeRecords as e:
6660 6663 s = ' '.join(e.recordtypes)
6661 6664 ui.warn(
6662 6665 _('warning: merge state has unsupported record types: %s\n') % s)
6663 6666 unresolved = 0
6664 6667 else:
6665 6668 unresolved = [f for f in ms if ms[f] == 'u']
6666 6669
6667 6670 for p in parents:
6668 6671 # label with log.changeset (instead of log.parent) since this
6669 6672 # shows a working directory parent *changeset*:
6670 6673 # i18n: column positioning for "hg summary"
6671 6674 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6672 6675 label='log.changeset changeset.%s' % p.phasestr())
6673 6676 ui.write(' '.join(p.tags()), label='log.tag')
6674 6677 if p.bookmarks():
6675 6678 marks.extend(p.bookmarks())
6676 6679 if p.rev() == -1:
6677 6680 if not len(repo):
6678 6681 ui.write(_(' (empty repository)'))
6679 6682 else:
6680 6683 ui.write(_(' (no revision checked out)'))
6681 6684 ui.write('\n')
6682 6685 if p.description():
6683 6686 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6684 6687 label='log.summary')
6685 6688
6686 6689 branch = ctx.branch()
6687 6690 bheads = repo.branchheads(branch)
6688 6691 # i18n: column positioning for "hg summary"
6689 6692 m = _('branch: %s\n') % branch
6690 6693 if branch != 'default':
6691 6694 ui.write(m, label='log.branch')
6692 6695 else:
6693 6696 ui.status(m, label='log.branch')
6694 6697
6695 6698 if marks:
6696 6699 active = repo._activebookmark
6697 6700 # i18n: column positioning for "hg summary"
6698 6701 ui.write(_('bookmarks:'), label='log.bookmark')
6699 6702 if active is not None:
6700 6703 if active in marks:
6701 6704 ui.write(' *' + active, label=activebookmarklabel)
6702 6705 marks.remove(active)
6703 6706 else:
6704 6707 ui.write(' [%s]' % active, label=activebookmarklabel)
6705 6708 for m in marks:
6706 6709 ui.write(' ' + m, label='log.bookmark')
6707 6710 ui.write('\n', label='log.bookmark')
6708 6711
6709 6712 status = repo.status(unknown=True)
6710 6713
6711 6714 c = repo.dirstate.copies()
6712 6715 copied, renamed = [], []
6713 6716 for d, s in c.iteritems():
6714 6717 if s in status.removed:
6715 6718 status.removed.remove(s)
6716 6719 renamed.append(d)
6717 6720 else:
6718 6721 copied.append(d)
6719 6722 if d in status.added:
6720 6723 status.added.remove(d)
6721 6724
6722 6725 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6723 6726
6724 6727 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6725 6728 (ui.label(_('%d added'), 'status.added'), status.added),
6726 6729 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6727 6730 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6728 6731 (ui.label(_('%d copied'), 'status.copied'), copied),
6729 6732 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6730 6733 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6731 6734 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6732 6735 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6733 6736 t = []
6734 6737 for l, s in labels:
6735 6738 if s:
6736 6739 t.append(l % len(s))
6737 6740
6738 6741 t = ', '.join(t)
6739 6742 cleanworkdir = False
6740 6743
6741 6744 if repo.vfs.exists('graftstate'):
6742 6745 t += _(' (graft in progress)')
6743 6746 if repo.vfs.exists('updatestate'):
6744 6747 t += _(' (interrupted update)')
6745 6748 elif len(parents) > 1:
6746 6749 t += _(' (merge)')
6747 6750 elif branch != parents[0].branch():
6748 6751 t += _(' (new branch)')
6749 6752 elif (parents[0].closesbranch() and
6750 6753 pnode in repo.branchheads(branch, closed=True)):
6751 6754 t += _(' (head closed)')
6752 6755 elif not (status.modified or status.added or status.removed or renamed or
6753 6756 copied or subs):
6754 6757 t += _(' (clean)')
6755 6758 cleanworkdir = True
6756 6759 elif pnode not in bheads:
6757 6760 t += _(' (new branch head)')
6758 6761
6759 6762 if parents:
6760 6763 pendingphase = max(p.phase() for p in parents)
6761 6764 else:
6762 6765 pendingphase = phases.public
6763 6766
6764 6767 if pendingphase > phases.newcommitphase(ui):
6765 6768 t += ' (%s)' % phases.phasenames[pendingphase]
6766 6769
6767 6770 if cleanworkdir:
6768 6771 # i18n: column positioning for "hg summary"
6769 6772 ui.status(_('commit: %s\n') % t.strip())
6770 6773 else:
6771 6774 # i18n: column positioning for "hg summary"
6772 6775 ui.write(_('commit: %s\n') % t.strip())
6773 6776
6774 6777 # all ancestors of branch heads - all ancestors of parent = new csets
6775 6778 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6776 6779 bheads))
6777 6780
6778 6781 if new == 0:
6779 6782 # i18n: column positioning for "hg summary"
6780 6783 ui.status(_('update: (current)\n'))
6781 6784 elif pnode not in bheads:
6782 6785 # i18n: column positioning for "hg summary"
6783 6786 ui.write(_('update: %d new changesets (update)\n') % new)
6784 6787 else:
6785 6788 # i18n: column positioning for "hg summary"
6786 6789 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6787 6790 (new, len(bheads)))
6788 6791
6789 6792 t = []
6790 6793 draft = len(repo.revs('draft()'))
6791 6794 if draft:
6792 6795 t.append(_('%d draft') % draft)
6793 6796 secret = len(repo.revs('secret()'))
6794 6797 if secret:
6795 6798 t.append(_('%d secret') % secret)
6796 6799
6797 6800 if draft or secret:
6798 6801 ui.status(_('phases: %s\n') % ', '.join(t))
6799 6802
6800 6803 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6801 6804 for trouble in ("unstable", "divergent", "bumped"):
6802 6805 numtrouble = len(repo.revs(trouble + "()"))
6803 6806 # We write all the possibilities to ease translation
6804 6807 troublemsg = {
6805 6808 "unstable": _("unstable: %d changesets"),
6806 6809 "divergent": _("divergent: %d changesets"),
6807 6810 "bumped": _("bumped: %d changesets"),
6808 6811 }
6809 6812 if numtrouble > 0:
6810 6813 ui.status(troublemsg[trouble] % numtrouble + "\n")
6811 6814
6812 6815 cmdutil.summaryhooks(ui, repo)
6813 6816
6814 6817 if opts.get('remote'):
6815 6818 needsincoming, needsoutgoing = True, True
6816 6819 else:
6817 6820 needsincoming, needsoutgoing = False, False
6818 6821 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6819 6822 if i:
6820 6823 needsincoming = True
6821 6824 if o:
6822 6825 needsoutgoing = True
6823 6826 if not needsincoming and not needsoutgoing:
6824 6827 return
6825 6828
6826 6829 def getincoming():
6827 6830 source, branches = hg.parseurl(ui.expandpath('default'))
6828 6831 sbranch = branches[0]
6829 6832 try:
6830 6833 other = hg.peer(repo, {}, source)
6831 6834 except error.RepoError:
6832 6835 if opts.get('remote'):
6833 6836 raise
6834 6837 return source, sbranch, None, None, None
6835 6838 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6836 6839 if revs:
6837 6840 revs = [other.lookup(rev) for rev in revs]
6838 6841 ui.debug('comparing with %s\n' % util.hidepassword(source))
6839 6842 repo.ui.pushbuffer()
6840 6843 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6841 6844 repo.ui.popbuffer()
6842 6845 return source, sbranch, other, commoninc, commoninc[1]
6843 6846
6844 6847 if needsincoming:
6845 6848 source, sbranch, sother, commoninc, incoming = getincoming()
6846 6849 else:
6847 6850 source = sbranch = sother = commoninc = incoming = None
6848 6851
6849 6852 def getoutgoing():
6850 6853 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6851 6854 dbranch = branches[0]
6852 6855 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6853 6856 if source != dest:
6854 6857 try:
6855 6858 dother = hg.peer(repo, {}, dest)
6856 6859 except error.RepoError:
6857 6860 if opts.get('remote'):
6858 6861 raise
6859 6862 return dest, dbranch, None, None
6860 6863 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6861 6864 elif sother is None:
6862 6865 # there is no explicit destination peer, but source one is invalid
6863 6866 return dest, dbranch, None, None
6864 6867 else:
6865 6868 dother = sother
6866 6869 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6867 6870 common = None
6868 6871 else:
6869 6872 common = commoninc
6870 6873 if revs:
6871 6874 revs = [repo.lookup(rev) for rev in revs]
6872 6875 repo.ui.pushbuffer()
6873 6876 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6874 6877 commoninc=common)
6875 6878 repo.ui.popbuffer()
6876 6879 return dest, dbranch, dother, outgoing
6877 6880
6878 6881 if needsoutgoing:
6879 6882 dest, dbranch, dother, outgoing = getoutgoing()
6880 6883 else:
6881 6884 dest = dbranch = dother = outgoing = None
6882 6885
6883 6886 if opts.get('remote'):
6884 6887 t = []
6885 6888 if incoming:
6886 6889 t.append(_('1 or more incoming'))
6887 6890 o = outgoing.missing
6888 6891 if o:
6889 6892 t.append(_('%d outgoing') % len(o))
6890 6893 other = dother or sother
6891 6894 if 'bookmarks' in other.listkeys('namespaces'):
6892 6895 counts = bookmarks.summary(repo, other)
6893 6896 if counts[0] > 0:
6894 6897 t.append(_('%d incoming bookmarks') % counts[0])
6895 6898 if counts[1] > 0:
6896 6899 t.append(_('%d outgoing bookmarks') % counts[1])
6897 6900
6898 6901 if t:
6899 6902 # i18n: column positioning for "hg summary"
6900 6903 ui.write(_('remote: %s\n') % (', '.join(t)))
6901 6904 else:
6902 6905 # i18n: column positioning for "hg summary"
6903 6906 ui.status(_('remote: (synced)\n'))
6904 6907
6905 6908 cmdutil.summaryremotehooks(ui, repo, opts,
6906 6909 ((source, sbranch, sother, commoninc),
6907 6910 (dest, dbranch, dother, outgoing)))
6908 6911
6909 6912 @command('tag',
6910 6913 [('f', 'force', None, _('force tag')),
6911 6914 ('l', 'local', None, _('make the tag local')),
6912 6915 ('r', 'rev', '', _('revision to tag'), _('REV')),
6913 6916 ('', 'remove', None, _('remove a tag')),
6914 6917 # -l/--local is already there, commitopts cannot be used
6915 6918 ('e', 'edit', None, _('invoke editor on commit messages')),
6916 6919 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6917 6920 ] + commitopts2,
6918 6921 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6919 6922 def tag(ui, repo, name1, *names, **opts):
6920 6923 """add one or more tags for the current or given revision
6921 6924
6922 6925 Name a particular revision using <name>.
6923 6926
6924 6927 Tags are used to name particular revisions of the repository and are
6925 6928 very useful to compare different revisions, to go back to significant
6926 6929 earlier versions or to mark branch points as releases, etc. Changing
6927 6930 an existing tag is normally disallowed; use -f/--force to override.
6928 6931
6929 6932 If no revision is given, the parent of the working directory is
6930 6933 used.
6931 6934
6932 6935 To facilitate version control, distribution, and merging of tags,
6933 6936 they are stored as a file named ".hgtags" which is managed similarly
6934 6937 to other project files and can be hand-edited if necessary. This
6935 6938 also means that tagging creates a new commit. The file
6936 6939 ".hg/localtags" is used for local tags (not shared among
6937 6940 repositories).
6938 6941
6939 6942 Tag commits are usually made at the head of a branch. If the parent
6940 6943 of the working directory is not a branch head, :hg:`tag` aborts; use
6941 6944 -f/--force to force the tag commit to be based on a non-head
6942 6945 changeset.
6943 6946
6944 6947 See :hg:`help dates` for a list of formats valid for -d/--date.
6945 6948
6946 6949 Since tag names have priority over branch names during revision
6947 6950 lookup, using an existing branch name as a tag name is discouraged.
6948 6951
6949 6952 Returns 0 on success.
6950 6953 """
6951 6954 wlock = lock = None
6952 6955 try:
6953 6956 wlock = repo.wlock()
6954 6957 lock = repo.lock()
6955 6958 rev_ = "."
6956 6959 names = [t.strip() for t in (name1,) + names]
6957 6960 if len(names) != len(set(names)):
6958 6961 raise error.Abort(_('tag names must be unique'))
6959 6962 for n in names:
6960 6963 scmutil.checknewlabel(repo, n, 'tag')
6961 6964 if not n:
6962 6965 raise error.Abort(_('tag names cannot consist entirely of '
6963 6966 'whitespace'))
6964 6967 if opts.get('rev') and opts.get('remove'):
6965 6968 raise error.Abort(_("--rev and --remove are incompatible"))
6966 6969 if opts.get('rev'):
6967 6970 rev_ = opts['rev']
6968 6971 message = opts.get('message')
6969 6972 if opts.get('remove'):
6970 6973 if opts.get('local'):
6971 6974 expectedtype = 'local'
6972 6975 else:
6973 6976 expectedtype = 'global'
6974 6977
6975 6978 for n in names:
6976 6979 if not repo.tagtype(n):
6977 6980 raise error.Abort(_("tag '%s' does not exist") % n)
6978 6981 if repo.tagtype(n) != expectedtype:
6979 6982 if expectedtype == 'global':
6980 6983 raise error.Abort(_("tag '%s' is not a global tag") % n)
6981 6984 else:
6982 6985 raise error.Abort(_("tag '%s' is not a local tag") % n)
6983 6986 rev_ = 'null'
6984 6987 if not message:
6985 6988 # we don't translate commit messages
6986 6989 message = 'Removed tag %s' % ', '.join(names)
6987 6990 elif not opts.get('force'):
6988 6991 for n in names:
6989 6992 if n in repo.tags():
6990 6993 raise error.Abort(_("tag '%s' already exists "
6991 6994 "(use -f to force)") % n)
6992 6995 if not opts.get('local'):
6993 6996 p1, p2 = repo.dirstate.parents()
6994 6997 if p2 != nullid:
6995 6998 raise error.Abort(_('uncommitted merge'))
6996 6999 bheads = repo.branchheads()
6997 7000 if not opts.get('force') and bheads and p1 not in bheads:
6998 7001 raise error.Abort(_('not at a branch head (use -f to force)'))
6999 7002 r = scmutil.revsingle(repo, rev_).node()
7000 7003
7001 7004 if not message:
7002 7005 # we don't translate commit messages
7003 7006 message = ('Added tag %s for changeset %s' %
7004 7007 (', '.join(names), short(r)))
7005 7008
7006 7009 date = opts.get('date')
7007 7010 if date:
7008 7011 date = util.parsedate(date)
7009 7012
7010 7013 if opts.get('remove'):
7011 7014 editform = 'tag.remove'
7012 7015 else:
7013 7016 editform = 'tag.add'
7014 7017 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7015 7018
7016 7019 # don't allow tagging the null rev
7017 7020 if (not opts.get('remove') and
7018 7021 scmutil.revsingle(repo, rev_).rev() == nullrev):
7019 7022 raise error.Abort(_("cannot tag null revision"))
7020 7023
7021 7024 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7022 7025 editor=editor)
7023 7026 finally:
7024 7027 release(lock, wlock)
7025 7028
7026 7029 @command('tags', formatteropts, '')
7027 7030 def tags(ui, repo, **opts):
7028 7031 """list repository tags
7029 7032
7030 7033 This lists both regular and local tags. When the -v/--verbose
7031 7034 switch is used, a third column "local" is printed for local tags.
7032 7035 When the -q/--quiet switch is used, only the tag name is printed.
7033 7036
7034 7037 Returns 0 on success.
7035 7038 """
7036 7039
7037 7040 fm = ui.formatter('tags', opts)
7038 7041 hexfunc = fm.hexfunc
7039 7042 tagtype = ""
7040 7043
7041 7044 for t, n in reversed(repo.tagslist()):
7042 7045 hn = hexfunc(n)
7043 7046 label = 'tags.normal'
7044 7047 tagtype = ''
7045 7048 if repo.tagtype(t) == 'local':
7046 7049 label = 'tags.local'
7047 7050 tagtype = 'local'
7048 7051
7049 7052 fm.startitem()
7050 7053 fm.write('tag', '%s', t, label=label)
7051 7054 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7052 7055 fm.condwrite(not ui.quiet, 'rev node', fmt,
7053 7056 repo.changelog.rev(n), hn, label=label)
7054 7057 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7055 7058 tagtype, label=label)
7056 7059 fm.plain('\n')
7057 7060 fm.end()
7058 7061
7059 7062 @command('tip',
7060 7063 [('p', 'patch', None, _('show patch')),
7061 7064 ('g', 'git', None, _('use git extended diff format')),
7062 7065 ] + templateopts,
7063 7066 _('[-p] [-g]'))
7064 7067 def tip(ui, repo, **opts):
7065 7068 """show the tip revision (DEPRECATED)
7066 7069
7067 7070 The tip revision (usually just called the tip) is the changeset
7068 7071 most recently added to the repository (and therefore the most
7069 7072 recently changed head).
7070 7073
7071 7074 If you have just made a commit, that commit will be the tip. If
7072 7075 you have just pulled changes from another repository, the tip of
7073 7076 that repository becomes the current tip. The "tip" tag is special
7074 7077 and cannot be renamed or assigned to a different changeset.
7075 7078
7076 7079 This command is deprecated, please use :hg:`heads` instead.
7077 7080
7078 7081 Returns 0 on success.
7079 7082 """
7080 7083 displayer = cmdutil.show_changeset(ui, repo, opts)
7081 7084 displayer.show(repo['tip'])
7082 7085 displayer.close()
7083 7086
7084 7087 @command('unbundle',
7085 7088 [('u', 'update', None,
7086 7089 _('update to new branch head if changesets were unbundled'))],
7087 7090 _('[-u] FILE...'))
7088 7091 def unbundle(ui, repo, fname1, *fnames, **opts):
7089 7092 """apply one or more changegroup files
7090 7093
7091 7094 Apply one or more compressed changegroup files generated by the
7092 7095 bundle command.
7093 7096
7094 7097 Returns 0 on success, 1 if an update has unresolved files.
7095 7098 """
7096 7099 fnames = (fname1,) + fnames
7097 7100
7098 7101 with repo.lock():
7099 7102 for fname in fnames:
7100 7103 f = hg.openpath(ui, fname)
7101 7104 gen = exchange.readbundle(ui, f, fname)
7102 7105 if isinstance(gen, bundle2.unbundle20):
7103 7106 tr = repo.transaction('unbundle')
7104 7107 try:
7105 7108 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7106 7109 url='bundle:' + fname)
7107 7110 tr.close()
7108 7111 except error.BundleUnknownFeatureError as exc:
7109 7112 raise error.Abort(_('%s: unknown bundle feature, %s')
7110 7113 % (fname, exc),
7111 7114 hint=_("see https://mercurial-scm.org/"
7112 7115 "wiki/BundleFeature for more "
7113 7116 "information"))
7114 7117 finally:
7115 7118 if tr:
7116 7119 tr.release()
7117 7120 changes = [r.get('return', 0)
7118 7121 for r in op.records['changegroup']]
7119 7122 modheads = changegroup.combineresults(changes)
7120 7123 elif isinstance(gen, streamclone.streamcloneapplier):
7121 7124 raise error.Abort(
7122 7125 _('packed bundles cannot be applied with '
7123 7126 '"hg unbundle"'),
7124 7127 hint=_('use "hg debugapplystreamclonebundle"'))
7125 7128 else:
7126 7129 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7127 7130
7128 7131 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7129 7132
7130 7133 @command('^update|up|checkout|co',
7131 7134 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7132 7135 ('c', 'check', None, _('require clean working directory')),
7133 7136 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7134 7137 ('r', 'rev', '', _('revision'), _('REV'))
7135 7138 ] + mergetoolopts,
7136 7139 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7137 7140 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7138 7141 tool=None):
7139 7142 """update working directory (or switch revisions)
7140 7143
7141 7144 Update the repository's working directory to the specified
7142 7145 changeset. If no changeset is specified, update to the tip of the
7143 7146 current named branch and move the active bookmark (see :hg:`help
7144 7147 bookmarks`).
7145 7148
7146 7149 Update sets the working directory's parent revision to the specified
7147 7150 changeset (see :hg:`help parents`).
7148 7151
7149 7152 If the changeset is not a descendant or ancestor of the working
7150 7153 directory's parent, the update is aborted. With the -c/--check
7151 7154 option, the working directory is checked for uncommitted changes; if
7152 7155 none are found, the working directory is updated to the specified
7153 7156 changeset.
7154 7157
7155 7158 .. container:: verbose
7156 7159
7157 7160 The following rules apply when the working directory contains
7158 7161 uncommitted changes:
7159 7162
7160 7163 1. If neither -c/--check nor -C/--clean is specified, and if
7161 7164 the requested changeset is an ancestor or descendant of
7162 7165 the working directory's parent, the uncommitted changes
7163 7166 are merged into the requested changeset and the merged
7164 7167 result is left uncommitted. If the requested changeset is
7165 7168 not an ancestor or descendant (that is, it is on another
7166 7169 branch), the update is aborted and the uncommitted changes
7167 7170 are preserved.
7168 7171
7169 7172 2. With the -c/--check option, the update is aborted and the
7170 7173 uncommitted changes are preserved.
7171 7174
7172 7175 3. With the -C/--clean option, uncommitted changes are discarded and
7173 7176 the working directory is updated to the requested changeset.
7174 7177
7175 7178 To cancel an uncommitted merge (and lose your changes), use
7176 7179 :hg:`update --clean .`.
7177 7180
7178 7181 Use null as the changeset to remove the working directory (like
7179 7182 :hg:`clone -U`).
7180 7183
7181 7184 If you want to revert just one file to an older revision, use
7182 7185 :hg:`revert [-r REV] NAME`.
7183 7186
7184 7187 See :hg:`help dates` for a list of formats valid for -d/--date.
7185 7188
7186 7189 Returns 0 on success, 1 if there are unresolved files.
7187 7190 """
7188 7191 if rev and node:
7189 7192 raise error.Abort(_("please specify just one revision"))
7190 7193
7191 7194 if rev is None or rev == '':
7192 7195 rev = node
7193 7196
7194 7197 if date and rev is not None:
7195 7198 raise error.Abort(_("you can't specify a revision and a date"))
7196 7199
7197 7200 if check and clean:
7198 7201 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7199 7202
7200 7203 with repo.wlock():
7201 7204 cmdutil.clearunfinished(repo)
7202 7205
7203 7206 if date:
7204 7207 rev = cmdutil.finddate(ui, repo, date)
7205 7208
7206 7209 # if we defined a bookmark, we have to remember the original name
7207 7210 brev = rev
7208 7211 rev = scmutil.revsingle(repo, rev, rev).rev()
7209 7212
7210 7213 if check:
7211 7214 cmdutil.bailifchanged(repo, merge=False)
7212 7215
7213 7216 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7214 7217
7215 7218 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7216 7219
7217 7220 @command('verify', [])
7218 7221 def verify(ui, repo):
7219 7222 """verify the integrity of the repository
7220 7223
7221 7224 Verify the integrity of the current repository.
7222 7225
7223 7226 This will perform an extensive check of the repository's
7224 7227 integrity, validating the hashes and checksums of each entry in
7225 7228 the changelog, manifest, and tracked files, as well as the
7226 7229 integrity of their crosslinks and indices.
7227 7230
7228 7231 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7229 7232 for more information about recovery from corruption of the
7230 7233 repository.
7231 7234
7232 7235 Returns 0 on success, 1 if errors are encountered.
7233 7236 """
7234 7237 return hg.verify(repo)
7235 7238
7236 7239 @command('version', [], norepo=True)
7237 7240 def version_(ui):
7238 7241 """output version and copyright information"""
7239 7242 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7240 7243 % util.version())
7241 7244 ui.status(_(
7242 7245 "(see https://mercurial-scm.org for more information)\n"
7243 7246 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7244 7247 "This is free software; see the source for copying conditions. "
7245 7248 "There is NO\nwarranty; "
7246 7249 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7247 7250 ))
7248 7251
7249 7252 ui.note(_("\nEnabled extensions:\n\n"))
7250 7253 if ui.verbose:
7251 7254 # format names and versions into columns
7252 7255 names = []
7253 7256 vers = []
7254 7257 place = []
7255 7258 for name, module in extensions.extensions():
7256 7259 names.append(name)
7257 7260 vers.append(extensions.moduleversion(module))
7258 7261 if extensions.ismoduleinternal(module):
7259 7262 place.append(_("internal"))
7260 7263 else:
7261 7264 place.append(_("external"))
7262 7265 if names:
7263 7266 maxnamelen = max(len(n) for n in names)
7264 7267 for i, name in enumerate(names):
7265 7268 ui.write(" %-*s %s %s\n" %
7266 7269 (maxnamelen, name, place[i], vers[i]))
7267 7270
7268 7271 def loadcmdtable(ui, name, cmdtable):
7269 7272 """Load command functions from specified cmdtable
7270 7273 """
7271 7274 overrides = [cmd for cmd in cmdtable if cmd in table]
7272 7275 if overrides:
7273 7276 ui.warn(_("extension '%s' overrides commands: %s\n")
7274 7277 % (name, " ".join(overrides)))
7275 7278 table.update(cmdtable)
@@ -1,607 +1,607 b''
1 1 # help.py - help data for mercurial
2 2 #
3 3 # Copyright 2006 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 itertools
11 11 import os
12 12 import textwrap
13 13
14 14 from .i18n import (
15 15 _,
16 16 gettext,
17 17 )
18 18 from . import (
19 19 cmdutil,
20 20 encoding,
21 21 error,
22 22 extensions,
23 23 filemerge,
24 24 fileset,
25 25 minirst,
26 26 revset,
27 27 templatefilters,
28 28 templatekw,
29 29 templater,
30 30 util,
31 31 )
32 32 from .hgweb import (
33 33 webcommands,
34 34 )
35 35
36 36 _exclkeywords = [
37 37 "(DEPRECATED)",
38 38 "(EXPERIMENTAL)",
39 39 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
40 40 _("(DEPRECATED)"),
41 41 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
42 42 _("(EXPERIMENTAL)"),
43 43 ]
44 44
45 45 def listexts(header, exts, indent=1, showdeprecated=False):
46 46 '''return a text listing of the given extensions'''
47 47 rst = []
48 48 if exts:
49 49 for name, desc in sorted(exts.iteritems()):
50 50 if not showdeprecated and any(w in desc for w in _exclkeywords):
51 51 continue
52 52 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
53 53 if rst:
54 54 rst.insert(0, '\n%s\n\n' % header)
55 55 return rst
56 56
57 57 def extshelp(ui):
58 58 rst = loaddoc('extensions')(ui).splitlines(True)
59 59 rst.extend(listexts(
60 60 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
61 61 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
62 62 doc = ''.join(rst)
63 63 return doc
64 64
65 65 def optrst(header, options, verbose):
66 66 data = []
67 67 multioccur = False
68 68 for option in options:
69 69 if len(option) == 5:
70 70 shortopt, longopt, default, desc, optlabel = option
71 71 else:
72 72 shortopt, longopt, default, desc = option
73 73 optlabel = _("VALUE") # default label
74 74
75 75 if not verbose and any(w in desc for w in _exclkeywords):
76 76 continue
77 77
78 78 so = ''
79 79 if shortopt:
80 80 so = '-' + shortopt
81 81 lo = '--' + longopt
82 82 if default:
83 83 desc += _(" (default: %s)") % default
84 84
85 85 if isinstance(default, list):
86 86 lo += " %s [+]" % optlabel
87 87 multioccur = True
88 88 elif (default is not None) and not isinstance(default, bool):
89 89 lo += " %s" % optlabel
90 90
91 91 data.append((so, lo, desc))
92 92
93 93 if multioccur:
94 94 header += (_(" ([+] can be repeated)"))
95 95
96 96 rst = ['\n%s:\n\n' % header]
97 97 rst.extend(minirst.maketable(data, 1))
98 98
99 99 return ''.join(rst)
100 100
101 101 def indicateomitted(rst, omitted, notomitted=None):
102 102 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
103 103 if notomitted:
104 104 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
105 105
106 106 def filtercmd(ui, cmd, kw, doc):
107 107 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
108 108 return True
109 109 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
110 110 return True
111 111 return False
112 112
113 113 def topicmatch(ui, kw):
114 114 """Return help topics matching kw.
115 115
116 116 Returns {'section': [(name, summary), ...], ...} where section is
117 117 one of topics, commands, extensions, or extensioncommands.
118 118 """
119 119 kw = encoding.lower(kw)
120 120 def lowercontains(container):
121 121 return kw in encoding.lower(container) # translated in helptable
122 122 results = {'topics': [],
123 123 'commands': [],
124 124 'extensions': [],
125 125 'extensioncommands': [],
126 126 }
127 127 for names, header, doc in helptable:
128 128 # Old extensions may use a str as doc.
129 129 if (sum(map(lowercontains, names))
130 130 or lowercontains(header)
131 131 or (callable(doc) and lowercontains(doc(ui)))):
132 132 results['topics'].append((names[0], header))
133 133 from . import commands # avoid cycle
134 134 for cmd, entry in commands.table.iteritems():
135 135 if len(entry) == 3:
136 136 summary = entry[2]
137 137 else:
138 138 summary = ''
139 139 # translate docs *before* searching there
140 140 docs = _(getattr(entry[0], '__doc__', None)) or ''
141 141 if kw in cmd or lowercontains(summary) or lowercontains(docs):
142 142 doclines = docs.splitlines()
143 143 if doclines:
144 144 summary = doclines[0]
145 145 cmdname = cmd.partition('|')[0].lstrip('^')
146 146 if filtercmd(ui, cmdname, kw, docs):
147 147 continue
148 148 results['commands'].append((cmdname, summary))
149 149 for name, docs in itertools.chain(
150 150 extensions.enabled(False).iteritems(),
151 151 extensions.disabled().iteritems()):
152 152 if not docs:
153 153 continue
154 154 mod = extensions.load(ui, name, '')
155 155 name = name.rpartition('.')[-1]
156 156 if lowercontains(name) or lowercontains(docs):
157 157 # extension docs are already translated
158 158 results['extensions'].append((name, docs.splitlines()[0]))
159 159 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
160 160 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
161 161 cmdname = cmd.partition('|')[0].lstrip('^')
162 162 if entry[0].__doc__:
163 163 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
164 164 else:
165 165 cmddoc = _('(no help text available)')
166 166 if filtercmd(ui, cmdname, kw, cmddoc):
167 167 continue
168 168 results['extensioncommands'].append((cmdname, cmddoc))
169 169 return results
170 170
171 171 def loaddoc(topic, subdir=None):
172 172 """Return a delayed loader for help/topic.txt."""
173 173
174 174 def loader(ui):
175 175 docdir = os.path.join(util.datapath, 'help')
176 176 if subdir:
177 177 docdir = os.path.join(docdir, subdir)
178 178 path = os.path.join(docdir, topic + ".txt")
179 179 doc = gettext(util.readfile(path))
180 180 for rewriter in helphooks.get(topic, []):
181 181 doc = rewriter(ui, topic, doc)
182 182 return doc
183 183
184 184 return loader
185 185
186 186 internalstable = sorted([
187 (['bundles'], _('container for exchange of repository data'),
187 (['bundles'], _('Bundles'),
188 188 loaddoc('bundles', subdir='internals')),
189 (['changegroups'], _('representation of revlog data'),
189 (['changegroups'], _('Changegroups'),
190 190 loaddoc('changegroups', subdir='internals')),
191 (['requirements'], _('repository requirements'),
191 (['requirements'], _('Repository Requirements'),
192 192 loaddoc('requirements', subdir='internals')),
193 (['revlogs'], _('revision storage mechanism'),
193 (['revlogs'], _('Revision Logs'),
194 194 loaddoc('revlogs', subdir='internals')),
195 195 ])
196 196
197 197 def internalshelp(ui):
198 198 """Generate the index for the "internals" topic."""
199 199 lines = []
200 200 for names, header, doc in internalstable:
201 201 lines.append(' :%s: %s\n' % (names[0], header))
202 202
203 203 return ''.join(lines)
204 204
205 205 helptable = sorted([
206 206 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
207 207 (["dates"], _("Date Formats"), loaddoc('dates')),
208 208 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
209 209 (['environment', 'env'], _('Environment Variables'),
210 210 loaddoc('environment')),
211 211 (['revisions', 'revs'], _('Specifying Single Revisions'),
212 212 loaddoc('revisions')),
213 213 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
214 214 loaddoc('multirevs')),
215 215 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
216 216 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
217 217 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
218 218 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
219 219 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
220 220 loaddoc('templates')),
221 221 (['urls'], _('URL Paths'), loaddoc('urls')),
222 222 (["extensions"], _("Using Additional Features"), extshelp),
223 223 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
224 224 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
225 225 (["glossary"], _("Glossary"), loaddoc('glossary')),
226 226 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
227 227 loaddoc('hgignore')),
228 228 (["phases"], _("Working with Phases"), loaddoc('phases')),
229 229 (['scripting'], _('Using Mercurial from scripts and automation'),
230 230 loaddoc('scripting')),
231 231 (['internals'], _("Technical implementation topics"),
232 232 internalshelp),
233 233 ])
234 234
235 235 # Maps topics with sub-topics to a list of their sub-topics.
236 236 subtopics = {
237 237 'internals': internalstable,
238 238 }
239 239
240 240 # Map topics to lists of callable taking the current topic help and
241 241 # returning the updated version
242 242 helphooks = {}
243 243
244 244 def addtopichook(topic, rewriter):
245 245 helphooks.setdefault(topic, []).append(rewriter)
246 246
247 247 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
248 248 """Extract docstring from the items key to function mapping, build a
249 249 single documentation block and use it to overwrite the marker in doc.
250 250 """
251 251 entries = []
252 252 for name in sorted(items):
253 253 text = (items[name].__doc__ or '').rstrip()
254 254 if (not text
255 255 or not ui.verbose and any(w in text for w in _exclkeywords)):
256 256 continue
257 257 text = gettext(text)
258 258 if dedent:
259 259 text = textwrap.dedent(text)
260 260 lines = text.splitlines()
261 261 doclines = [(lines[0])]
262 262 for l in lines[1:]:
263 263 # Stop once we find some Python doctest
264 264 if l.strip().startswith('>>>'):
265 265 break
266 266 if dedent:
267 267 doclines.append(l.rstrip())
268 268 else:
269 269 doclines.append(' ' + l.strip())
270 270 entries.append('\n'.join(doclines))
271 271 entries = '\n\n'.join(entries)
272 272 return doc.replace(marker, entries)
273 273
274 274 def addtopicsymbols(topic, marker, symbols, dedent=False):
275 275 def add(ui, topic, doc):
276 276 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
277 277 addtopichook(topic, add)
278 278
279 279 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
280 280 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
281 281 filemerge.internalsdoc)
282 282 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
283 283 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
284 284 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
285 285 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
286 286 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
287 287 dedent=True)
288 288
289 289 def help_(ui, name, unknowncmd=False, full=True, subtopic=None, **opts):
290 290 '''
291 291 Generate the help for 'name' as unformatted restructured text. If
292 292 'name' is None, describe the commands available.
293 293 '''
294 294
295 295 from . import commands # avoid cycle
296 296
297 297 def helpcmd(name, subtopic=None):
298 298 try:
299 299 aliases, entry = cmdutil.findcmd(name, commands.table,
300 300 strict=unknowncmd)
301 301 except error.AmbiguousCommand as inst:
302 302 # py3k fix: except vars can't be used outside the scope of the
303 303 # except block, nor can be used inside a lambda. python issue4617
304 304 prefix = inst.args[0]
305 305 select = lambda c: c.lstrip('^').startswith(prefix)
306 306 rst = helplist(select)
307 307 return rst
308 308
309 309 rst = []
310 310
311 311 # check if it's an invalid alias and display its error if it is
312 312 if getattr(entry[0], 'badalias', None):
313 313 rst.append(entry[0].badalias + '\n')
314 314 if entry[0].unknowncmd:
315 315 try:
316 316 rst.extend(helpextcmd(entry[0].cmdname))
317 317 except error.UnknownCommand:
318 318 pass
319 319 return rst
320 320
321 321 # synopsis
322 322 if len(entry) > 2:
323 323 if entry[2].startswith('hg'):
324 324 rst.append("%s\n" % entry[2])
325 325 else:
326 326 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
327 327 else:
328 328 rst.append('hg %s\n' % aliases[0])
329 329 # aliases
330 330 if full and not ui.quiet and len(aliases) > 1:
331 331 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
332 332 rst.append('\n')
333 333
334 334 # description
335 335 doc = gettext(entry[0].__doc__)
336 336 if not doc:
337 337 doc = _("(no help text available)")
338 338 if util.safehasattr(entry[0], 'definition'): # aliased command
339 339 source = entry[0].source
340 340 if entry[0].definition.startswith('!'): # shell alias
341 341 doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
342 342 (entry[0].definition[1:], source))
343 343 else:
344 344 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
345 345 (entry[0].definition, doc, source))
346 346 doc = doc.splitlines(True)
347 347 if ui.quiet or not full:
348 348 rst.append(doc[0])
349 349 else:
350 350 rst.extend(doc)
351 351 rst.append('\n')
352 352
353 353 # check if this command shadows a non-trivial (multi-line)
354 354 # extension help text
355 355 try:
356 356 mod = extensions.find(name)
357 357 doc = gettext(mod.__doc__) or ''
358 358 if '\n' in doc.strip():
359 359 msg = _('(use "hg help -e %s" to show help for '
360 360 'the %s extension)') % (name, name)
361 361 rst.append('\n%s\n' % msg)
362 362 except KeyError:
363 363 pass
364 364
365 365 # options
366 366 if not ui.quiet and entry[1]:
367 367 rst.append(optrst(_("options"), entry[1], ui.verbose))
368 368
369 369 if ui.verbose:
370 370 rst.append(optrst(_("global options"),
371 371 commands.globalopts, ui.verbose))
372 372
373 373 if not ui.verbose:
374 374 if not full:
375 375 rst.append(_('\n(use "hg %s -h" to show more help)\n')
376 376 % name)
377 377 elif not ui.quiet:
378 378 rst.append(_('\n(some details hidden, use --verbose '
379 379 'to show complete help)'))
380 380
381 381 return rst
382 382
383 383
384 384 def helplist(select=None, **opts):
385 385 # list of commands
386 386 if name == "shortlist":
387 387 header = _('basic commands:\n\n')
388 388 elif name == "debug":
389 389 header = _('debug commands (internal and unsupported):\n\n')
390 390 else:
391 391 header = _('list of commands:\n\n')
392 392
393 393 h = {}
394 394 cmds = {}
395 395 for c, e in commands.table.iteritems():
396 396 f = c.partition("|")[0]
397 397 if select and not select(f):
398 398 continue
399 399 if (not select and name != 'shortlist' and
400 400 e[0].__module__ != commands.__name__):
401 401 continue
402 402 if name == "shortlist" and not f.startswith("^"):
403 403 continue
404 404 f = f.lstrip("^")
405 405 doc = e[0].__doc__
406 406 if filtercmd(ui, f, name, doc):
407 407 continue
408 408 doc = gettext(doc)
409 409 if not doc:
410 410 doc = _("(no help text available)")
411 411 h[f] = doc.splitlines()[0].rstrip()
412 412 cmds[f] = c.lstrip("^")
413 413
414 414 rst = []
415 415 if not h:
416 416 if not ui.quiet:
417 417 rst.append(_('no commands defined\n'))
418 418 return rst
419 419
420 420 if not ui.quiet:
421 421 rst.append(header)
422 422 fns = sorted(h)
423 423 for f in fns:
424 424 if ui.verbose:
425 425 commacmds = cmds[f].replace("|",", ")
426 426 rst.append(" :%s: %s\n" % (commacmds, h[f]))
427 427 else:
428 428 rst.append(' :%s: %s\n' % (f, h[f]))
429 429
430 430 ex = opts.get
431 431 anyopts = (ex('keyword') or not (ex('command') or ex('extension')))
432 432 if not name and anyopts:
433 433 exts = listexts(_('enabled extensions:'), extensions.enabled())
434 434 if exts:
435 435 rst.append('\n')
436 436 rst.extend(exts)
437 437
438 438 rst.append(_("\nadditional help topics:\n\n"))
439 439 topics = []
440 440 for names, header, doc in helptable:
441 441 topics.append((names[0], header))
442 442 for t, desc in topics:
443 443 rst.append(" :%s: %s\n" % (t, desc))
444 444
445 445 if ui.quiet:
446 446 pass
447 447 elif ui.verbose:
448 448 rst.append('\n%s\n' % optrst(_("global options"),
449 449 commands.globalopts, ui.verbose))
450 450 if name == 'shortlist':
451 451 rst.append(_('\n(use "hg help" for the full list '
452 452 'of commands)\n'))
453 453 else:
454 454 if name == 'shortlist':
455 455 rst.append(_('\n(use "hg help" for the full list of commands '
456 456 'or "hg -v" for details)\n'))
457 457 elif name and not full:
458 458 rst.append(_('\n(use "hg help %s" to show the full help '
459 459 'text)\n') % name)
460 460 elif name and cmds and name in cmds.keys():
461 461 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
462 462 'aliases and global options)\n') % name)
463 463 else:
464 464 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
465 465 'and global options)\n')
466 466 % (name and " " + name or ""))
467 467 return rst
468 468
469 469 def helptopic(name, subtopic=None):
470 470 # Look for sub-topic entry first.
471 471 header, doc = None, None
472 472 if subtopic and name in subtopics:
473 473 for names, header, doc in subtopics[name]:
474 474 if subtopic in names:
475 475 break
476 476
477 477 if not header:
478 478 for names, header, doc in helptable:
479 479 if name in names:
480 480 break
481 481 else:
482 482 raise error.UnknownCommand(name)
483 483
484 484 rst = [minirst.section(header)]
485 485
486 486 # description
487 487 if not doc:
488 488 rst.append(" %s\n" % _("(no help text available)"))
489 489 if callable(doc):
490 490 rst += [" %s\n" % l for l in doc(ui).splitlines()]
491 491
492 492 if not ui.verbose:
493 493 omitted = _('(some details hidden, use --verbose'
494 494 ' to show complete help)')
495 495 indicateomitted(rst, omitted)
496 496
497 497 try:
498 498 cmdutil.findcmd(name, commands.table)
499 499 rst.append(_('\nuse "hg help -c %s" to see help for '
500 500 'the %s command\n') % (name, name))
501 501 except error.UnknownCommand:
502 502 pass
503 503 return rst
504 504
505 505 def helpext(name, subtopic=None):
506 506 try:
507 507 mod = extensions.find(name)
508 508 doc = gettext(mod.__doc__) or _('no help text available')
509 509 except KeyError:
510 510 mod = None
511 511 doc = extensions.disabledext(name)
512 512 if not doc:
513 513 raise error.UnknownCommand(name)
514 514
515 515 if '\n' not in doc:
516 516 head, tail = doc, ""
517 517 else:
518 518 head, tail = doc.split('\n', 1)
519 519 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
520 520 if tail:
521 521 rst.extend(tail.splitlines(True))
522 522 rst.append('\n')
523 523
524 524 if not ui.verbose:
525 525 omitted = _('(some details hidden, use --verbose'
526 526 ' to show complete help)')
527 527 indicateomitted(rst, omitted)
528 528
529 529 if mod:
530 530 try:
531 531 ct = mod.cmdtable
532 532 except AttributeError:
533 533 ct = {}
534 534 modcmds = set([c.partition('|')[0] for c in ct])
535 535 rst.extend(helplist(modcmds.__contains__))
536 536 else:
537 537 rst.append(_('(use "hg help extensions" for information on enabling'
538 538 ' extensions)\n'))
539 539 return rst
540 540
541 541 def helpextcmd(name, subtopic=None):
542 542 cmd, ext, mod = extensions.disabledcmd(ui, name,
543 543 ui.configbool('ui', 'strict'))
544 544 doc = gettext(mod.__doc__).splitlines()[0]
545 545
546 546 rst = listexts(_("'%s' is provided by the following "
547 547 "extension:") % cmd, {ext: doc}, indent=4,
548 548 showdeprecated=True)
549 549 rst.append('\n')
550 550 rst.append(_('(use "hg help extensions" for information on enabling '
551 551 'extensions)\n'))
552 552 return rst
553 553
554 554
555 555 rst = []
556 556 kw = opts.get('keyword')
557 557 if kw or name is None and any(opts[o] for o in opts):
558 558 matches = topicmatch(ui, name or '')
559 559 helpareas = []
560 560 if opts.get('extension'):
561 561 helpareas += [('extensions', _('Extensions'))]
562 562 if opts.get('command'):
563 563 helpareas += [('commands', _('Commands'))]
564 564 if not helpareas:
565 565 helpareas = [('topics', _('Topics')),
566 566 ('commands', _('Commands')),
567 567 ('extensions', _('Extensions')),
568 568 ('extensioncommands', _('Extension Commands'))]
569 569 for t, title in helpareas:
570 570 if matches[t]:
571 571 rst.append('%s:\n\n' % title)
572 572 rst.extend(minirst.maketable(sorted(matches[t]), 1))
573 573 rst.append('\n')
574 574 if not rst:
575 575 msg = _('no matches')
576 576 hint = _('try "hg help" for a list of topics')
577 577 raise error.Abort(msg, hint=hint)
578 578 elif name and name != 'shortlist':
579 579 queries = []
580 580 if unknowncmd:
581 581 queries += [helpextcmd]
582 582 if opts.get('extension'):
583 583 queries += [helpext]
584 584 if opts.get('command'):
585 585 queries += [helpcmd]
586 586 if not queries:
587 587 queries = (helptopic, helpcmd, helpext, helpextcmd)
588 588 for f in queries:
589 589 try:
590 590 rst = f(name, subtopic)
591 591 break
592 592 except error.UnknownCommand:
593 593 pass
594 594 else:
595 595 if unknowncmd:
596 596 raise error.UnknownCommand(name)
597 597 else:
598 598 msg = _('no such help topic: %s') % name
599 599 hint = _('try "hg help --keyword %s"') % name
600 600 raise error.Abort(msg, hint=hint)
601 601 else:
602 602 # program name
603 603 if not ui.quiet:
604 604 rst = [_("Mercurial Distributed SCM\n"), '\n']
605 605 rst.extend(helplist(None, **opts))
606 606
607 607 return ''.join(rst)
@@ -1,97 +1,94 b''
1 Bundles
2 =======
3
4 1 A bundle is a container for repository data.
5 2
6 3 Bundles are used as standalone files as well as the interchange format
7 4 over the wire protocol used when two Mercurial peers communicate with
8 5 each other.
9 6
10 7 Headers
11 -------
8 =======
12 9
13 10 Bundles produced since Mercurial 0.7 (September 2005) have a 4 byte
14 11 header identifying the major bundle type. The header always begins with
15 12 ``HG`` and the follow 2 bytes indicate the bundle type/version. Some
16 13 bundle types have additional data after this 4 byte header.
17 14
18 15 The following sections describe each bundle header/type.
19 16
20 17 HG10
21 18 ----
22 19
23 20 ``HG10`` headers indicate a *changegroup bundle*. This is the original
24 21 bundle format, so it is sometimes referred to as *bundle1*. It has been
25 22 present since version 0.7 (released September 2005).
26 23
27 24 This header is followed by 2 bytes indicating the compression algorithm
28 25 used for data that follows. All subsequent data following this
29 26 compression identifier is compressed according to the algorithm/method
30 27 specified.
31 28
32 29 Supported algorithms include the following.
33 30
34 31 ``BZ``
35 32 *bzip2* compression.
36 33
37 34 Bzip2 compressors emit a leading ``BZ`` header. Mercurial uses this
38 35 leading ``BZ`` as part of the bundle header. Therefore consumers
39 36 of bzip2 bundles need to *seed* the bzip2 decompressor with ``BZ`` or
40 37 seek the input stream back to the beginning of the algorithm component
41 38 of the bundle header so that decompressor input is valid. This behavior
42 39 is unique among supported compression algorithms.
43 40
44 41 Supported since version 0.7 (released December 2006).
45 42
46 43 ``GZ``
47 44 *zlib* compression.
48 45
49 46 Supported since version 0.9.2 (released December 2006).
50 47
51 48 ``UN``
52 49 *Uncompressed* or no compression. Unmodified changegroup data follows.
53 50
54 51 Supported since version 0.9.2 (released December 2006).
55 52
56 53 3rd party extensions may implement their own compression. However, no
57 54 authority reserves values for their compression algorithm identifiers.
58 55
59 56 HG2X
60 57 ----
61 58
62 59 ``HG2X`` headers (where ``X`` is any value) denote a *bundle2* bundle.
63 60 Bundle2 bundles are a container format for various kinds of repository
64 61 data and capabilities, beyond changegroup data (which was the only data
65 62 supported by ``HG10`` bundles.
66 63
67 64 ``HG20`` is currently the only defined bundle2 version.
68 65
69 66 The ``HG20`` format is not yet documented here. See the inline comments
70 67 in ``mercurial/exchange.py`` for now.
71 68
72 69 Initial ``HG20`` support was added in Mercurial 3.0 (released May
73 70 2014). However, bundle2 bundles were hidden behind an experimental flag
74 71 until version 3.5 (released August 2015), when they were enabled in the
75 72 wire protocol. Various commands (including ``hg bundle``) did not
76 73 support generating bundle2 files until Mercurial 3.6 (released November
77 74 2015).
78 75
79 76 HGS1
80 77 ----
81 78
82 79 *Experimental*
83 80
84 81 A ``HGS1`` header indicates a *streaming clone bundle*. This is a bundle
85 82 that contains raw revlog data from a repository store. (Typically revlog
86 83 data is exchanged in the form of changegroups.)
87 84
88 85 The purpose of *streaming clone bundles* are to *clone* repository data
89 86 very efficiently.
90 87
91 88 The ``HGS1`` header is always followed by 2 bytes indicating a
92 89 compression algorithm of the data that follows. Only ``UN``
93 90 (uncompressed data) is currently allowed.
94 91
95 92 ``HGS1UN`` support was added as an experimental feature in version 3.6
96 93 (released November 2015) as part of the initial offering of the *clone
97 94 bundles* feature.
@@ -1,157 +1,153 b''
1 Changegroups
2 ============
3
4 1 Changegroups are representations of repository revlog data, specifically
5 2 the changelog, manifest, and filelogs.
6 3
7 4 There are 3 versions of changegroups: ``1``, ``2``, and ``3``. From a
8 5 high-level, versions ``1`` and ``2`` are almost exactly the same, with
9 6 the only difference being a header on entries in the changeset
10 7 segment. Version ``3`` adds support for exchanging treemanifests and
11 8 includes revlog flags in the delta header.
12 9
13 10 Changegroups consists of 3 logical segments::
14 11
15 12 +---------------------------------+
16 13 | | | |
17 14 | changeset | manifest | filelogs |
18 15 | | | |
19 16 +---------------------------------+
20 17
21 18 The principle building block of each segment is a *chunk*. A *chunk*
22 19 is a framed piece of data::
23 20
24 21 +---------------------------------------+
25 22 | | |
26 23 | length | data |
27 24 | (32 bits) | <length> bytes |
28 25 | | |
29 26 +---------------------------------------+
30 27
31 28 Each chunk starts with a 32-bit big-endian signed integer indicating
32 29 the length of the raw data that follows.
33 30
34 31 There is a special case chunk that has 0 length (``0x00000000``). We
35 32 call this an *empty chunk*.
36 33
37 34 Delta Groups
38 ------------
35 ============
39 36
40 37 A *delta group* expresses the content of a revlog as a series of deltas,
41 38 or patches against previous revisions.
42 39
43 40 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
44 41 to signal the end of the delta group::
45 42
46 43 +------------------------------------------------------------------------+
47 44 | | | | | |
48 45 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
49 46 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
50 47 | | | | | |
51 48 +------------------------------------------------------------+-----------+
52 49
53 50 Each *chunk*'s data consists of the following::
54 51
55 52 +-----------------------------------------+
56 53 | | | |
57 54 | delta header | mdiff header | delta |
58 55 | (various) | (12 bytes) | (various) |
59 56 | | | |
60 57 +-----------------------------------------+
61 58
62 59 The *length* field is the byte length of the remaining 3 logical pieces
63 60 of data. The *delta* is a diff from an existing entry in the changelog.
64 61
65 62 The *delta header* is different between versions ``1``, ``2``, and
66 63 ``3`` of the changegroup format.
67 64
68 65 Version 1::
69 66
70 67 +------------------------------------------------------+
71 68 | | | | |
72 69 | node | p1 node | p2 node | link node |
73 70 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
74 71 | | | | |
75 72 +------------------------------------------------------+
76 73
77 74 Version 2::
78 75
79 76 +------------------------------------------------------------------+
80 77 | | | | | |
81 78 | node | p1 node | p2 node | base node | link node |
82 79 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
83 80 | | | | | |
84 81 +------------------------------------------------------------------+
85 82
86 83 Version 3::
87 84
88 85 +------------------------------------------------------------------------------+
89 86 | | | | | | |
90 87 | node | p1 node | p2 node | base node | link node | flags |
91 88 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
92 89 | | | | | | |
93 90 +------------------------------------------------------------------------------+
94 91
95 92 The *mdiff header* consists of 3 32-bit big-endian signed integers
96 93 describing offsets at which to apply the following delta content::
97 94
98 95 +-------------------------------------+
99 96 | | | |
100 97 | offset | old length | new length |
101 98 | (32 bits) | (32 bits) | (32 bits) |
102 99 | | | |
103 100 +-------------------------------------+
104 101
105 102 In version 1, the delta is always applied against the previous node from
106 103 the changegroup or the first parent if this is the first entry in the
107 104 changegroup.
108 105
109 106 In version 2, the delta base node is encoded in the entry in the
110 107 changegroup. This allows the delta to be expressed against any parent,
111 108 which can result in smaller deltas and more efficient encoding of data.
112 109
113 110 Changeset Segment
114 -----------------
111 =================
115 112
116 113 The *changeset segment* consists of a single *delta group* holding
117 114 changelog data. It is followed by an *empty chunk* to denote the
118 115 boundary to the *manifests segment*.
119 116
120 117 Manifest Segment
121 ----------------
118 ================
122 119
123 120 The *manifest segment* consists of a single *delta group* holding
124 121 manifest data. It is followed by an *empty chunk* to denote the boundary
125 122 to the *filelogs segment*.
126 123
127 124 Filelogs Segment
128 ----------------
125 ================
129 126
130 127 The *filelogs* segment consists of multiple sub-segments, each
131 128 corresponding to an individual file whose data is being described::
132 129
133 130 +--------------------------------------+
134 131 | | | | |
135 132 | filelog0 | filelog1 | filelog2 | ... |
136 133 | | | | |
137 134 +--------------------------------------+
138 135
139 136 In version ``3`` of the changegroup format, filelogs may include
140 137 directory logs when treemanifests are in use. directory logs are
141 138 identified by having a trailing '/' on their filename (see below).
142 139
143 140 The final filelog sub-segment is followed by an *empty chunk* to denote
144 141 the end of the segment and the overall changegroup.
145 142
146 143 Each filelog sub-segment consists of the following::
147 144
148 145 +------------------------------------------+
149 146 | | | |
150 147 | filename size | filename | delta group |
151 148 | (32 bits) | (various) | (various) |
152 149 | | | |
153 150 +------------------------------------------+
154 151
155 152 That is, a *chunk* consisting of the filename (not terminated or padded)
156 153 followed by N chunks constituting the *delta group* for this file.
157
@@ -1,110 +1,108 b''
1 Requirements
2 ============
3 1
4 2 Repositories contain a file (``.hg/requires``) containing a list of
5 3 features/capabilities that are *required* for clients to interface
6 4 with the repository. This file has been present in Mercurial since
7 5 version 0.9.2 (released December 2006).
8 6
9 7 One of the first things clients do when opening a repository is read
10 8 ``.hg/requires`` and verify that all listed requirements are supported,
11 9 aborting if not. Requirements are therefore a strong mechanism to
12 10 prevent incompatible clients from reading from unknown repository
13 11 formats or even corrupting them by writing to them.
14 12
15 13 Extensions may add requirements. When they do this, clients not running
16 14 an extension will be unable to read from repositories.
17 15
18 16 The following sections describe the requirements defined by the
19 17 Mercurial core distribution.
20 18
21 19 revlogv1
22 --------
20 ========
23 21
24 22 When present, revlogs are version 1 (RevlogNG). RevlogNG was introduced
25 23 in 2006. The ``revlogv1`` requirement has been enabled by default
26 24 since the ``requires`` file was introduced in Mercurial 0.9.2.
27 25
28 26 If this requirement is not present, version 0 revlogs are assumed.
29 27
30 28 store
31 -----
29 =====
32 30
33 31 The *store* repository layout should be used.
34 32
35 33 This requirement has been enabled by default since the ``requires`` file
36 34 was introduced in Mercurial 0.9.2.
37 35
38 36 fncache
39 -------
37 =======
40 38
41 39 The *fncache* repository layout should be used.
42 40
43 41 The *fncache* layout hash encodes filenames with long paths and
44 42 encodes reserved filenames.
45 43
46 44 This requirement is enabled by default when the *store* requirement is
47 45 enabled (which is the default behavior). It was introduced in Mercurial
48 46 1.1 (released December 2008).
49 47
50 48 shared
51 ------
49 ======
52 50
53 51 Denotes that the store for a repository is shared from another location
54 52 (defined by the ``.hg/sharedpath`` file).
55 53
56 54 This requirement is set when a repository is created via :hg:`share`.
57 55
58 56 The requirement was added in Mercurial 1.3 (released July 2009).
59 57
60 58 dotencode
61 ---------
59 =========
62 60
63 61 The *dotencode* repository layout should be used.
64 62
65 63 The *dotencode* layout encodes the first period or space in filenames
66 64 to prevent issues on OS X and Windows.
67 65
68 66 This requirement is enabled by default when the *store* requirement
69 67 is enabled (which is the default behavior). It was introduced in
70 68 Mercurial 1.7 (released November 2010).
71 69
72 70 parentdelta
73 -----------
71 ===========
74 72
75 73 Denotes a revlog delta encoding format that was experimental and
76 74 replaced by *generaldelta*. It should not be seen in the wild because
77 75 it was never enabled by default.
78 76
79 77 This requirement was added in Mercurial 1.7 and removed in Mercurial
80 78 1.9.
81 79
82 80 generaldelta
83 ------------
81 ============
84 82
85 83 Revlogs should be created with the *generaldelta* flag enabled. The
86 84 generaldelta flag will cause deltas to be encoded against a parent
87 85 revision instead of the previous revision in the revlog.
88 86
89 87 Support for this requirement was added in Mercurial 1.9 (released
90 88 July 2011). The requirement was disabled on new repositories by
91 89 default until Mercurial 3.7 (released February 2016).
92 90
93 91 manifestv2
94 ----------
92 ==========
95 93
96 94 Denotes that version 2 of manifests are being used.
97 95
98 96 Support for this requirement was added in Mercurial 3.4 (released
99 97 May 2015). The requirement is currently experimental and is disabled
100 98 by default.
101 99
102 100 treemanifest
103 ------------
101 ============
104 102
105 103 Denotes that tree manifests are being used. Tree manifests are
106 104 one manifest per directory (as opposed to a single flat manifest).
107 105
108 106 Support for this requirement was added in Mercurial 3.4 (released
109 107 August 2015). The requirement is currently experimental and is
110 108 disabled by default.
@@ -1,201 +1,198 b''
1 Revlogs
2 =======
3
4 1 Revision logs - or *revlogs* - are an append only data structure for
5 2 storing discrete entries, or *revisions*. They are the primary storage
6 3 mechanism of repository data.
7 4
8 5 Revlogs effectively model a directed acyclic graph (DAG). Each node
9 6 has edges to 1 or 2 *parent* nodes. Each node contains metadata and
10 7 the raw value for that node.
11 8
12 9 Revlogs consist of entries which have metadata and revision data.
13 10 Metadata includes the hash of the revision's content, sizes, and
14 11 links to its *parent* entries. The collective metadata is referred
15 12 to as the *index* and the revision data is the *data*.
16 13
17 14 Revision data is stored as a series of compressed deltas against previous
18 15 revisions.
19 16
20 17 Revlogs are written in an append-only fashion. We never need to rewrite
21 18 a file to insert nor do we need to remove data. Rolling back in-progress
22 19 writes can be performed by truncating files. Read locks can be avoided
23 20 using simple techniques. This means that references to other data in
24 21 the same revlog *always* refer to a previous entry.
25 22
26 23 Revlogs can be modeled as 0-indexed arrays. The first revision is
27 24 revision #0 and the second is revision #1. The revision -1 is typically
28 25 used to mean *does not exist* or *not defined*.
29 26
30 27 File Format
31 -----------
28 ===========
32 29
33 30 A revlog begins with a 32-bit big endian integer holding version info
34 31 and feature flags. This integer is shared with the first revision
35 32 entry.
36 33
37 34 This integer is logically divided into 2 16-bit shorts. The least
38 35 significant half of the integer is the format/version short. The other
39 36 short holds feature flags that dictate behavior of the revlog.
40 37
41 38 Only 1 bit of the format/version short is currently used. Remaining
42 39 bits are reserved for future use.
43 40
44 41 The following values for the format/version short are defined:
45 42
46 43 0
47 44 The original revlog version.
48 45 1
49 46 RevlogNG (*next generation*). It replaced version 0 when it was
50 47 implemented in 2006.
51 48
52 49 The feature flags short consists of bit flags. Where 0 is the least
53 50 significant bit, the following bit offsets define flags:
54 51
55 52 0
56 53 Store revision data inline.
57 54 1
58 55 Generaldelta encoding.
59 56
60 57 2-15
61 58 Reserved for future use.
62 59
63 60 The following header values are common:
64 61
65 62 00 00 00 01
66 63 RevlogNG
67 64 00 01 00 01
68 65 RevlogNG + inline
69 66 00 02 00 01
70 67 RevlogNG + generaldelta
71 68 00 03 00 01
72 69 RevlogNG + inline + generaldelta
73 70
74 71 Following the 32-bit header is the remainder of the first index entry.
75 72 Following that are remaining *index* data. Inlined revision data is
76 73 possibly located between index entries. More on this layout is described
77 74 below.
78 75
79 76 RevlogNG Format
80 ---------------
77 ===============
81 78
82 79 RevlogNG (version 1) begins with an index describing the revisions in
83 80 the revlog. If the ``inline`` flag is set, revision data is stored inline,
84 81 or between index entries (as opposed to in a separate container).
85 82
86 83 Each index entry is 64 bytes. The byte layout of each entry is as
87 84 follows, with byte 0 being the first byte (all data stored as big endian):
88 85
89 86 0-3 (4 bytes) (rev 0 only)
90 87 Revlog header
91 88 0-5 (6 bytes)
92 89 Absolute offset of revision data from beginning of revlog.
93 90 6-7 (2 bytes)
94 91 Bit flags impacting revision behavior.
95 92 8-11 (4 bytes)
96 93 Compressed length of revision data / chunk as stored in revlog.
97 94 12-15 (4 bytes)
98 95 Uncompressed length of revision data / chunk.
99 96 16-19 (4 bytes)
100 97 Base or previous revision this revision's delta was produced against.
101 98 -1 means this revision holds full text (as opposed to a delta).
102 99 For generaldelta repos, this is the previous revision in the delta
103 100 chain. For non-generaldelta repos, this is the base or first
104 101 revision in the delta chain.
105 102 20-23 (4 bytes)
106 103 A revision this revision is *linked* to. This allows a revision in
107 104 one revlog to be forever associated with a revision in another
108 105 revlog. For example, a file's revlog may point to the changelog
109 106 revision that introduced it.
110 107 24-27 (4 bytes)
111 108 Revision of 1st parent. -1 indicates no parent.
112 109 28-31 (4 bytes)
113 110 Revision of 2nd parent. -1 indicates no 2nd parent.
114 111 32-63 (32 bytes)
115 112 Hash of revision's full text. Currently, SHA-1 is used and only
116 113 the first 20 bytes of this field are used. The rest of the bytes
117 114 are ignored and should be stored as \0.
118 115
119 116 If inline revision data is being stored, the compressed revision data
120 117 (of length from bytes offset 8-11 from the index entry) immediately
121 118 follows the index entry. There is no header on the revision data. There
122 119 is no padding between it and the index entries before and after.
123 120
124 121 If revision data is not inline, then raw revision data is stored in a
125 122 separate byte container. The offsets from bytes 0-5 and the compressed
126 123 length from bytes 8-11 define how to access this data.
127 124
128 125 The first 4 bytes of the revlog are shared between the revlog header
129 126 and the 6 byte absolute offset field from the first revlog entry.
130 127
131 128 Delta Chains
132 ------------
129 ============
133 130
134 131 Revision data is encoded as a chain of *chunks*. Each chain begins with
135 132 the compressed original full text for that revision. Each subsequent
136 133 *chunk* is a *delta* against the previous revision. We therefore call
137 134 these chains of chunks/deltas *delta chains*.
138 135
139 136 The full text for a revision is reconstructed by loading the original
140 137 full text for the base revision of a *delta chain* and then applying
141 138 *deltas* until the target revision is reconstructed.
142 139
143 140 *Delta chains* are limited in length so lookup time is bound. They are
144 141 limited to ~2x the length of the revision's data. The linear distance
145 142 between the base chunk and the final chunk is also limited so the
146 143 amount of read I/O to load all chunks in the delta chain is bound.
147 144
148 145 Deltas and delta chains are either computed against the previous
149 146 revision in the revlog or another revision (almost certainly one of
150 147 the parents of the revision). Historically, deltas were computed against
151 148 the previous revision. The *generaldelta* revlog feature flag (enabled
152 149 by default in Mercurial 3.7) activates the mode where deltas are
153 150 computed against an arbitrary revision (almost certainly a parent revision).
154 151
155 152 File Storage
156 ------------
153 ============
157 154
158 155 Revlogs logically consist of an index (metadata of entries) and
159 156 revision data. This data may be stored together in a single file or in
160 157 separate files. The mechanism used is indicated by the ``inline`` feature
161 158 flag on the revlog.
162 159
163 160 Mercurial's behavior is to use inline storage until a revlog reaches a
164 161 certain size, at which point it will be converted to non-inline. The
165 162 reason there is a size limit on inline storage is to establish an upper
166 163 bound on how much data must be read to load the index. It would be a waste
167 164 to read tens or hundreds of extra megabytes of data just to access the
168 165 index data.
169 166
170 167 The actual layout of revlog files on disk is governed by the repository's
171 168 *store format*. Typically, a ``.i`` file represents the index revlog
172 169 (possibly containing inline data) and a ``.d`` file holds the revision data.
173 170
174 171 Revision Entries
175 ----------------
172 ================
176 173
177 174 Revision entries consist of an optional 1 byte header followed by an
178 175 encoding of the revision data. The headers are as follows:
179 176
180 177 \0 (0x00)
181 178 Revision data is the entirety of the entry, including this header.
182 179 u (0x75)
183 180 Raw revision data follows.
184 181 x (0x78)
185 182 zlib (RFC 1950) data.
186 183
187 184 The 0x78 value is actually the first byte of the zlib header (CMF byte).
188 185
189 186 Hash Computation
190 ----------------
187 ================
191 188
192 189 The hash of the revision is stored in the index and is used both as a primary
193 190 key and for data integrity verification.
194 191
195 192 Currently, SHA-1 is the only supported hashing algorithm. To obtain the SHA-1
196 193 hash of a revision:
197 194
198 195 1. Hash the parent nodes
199 196 2. Hash the fulltext of the revision
200 197
201 198 The 20 byte node ids of the parents are fed into the hasher in ascending order.
@@ -1,3156 +1,3155 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 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks create a new bookmark or list existing bookmarks
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 files list tracked files
70 70 forget forget the specified files on the next commit
71 71 graft copy changes from other branches onto the current branch
72 72 grep search for a pattern in specified files and revisions
73 73 heads show branch heads
74 74 help show help for a given topic or a help overview
75 75 identify identify the working directory or specified revision
76 76 import import an ordered set of patches
77 77 incoming show new changesets found in source
78 78 init create a new repository in the given directory
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge another revision into working directory
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 diffs Diff Formats
108 108 environment Environment Variables
109 109 extensions Using Additional Features
110 110 filesets Specifying File Sets
111 111 glossary Glossary
112 112 hgignore Syntax for Mercurial Ignore Files
113 113 hgweb Configuring hgweb
114 114 internals Technical implementation topics
115 115 merge-tools Merge Tools
116 116 multirevs Specifying Multiple Revisions
117 117 patterns File Name Patterns
118 118 phases Working with Phases
119 119 revisions Specifying Single Revisions
120 120 revsets Specifying Revision Sets
121 121 scripting Using Mercurial from scripts and automation
122 122 subrepos Subrepositories
123 123 templating Template Usage
124 124 urls URL Paths
125 125
126 126 (use "hg help -v" to show built-in aliases and global options)
127 127
128 128 $ hg -q help
129 129 add add the specified files on the next commit
130 130 addremove add all new files, delete all missing files
131 131 annotate show changeset information by line for each file
132 132 archive create an unversioned archive of a repository revision
133 133 backout reverse effect of earlier changeset
134 134 bisect subdivision search of changesets
135 135 bookmarks create a new bookmark or list existing bookmarks
136 136 branch set or show the current branch name
137 137 branches list repository named branches
138 138 bundle create a changegroup file
139 139 cat output the current or given revision of files
140 140 clone make a copy of an existing repository
141 141 commit commit the specified files or all outstanding changes
142 142 config show combined config settings from all hgrc files
143 143 copy mark files as copied for the next commit
144 144 diff diff repository (or selected files)
145 145 export dump the header and diffs for one or more changesets
146 146 files list tracked files
147 147 forget forget the specified files on the next commit
148 148 graft copy changes from other branches onto the current branch
149 149 grep search for a pattern in specified files and revisions
150 150 heads show branch heads
151 151 help show help for a given topic or a help overview
152 152 identify identify the working directory or specified revision
153 153 import import an ordered set of patches
154 154 incoming show new changesets found in source
155 155 init create a new repository in the given directory
156 156 log show revision history of entire repository or files
157 157 manifest output the current or given revision of the project manifest
158 158 merge merge another revision into working directory
159 159 outgoing show changesets not found in the destination
160 160 paths show aliases for remote repositories
161 161 phase set or show the current phase name
162 162 pull pull changes from the specified source
163 163 push push changes to the specified destination
164 164 recover roll back an interrupted transaction
165 165 remove remove the specified files on the next commit
166 166 rename rename files; equivalent of copy + remove
167 167 resolve redo merges or set/view the merge status of files
168 168 revert restore files to their checkout state
169 169 root print the root (top) of the current working directory
170 170 serve start stand-alone webserver
171 171 status show changed files in the working directory
172 172 summary summarize working directory state
173 173 tag add one or more tags for the current or given revision
174 174 tags list repository tags
175 175 unbundle apply one or more changegroup files
176 176 update update working directory (or switch revisions)
177 177 verify verify the integrity of the repository
178 178 version output version and copyright information
179 179
180 180 additional help topics:
181 181
182 182 config Configuration Files
183 183 dates Date Formats
184 184 diffs Diff Formats
185 185 environment Environment Variables
186 186 extensions Using Additional Features
187 187 filesets Specifying File Sets
188 188 glossary Glossary
189 189 hgignore Syntax for Mercurial Ignore Files
190 190 hgweb Configuring hgweb
191 191 internals Technical implementation topics
192 192 merge-tools Merge Tools
193 193 multirevs Specifying Multiple Revisions
194 194 patterns File Name Patterns
195 195 phases Working with Phases
196 196 revisions Specifying Single Revisions
197 197 revsets Specifying Revision Sets
198 198 scripting Using Mercurial from scripts and automation
199 199 subrepos Subrepositories
200 200 templating Template Usage
201 201 urls URL Paths
202 202
203 203 Test extension help:
204 204 $ hg help extensions --config extensions.rebase= --config extensions.children=
205 205 Using Additional Features
206 206 """""""""""""""""""""""""
207 207
208 208 Mercurial has the ability to add new features through the use of
209 209 extensions. Extensions may add new commands, add options to existing
210 210 commands, change the default behavior of commands, or implement hooks.
211 211
212 212 To enable the "foo" extension, either shipped with Mercurial or in the
213 213 Python search path, create an entry for it in your configuration file,
214 214 like this:
215 215
216 216 [extensions]
217 217 foo =
218 218
219 219 You may also specify the full path to an extension:
220 220
221 221 [extensions]
222 222 myfeature = ~/.hgext/myfeature.py
223 223
224 224 See 'hg help config' for more information on configuration files.
225 225
226 226 Extensions are not loaded by default for a variety of reasons: they can
227 227 increase startup overhead; they may be meant for advanced usage only; they
228 228 may provide potentially dangerous abilities (such as letting you destroy
229 229 or modify history); they might not be ready for prime time; or they may
230 230 alter some usual behaviors of stock Mercurial. It is thus up to the user
231 231 to activate extensions as needed.
232 232
233 233 To explicitly disable an extension enabled in a configuration file of
234 234 broader scope, prepend its path with !:
235 235
236 236 [extensions]
237 237 # disabling extension bar residing in /path/to/extension/bar.py
238 238 bar = !/path/to/extension/bar.py
239 239 # ditto, but no path was supplied for extension baz
240 240 baz = !
241 241
242 242 enabled extensions:
243 243
244 244 chgserver command server extension for cHg (EXPERIMENTAL) (?)
245 245 children command to display child changesets (DEPRECATED)
246 246 rebase command to move sets of revisions to a different ancestor
247 247
248 248 disabled extensions:
249 249
250 250 acl hooks for controlling repository access
251 251 blackbox log repository events to a blackbox for debugging
252 252 bugzilla hooks for integrating with the Bugzilla bug tracker
253 253 censor erase file content at a given revision
254 254 churn command to display statistics about repository history
255 255 clonebundles advertise pre-generated bundles to seed clones
256 256 color colorize output from some commands
257 257 convert import revisions from foreign VCS repositories into
258 258 Mercurial
259 259 eol automatically manage newlines in repository files
260 260 extdiff command to allow external programs to compare revisions
261 261 factotum http authentication with factotum
262 262 gpg commands to sign and verify changesets
263 263 hgk browse the repository in a graphical way
264 264 highlight syntax highlighting for hgweb (requires Pygments)
265 265 histedit interactive history editing
266 266 keyword expand keywords in tracked files
267 267 largefiles track large binary files
268 268 mq manage a stack of patches
269 269 notify hooks for sending email push notifications
270 270 pager browse command output with an external pager
271 271 patchbomb command to send changesets as (a series of) patch emails
272 272 purge command to delete untracked files from the working
273 273 directory
274 274 relink recreates hardlinks between repository clones
275 275 schemes extend schemes with shortcuts to repository swarms
276 276 share share a common history between several working directories
277 277 shelve save and restore changes to the working directory
278 278 strip strip changesets and their descendants from history
279 279 transplant command to transplant changesets from another branch
280 280 win32mbcs allow the use of MBCS paths with problematic encodings
281 281 zeroconf discover and advertise repositories on the local network
282 282
283 283 Verify that extension keywords appear in help templates
284 284
285 285 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
286 286
287 287 Test short command list with verbose option
288 288
289 289 $ hg -v help shortlist
290 290 Mercurial Distributed SCM
291 291
292 292 basic commands:
293 293
294 294 add add the specified files on the next commit
295 295 annotate, blame
296 296 show changeset information by line for each file
297 297 clone make a copy of an existing repository
298 298 commit, ci commit the specified files or all outstanding changes
299 299 diff diff repository (or selected files)
300 300 export dump the header and diffs for one or more changesets
301 301 forget forget the specified files on the next commit
302 302 init create a new repository in the given directory
303 303 log, history show revision history of entire repository or files
304 304 merge merge another revision into working directory
305 305 pull pull changes from the specified source
306 306 push push changes to the specified destination
307 307 remove, rm remove the specified files on the next commit
308 308 serve start stand-alone webserver
309 309 status, st show changed files in the working directory
310 310 summary, sum summarize working directory state
311 311 update, up, checkout, co
312 312 update working directory (or switch revisions)
313 313
314 314 global options ([+] can be repeated):
315 315
316 316 -R --repository REPO repository root directory or name of overlay bundle
317 317 file
318 318 --cwd DIR change working directory
319 319 -y --noninteractive do not prompt, automatically pick the first choice for
320 320 all prompts
321 321 -q --quiet suppress output
322 322 -v --verbose enable additional output
323 323 --config CONFIG [+] set/override config option (use 'section.name=value')
324 324 --debug enable debugging output
325 325 --debugger start debugger
326 326 --encoding ENCODE set the charset encoding (default: ascii)
327 327 --encodingmode MODE set the charset encoding mode (default: strict)
328 328 --traceback always print a traceback on exception
329 329 --time time how long the command takes
330 330 --profile print command execution profile
331 331 --version output version information and exit
332 332 -h --help display help and exit
333 333 --hidden consider hidden changesets
334 334
335 335 (use "hg help" for the full list of commands)
336 336
337 337 $ hg add -h
338 338 hg add [OPTION]... [FILE]...
339 339
340 340 add the specified files on the next commit
341 341
342 342 Schedule files to be version controlled and added to the repository.
343 343
344 344 The files will be added to the repository at the next commit. To undo an
345 345 add before that, see 'hg forget'.
346 346
347 347 If no names are given, add all files to the repository (except files
348 348 matching ".hgignore").
349 349
350 350 Returns 0 if all files are successfully added.
351 351
352 352 options ([+] can be repeated):
353 353
354 354 -I --include PATTERN [+] include names matching the given patterns
355 355 -X --exclude PATTERN [+] exclude names matching the given patterns
356 356 -S --subrepos recurse into subrepositories
357 357 -n --dry-run do not perform actions, just print output
358 358
359 359 (some details hidden, use --verbose to show complete help)
360 360
361 361 Verbose help for add
362 362
363 363 $ hg add -hv
364 364 hg add [OPTION]... [FILE]...
365 365
366 366 add the specified files on the next commit
367 367
368 368 Schedule files to be version controlled and added to the repository.
369 369
370 370 The files will be added to the repository at the next commit. To undo an
371 371 add before that, see 'hg forget'.
372 372
373 373 If no names are given, add all files to the repository (except files
374 374 matching ".hgignore").
375 375
376 376 Examples:
377 377
378 378 - New (unknown) files are added automatically by 'hg add':
379 379
380 380 $ ls
381 381 foo.c
382 382 $ hg status
383 383 ? foo.c
384 384 $ hg add
385 385 adding foo.c
386 386 $ hg status
387 387 A foo.c
388 388
389 389 - Specific files to be added can be specified:
390 390
391 391 $ ls
392 392 bar.c foo.c
393 393 $ hg status
394 394 ? bar.c
395 395 ? foo.c
396 396 $ hg add bar.c
397 397 $ hg status
398 398 A bar.c
399 399 ? foo.c
400 400
401 401 Returns 0 if all files are successfully added.
402 402
403 403 options ([+] can be repeated):
404 404
405 405 -I --include PATTERN [+] include names matching the given patterns
406 406 -X --exclude PATTERN [+] exclude names matching the given patterns
407 407 -S --subrepos recurse into subrepositories
408 408 -n --dry-run do not perform actions, just print output
409 409
410 410 global options ([+] can be repeated):
411 411
412 412 -R --repository REPO repository root directory or name of overlay bundle
413 413 file
414 414 --cwd DIR change working directory
415 415 -y --noninteractive do not prompt, automatically pick the first choice for
416 416 all prompts
417 417 -q --quiet suppress output
418 418 -v --verbose enable additional output
419 419 --config CONFIG [+] set/override config option (use 'section.name=value')
420 420 --debug enable debugging output
421 421 --debugger start debugger
422 422 --encoding ENCODE set the charset encoding (default: ascii)
423 423 --encodingmode MODE set the charset encoding mode (default: strict)
424 424 --traceback always print a traceback on exception
425 425 --time time how long the command takes
426 426 --profile print command execution profile
427 427 --version output version information and exit
428 428 -h --help display help and exit
429 429 --hidden consider hidden changesets
430 430
431 431 Test the textwidth config option
432 432
433 433 $ hg root -h --config ui.textwidth=50
434 434 hg root
435 435
436 436 print the root (top) of the current working
437 437 directory
438 438
439 439 Print the root directory of the current
440 440 repository.
441 441
442 442 Returns 0 on success.
443 443
444 444 (some details hidden, use --verbose to show
445 445 complete help)
446 446
447 447 Test help option with version option
448 448
449 449 $ hg add -h --version
450 450 Mercurial Distributed SCM (version *) (glob)
451 451 (see https://mercurial-scm.org for more information)
452 452
453 453 Copyright (C) 2005-2016 Matt Mackall and others
454 454 This is free software; see the source for copying conditions. There is NO
455 455 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
456 456
457 457 $ hg add --skjdfks
458 458 hg add: option --skjdfks not recognized
459 459 hg add [OPTION]... [FILE]...
460 460
461 461 add the specified files on the next commit
462 462
463 463 options ([+] can be repeated):
464 464
465 465 -I --include PATTERN [+] include names matching the given patterns
466 466 -X --exclude PATTERN [+] exclude names matching the given patterns
467 467 -S --subrepos recurse into subrepositories
468 468 -n --dry-run do not perform actions, just print output
469 469
470 470 (use "hg add -h" to show more help)
471 471 [255]
472 472
473 473 Test ambiguous command help
474 474
475 475 $ hg help ad
476 476 list of commands:
477 477
478 478 add add the specified files on the next commit
479 479 addremove add all new files, delete all missing files
480 480
481 481 (use "hg help -v ad" to show built-in aliases and global options)
482 482
483 483 Test command without options
484 484
485 485 $ hg help verify
486 486 hg verify
487 487
488 488 verify the integrity of the repository
489 489
490 490 Verify the integrity of the current repository.
491 491
492 492 This will perform an extensive check of the repository's integrity,
493 493 validating the hashes and checksums of each entry in the changelog,
494 494 manifest, and tracked files, as well as the integrity of their crosslinks
495 495 and indices.
496 496
497 497 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
498 498 information about recovery from corruption of the repository.
499 499
500 500 Returns 0 on success, 1 if errors are encountered.
501 501
502 502 (some details hidden, use --verbose to show complete help)
503 503
504 504 $ hg help diff
505 505 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
506 506
507 507 diff repository (or selected files)
508 508
509 509 Show differences between revisions for the specified files.
510 510
511 511 Differences between files are shown using the unified diff format.
512 512
513 513 Note:
514 514 'hg diff' may generate unexpected results for merges, as it will
515 515 default to comparing against the working directory's first parent
516 516 changeset if no revisions are specified.
517 517
518 518 When two revision arguments are given, then changes are shown between
519 519 those revisions. If only one revision is specified then that revision is
520 520 compared to the working directory, and, when no revisions are specified,
521 521 the working directory files are compared to its first parent.
522 522
523 523 Alternatively you can specify -c/--change with a revision to see the
524 524 changes in that changeset relative to its first parent.
525 525
526 526 Without the -a/--text option, diff will avoid generating diffs of files it
527 527 detects as binary. With -a, diff will generate a diff anyway, probably
528 528 with undesirable results.
529 529
530 530 Use the -g/--git option to generate diffs in the git extended diff format.
531 531 For more information, read 'hg help diffs'.
532 532
533 533 Returns 0 on success.
534 534
535 535 options ([+] can be repeated):
536 536
537 537 -r --rev REV [+] revision
538 538 -c --change REV change made by revision
539 539 -a --text treat all files as text
540 540 -g --git use git extended diff format
541 541 --nodates omit dates from diff headers
542 542 --noprefix omit a/ and b/ prefixes from filenames
543 543 -p --show-function show which function each change is in
544 544 --reverse produce a diff that undoes the changes
545 545 -w --ignore-all-space ignore white space when comparing lines
546 546 -b --ignore-space-change ignore changes in the amount of white space
547 547 -B --ignore-blank-lines ignore changes whose lines are all blank
548 548 -U --unified NUM number of lines of context to show
549 549 --stat output diffstat-style summary of changes
550 550 --root DIR produce diffs relative to subdirectory
551 551 -I --include PATTERN [+] include names matching the given patterns
552 552 -X --exclude PATTERN [+] exclude names matching the given patterns
553 553 -S --subrepos recurse into subrepositories
554 554
555 555 (some details hidden, use --verbose to show complete help)
556 556
557 557 $ hg help status
558 558 hg status [OPTION]... [FILE]...
559 559
560 560 aliases: st
561 561
562 562 show changed files in the working directory
563 563
564 564 Show status of files in the repository. If names are given, only files
565 565 that match are shown. Files that are clean or ignored or the source of a
566 566 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
567 567 -C/--copies or -A/--all are given. Unless options described with "show
568 568 only ..." are given, the options -mardu are used.
569 569
570 570 Option -q/--quiet hides untracked (unknown and ignored) files unless
571 571 explicitly requested with -u/--unknown or -i/--ignored.
572 572
573 573 Note:
574 574 'hg status' may appear to disagree with diff if permissions have
575 575 changed or a merge has occurred. The standard diff format does not
576 576 report permission changes and diff only reports changes relative to one
577 577 merge parent.
578 578
579 579 If one revision is given, it is used as the base revision. If two
580 580 revisions are given, the differences between them are shown. The --change
581 581 option can also be used as a shortcut to list the changed files of a
582 582 revision from its first parent.
583 583
584 584 The codes used to show the status of files are:
585 585
586 586 M = modified
587 587 A = added
588 588 R = removed
589 589 C = clean
590 590 ! = missing (deleted by non-hg command, but still tracked)
591 591 ? = not tracked
592 592 I = ignored
593 593 = origin of the previous file (with --copies)
594 594
595 595 Returns 0 on success.
596 596
597 597 options ([+] can be repeated):
598 598
599 599 -A --all show status of all files
600 600 -m --modified show only modified files
601 601 -a --added show only added files
602 602 -r --removed show only removed files
603 603 -d --deleted show only deleted (but tracked) files
604 604 -c --clean show only files without changes
605 605 -u --unknown show only unknown (not tracked) files
606 606 -i --ignored show only ignored files
607 607 -n --no-status hide status prefix
608 608 -C --copies show source of copied files
609 609 -0 --print0 end filenames with NUL, for use with xargs
610 610 --rev REV [+] show difference from revision
611 611 --change REV list the changed files of a revision
612 612 -I --include PATTERN [+] include names matching the given patterns
613 613 -X --exclude PATTERN [+] exclude names matching the given patterns
614 614 -S --subrepos recurse into subrepositories
615 615
616 616 (some details hidden, use --verbose to show complete help)
617 617
618 618 $ hg -q help status
619 619 hg status [OPTION]... [FILE]...
620 620
621 621 show changed files in the working directory
622 622
623 623 $ hg help foo
624 624 abort: no such help topic: foo
625 625 (try "hg help --keyword foo")
626 626 [255]
627 627
628 628 $ hg skjdfks
629 629 hg: unknown command 'skjdfks'
630 630 Mercurial Distributed SCM
631 631
632 632 basic commands:
633 633
634 634 add add the specified files on the next commit
635 635 annotate show changeset information by line for each file
636 636 clone make a copy of an existing repository
637 637 commit commit the specified files or all outstanding changes
638 638 diff diff repository (or selected files)
639 639 export dump the header and diffs for one or more changesets
640 640 forget forget the specified files on the next commit
641 641 init create a new repository in the given directory
642 642 log show revision history of entire repository or files
643 643 merge merge another revision into working directory
644 644 pull pull changes from the specified source
645 645 push push changes to the specified destination
646 646 remove remove the specified files on the next commit
647 647 serve start stand-alone webserver
648 648 status show changed files in the working directory
649 649 summary summarize working directory state
650 650 update update working directory (or switch revisions)
651 651
652 652 (use "hg help" for the full list of commands or "hg -v" for details)
653 653 [255]
654 654
655 655
656 656 Make sure that we don't run afoul of the help system thinking that
657 657 this is a section and erroring out weirdly.
658 658
659 659 $ hg .log
660 660 hg: unknown command '.log'
661 661 (did you mean log?)
662 662 [255]
663 663
664 664 $ hg log.
665 665 hg: unknown command 'log.'
666 666 (did you mean log?)
667 667 [255]
668 668 $ hg pu.lh
669 669 hg: unknown command 'pu.lh'
670 670 (did you mean one of pull, push?)
671 671 [255]
672 672
673 673 $ cat > helpext.py <<EOF
674 674 > import os
675 675 > from mercurial import cmdutil, commands
676 676 >
677 677 > cmdtable = {}
678 678 > command = cmdutil.command(cmdtable)
679 679 >
680 680 > @command('nohelp',
681 681 > [('', 'longdesc', 3, 'x'*90),
682 682 > ('n', '', None, 'normal desc'),
683 683 > ('', 'newline', '', 'line1\nline2')],
684 684 > 'hg nohelp',
685 685 > norepo=True)
686 686 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
687 687 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
688 688 > def nohelp(ui, *args, **kwargs):
689 689 > pass
690 690 >
691 691 > def uisetup(ui):
692 692 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
693 693 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
694 694 >
695 695 > EOF
696 696 $ echo '[extensions]' >> $HGRCPATH
697 697 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
698 698
699 699 Test for aliases
700 700
701 701 $ hg help hgalias
702 702 hg hgalias [--remote]
703 703
704 704 alias for: hg summary
705 705
706 706 summarize working directory state
707 707
708 708 This generates a brief summary of the working directory state, including
709 709 parents, branch, commit status, phase and available updates.
710 710
711 711 With the --remote option, this will check the default paths for incoming
712 712 and outgoing changes. This can be time-consuming.
713 713
714 714 Returns 0 on success.
715 715
716 716 defined by: helpext
717 717
718 718 options:
719 719
720 720 --remote check for push and pull
721 721
722 722 (some details hidden, use --verbose to show complete help)
723 723
724 724 $ hg help shellalias
725 725 hg shellalias
726 726
727 727 shell alias for:
728 728
729 729 echo hi
730 730
731 731 defined by: helpext
732 732
733 733 (some details hidden, use --verbose to show complete help)
734 734
735 735 Test command with no help text
736 736
737 737 $ hg help nohelp
738 738 hg nohelp
739 739
740 740 (no help text available)
741 741
742 742 options:
743 743
744 744 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
745 745 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
746 746 -n -- normal desc
747 747 --newline VALUE line1 line2
748 748
749 749 (some details hidden, use --verbose to show complete help)
750 750
751 751 $ hg help -k nohelp
752 752 Commands:
753 753
754 754 nohelp hg nohelp
755 755
756 756 Extension Commands:
757 757
758 758 nohelp (no help text available)
759 759
760 760 Test that default list of commands omits extension commands
761 761
762 762 $ hg help
763 763 Mercurial Distributed SCM
764 764
765 765 list of commands:
766 766
767 767 add add the specified files on the next commit
768 768 addremove add all new files, delete all missing files
769 769 annotate show changeset information by line for each file
770 770 archive create an unversioned archive of a repository revision
771 771 backout reverse effect of earlier changeset
772 772 bisect subdivision search of changesets
773 773 bookmarks create a new bookmark or list existing bookmarks
774 774 branch set or show the current branch name
775 775 branches list repository named branches
776 776 bundle create a changegroup file
777 777 cat output the current or given revision of files
778 778 clone make a copy of an existing repository
779 779 commit commit the specified files or all outstanding changes
780 780 config show combined config settings from all hgrc files
781 781 copy mark files as copied for the next commit
782 782 diff diff repository (or selected files)
783 783 export dump the header and diffs for one or more changesets
784 784 files list tracked files
785 785 forget forget the specified files on the next commit
786 786 graft copy changes from other branches onto the current branch
787 787 grep search for a pattern in specified files and revisions
788 788 heads show branch heads
789 789 help show help for a given topic or a help overview
790 790 identify identify the working directory or specified revision
791 791 import import an ordered set of patches
792 792 incoming show new changesets found in source
793 793 init create a new repository in the given directory
794 794 log show revision history of entire repository or files
795 795 manifest output the current or given revision of the project manifest
796 796 merge merge another revision into working directory
797 797 outgoing show changesets not found in the destination
798 798 paths show aliases for remote repositories
799 799 phase set or show the current phase name
800 800 pull pull changes from the specified source
801 801 push push changes to the specified destination
802 802 recover roll back an interrupted transaction
803 803 remove remove the specified files on the next commit
804 804 rename rename files; equivalent of copy + remove
805 805 resolve redo merges or set/view the merge status of files
806 806 revert restore files to their checkout state
807 807 root print the root (top) of the current working directory
808 808 serve start stand-alone webserver
809 809 status show changed files in the working directory
810 810 summary summarize working directory state
811 811 tag add one or more tags for the current or given revision
812 812 tags list repository tags
813 813 unbundle apply one or more changegroup files
814 814 update update working directory (or switch revisions)
815 815 verify verify the integrity of the repository
816 816 version output version and copyright information
817 817
818 818 enabled extensions:
819 819
820 820 helpext (no help text available)
821 821
822 822 additional help topics:
823 823
824 824 config Configuration Files
825 825 dates Date Formats
826 826 diffs Diff Formats
827 827 environment Environment Variables
828 828 extensions Using Additional Features
829 829 filesets Specifying File Sets
830 830 glossary Glossary
831 831 hgignore Syntax for Mercurial Ignore Files
832 832 hgweb Configuring hgweb
833 833 internals Technical implementation topics
834 834 merge-tools Merge Tools
835 835 multirevs Specifying Multiple Revisions
836 836 patterns File Name Patterns
837 837 phases Working with Phases
838 838 revisions Specifying Single Revisions
839 839 revsets Specifying Revision Sets
840 840 scripting Using Mercurial from scripts and automation
841 841 subrepos Subrepositories
842 842 templating Template Usage
843 843 urls URL Paths
844 844
845 845 (use "hg help -v" to show built-in aliases and global options)
846 846
847 847
848 848 Test list of internal help commands
849 849
850 850 $ hg help debug
851 851 debug commands (internal and unsupported):
852 852
853 853 debugancestor
854 854 find the ancestor revision of two revisions in a given index
855 855 debugapplystreamclonebundle
856 856 apply a stream clone bundle file
857 857 debugbuilddag
858 858 builds a repo with a given DAG from scratch in the current
859 859 empty repo
860 860 debugbundle lists the contents of a bundle
861 861 debugcheckstate
862 862 validate the correctness of the current dirstate
863 863 debugcommands
864 864 list all available commands and options
865 865 debugcomplete
866 866 returns the completion list associated with the given command
867 867 debugcreatestreamclonebundle
868 868 create a stream clone bundle file
869 869 debugdag format the changelog or an index DAG as a concise textual
870 870 description
871 871 debugdata dump the contents of a data file revision
872 872 debugdate parse and display a date
873 873 debugdeltachain
874 874 dump information about delta chains in a revlog
875 875 debugdirstate
876 876 show the contents of the current dirstate
877 877 debugdiscovery
878 878 runs the changeset discovery protocol in isolation
879 879 debugextensions
880 880 show information about active extensions
881 881 debugfileset parse and apply a fileset specification
882 882 debugfsinfo show information detected about current filesystem
883 883 debuggetbundle
884 884 retrieves a bundle from a repo
885 885 debugignore display the combined ignore pattern and information about
886 886 ignored files
887 887 debugindex dump the contents of an index file
888 888 debugindexdot
889 889 dump an index DAG as a graphviz dot file
890 890 debuginstall test Mercurial installation
891 891 debugknown test whether node ids are known to a repo
892 892 debuglocks show or modify state of locks
893 893 debugmergestate
894 894 print merge state
895 895 debugnamecomplete
896 896 complete "names" - tags, open branch names, bookmark names
897 897 debugobsolete
898 898 create arbitrary obsolete marker
899 899 debugoptDEP (no help text available)
900 900 debugoptEXP (no help text available)
901 901 debugpathcomplete
902 902 complete part or all of a tracked path
903 903 debugpushkey access the pushkey key/value protocol
904 904 debugpvec (no help text available)
905 905 debugrebuilddirstate
906 906 rebuild the dirstate as it would look like for the given
907 907 revision
908 908 debugrebuildfncache
909 909 rebuild the fncache file
910 910 debugrename dump rename information
911 911 debugrevlog show data and statistics about a revlog
912 912 debugrevspec parse and apply a revision specification
913 913 debugsetparents
914 914 manually set the parents of the current working directory
915 915 debugsub (no help text available)
916 916 debugsuccessorssets
917 917 show set of successors for revision
918 918 debugtemplate
919 919 parse and apply a template
920 920 debugwalk show how files match on given patterns
921 921 debugwireargs
922 922 (no help text available)
923 923
924 924 (use "hg help -v debug" to show built-in aliases and global options)
925 925
926 926 internals topic renders index of available sub-topics
927 927
928 928 $ hg help internals
929 929 Technical implementation topics
930 930 """""""""""""""""""""""""""""""
931 931
932 bundles container for exchange of repository data
933 changegroups representation of revlog data
934 requirements repository requirements
935 revlogs revision storage mechanism
932 bundles Bundles
933 changegroups Changegroups
934 requirements Repository Requirements
935 revlogs Revision Logs
936 936
937 937 sub-topics can be accessed
938 938
939 939 $ hg help internals.changegroups
940 Changegroups
941 ============
940 Changegroups
941 """"""""""""
942 942
943 943 Changegroups are representations of repository revlog data, specifically
944 944 the changelog, manifest, and filelogs.
945 945
946 946 There are 3 versions of changegroups: "1", "2", and "3". From a high-
947 947 level, versions "1" and "2" are almost exactly the same, with the only
948 948 difference being a header on entries in the changeset segment. Version "3"
949 949 adds support for exchanging treemanifests and includes revlog flags in the
950 950 delta header.
951 951
952 952 Changegroups consists of 3 logical segments:
953 953
954 954 +---------------------------------+
955 955 | | | |
956 956 | changeset | manifest | filelogs |
957 957 | | | |
958 958 +---------------------------------+
959 959
960 960 The principle building block of each segment is a *chunk*. A *chunk* is a
961 961 framed piece of data:
962 962
963 963 +---------------------------------------+
964 964 | | |
965 965 | length | data |
966 966 | (32 bits) | <length> bytes |
967 967 | | |
968 968 +---------------------------------------+
969 969
970 970 Each chunk starts with a 32-bit big-endian signed integer indicating the
971 971 length of the raw data that follows.
972 972
973 973 There is a special case chunk that has 0 length ("0x00000000"). We call
974 974 this an *empty chunk*.
975 975
976 976 Delta Groups
977 ------------
977 ============
978 978
979 979 A *delta group* expresses the content of a revlog as a series of deltas,
980 980 or patches against previous revisions.
981 981
982 982 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
983 983 to signal the end of the delta group:
984 984
985 985 +------------------------------------------------------------------------+
986 986 | | | | | |
987 987 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
988 988 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
989 989 | | | | | |
990 990 +------------------------------------------------------------+-----------+
991 991
992 992 Each *chunk*'s data consists of the following:
993 993
994 994 +-----------------------------------------+
995 995 | | | |
996 996 | delta header | mdiff header | delta |
997 997 | (various) | (12 bytes) | (various) |
998 998 | | | |
999 999 +-----------------------------------------+
1000 1000
1001 1001 The *length* field is the byte length of the remaining 3 logical pieces of
1002 1002 data. The *delta* is a diff from an existing entry in the changelog.
1003 1003
1004 1004 The *delta header* is different between versions "1", "2", and "3" of the
1005 1005 changegroup format.
1006 1006
1007 1007 Version 1:
1008 1008
1009 1009 +------------------------------------------------------+
1010 1010 | | | | |
1011 1011 | node | p1 node | p2 node | link node |
1012 1012 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1013 1013 | | | | |
1014 1014 +------------------------------------------------------+
1015 1015
1016 1016 Version 2:
1017 1017
1018 1018 +------------------------------------------------------------------+
1019 1019 | | | | | |
1020 1020 | node | p1 node | p2 node | base node | link node |
1021 1021 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1022 1022 | | | | | |
1023 1023 +------------------------------------------------------------------+
1024 1024
1025 1025 Version 3:
1026 1026
1027 1027 +------------------------------------------------------------------------------+
1028 1028 | | | | | | |
1029 1029 | node | p1 node | p2 node | base node | link node | flags |
1030 1030 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1031 1031 | | | | | | |
1032 1032 +------------------------------------------------------------------------------+
1033 1033
1034 1034 The *mdiff header* consists of 3 32-bit big-endian signed integers
1035 1035 describing offsets at which to apply the following delta content:
1036 1036
1037 1037 +-------------------------------------+
1038 1038 | | | |
1039 1039 | offset | old length | new length |
1040 1040 | (32 bits) | (32 bits) | (32 bits) |
1041 1041 | | | |
1042 1042 +-------------------------------------+
1043 1043
1044 1044 In version 1, the delta is always applied against the previous node from
1045 1045 the changegroup or the first parent if this is the first entry in the
1046 1046 changegroup.
1047 1047
1048 1048 In version 2, the delta base node is encoded in the entry in the
1049 1049 changegroup. This allows the delta to be expressed against any parent,
1050 1050 which can result in smaller deltas and more efficient encoding of data.
1051 1051
1052 1052 Changeset Segment
1053 -----------------
1053 =================
1054 1054
1055 1055 The *changeset segment* consists of a single *delta group* holding
1056 1056 changelog data. It is followed by an *empty chunk* to denote the boundary
1057 1057 to the *manifests segment*.
1058 1058
1059 1059 Manifest Segment
1060 ----------------
1060 ================
1061 1061
1062 1062 The *manifest segment* consists of a single *delta group* holding manifest
1063 1063 data. It is followed by an *empty chunk* to denote the boundary to the
1064 1064 *filelogs segment*.
1065 1065
1066 1066 Filelogs Segment
1067 ----------------
1067 ================
1068 1068
1069 1069 The *filelogs* segment consists of multiple sub-segments, each
1070 1070 corresponding to an individual file whose data is being described:
1071 1071
1072 1072 +--------------------------------------+
1073 1073 | | | | |
1074 1074 | filelog0 | filelog1 | filelog2 | ... |
1075 1075 | | | | |
1076 1076 +--------------------------------------+
1077 1077
1078 1078 In version "3" of the changegroup format, filelogs may include directory
1079 1079 logs when treemanifests are in use. directory logs are identified by
1080 1080 having a trailing '/' on their filename (see below).
1081 1081
1082 1082 The final filelog sub-segment is followed by an *empty chunk* to denote
1083 1083 the end of the segment and the overall changegroup.
1084 1084
1085 1085 Each filelog sub-segment consists of the following:
1086 1086
1087 1087 +------------------------------------------+
1088 1088 | | | |
1089 1089 | filename size | filename | delta group |
1090 1090 | (32 bits) | (various) | (various) |
1091 1091 | | | |
1092 1092 +------------------------------------------+
1093 1093
1094 1094 That is, a *chunk* consisting of the filename (not terminated or padded)
1095 1095 followed by N chunks constituting the *delta group* for this file.
1096 1096
1097 1097 Test list of commands with command with no help text
1098 1098
1099 1099 $ hg help helpext
1100 1100 helpext extension - no help text available
1101 1101
1102 1102 list of commands:
1103 1103
1104 1104 nohelp (no help text available)
1105 1105
1106 1106 (use "hg help -v helpext" to show built-in aliases and global options)
1107 1107
1108 1108
1109 1109 test deprecated and experimental options are hidden in command help
1110 1110 $ hg help debugoptDEP
1111 1111 hg debugoptDEP
1112 1112
1113 1113 (no help text available)
1114 1114
1115 1115 options:
1116 1116
1117 1117 (some details hidden, use --verbose to show complete help)
1118 1118
1119 1119 $ hg help debugoptEXP
1120 1120 hg debugoptEXP
1121 1121
1122 1122 (no help text available)
1123 1123
1124 1124 options:
1125 1125
1126 1126 (some details hidden, use --verbose to show complete help)
1127 1127
1128 1128 test deprecated and experimental options is shown with -v
1129 1129 $ hg help -v debugoptDEP | grep dopt
1130 1130 --dopt option is (DEPRECATED)
1131 1131 $ hg help -v debugoptEXP | grep eopt
1132 1132 --eopt option is (EXPERIMENTAL)
1133 1133
1134 1134 #if gettext
1135 1135 test deprecated option is hidden with translation with untranslated description
1136 1136 (use many globy for not failing on changed transaction)
1137 1137 $ LANGUAGE=sv hg help debugoptDEP
1138 1138 hg debugoptDEP
1139 1139
1140 1140 (*) (glob)
1141 1141
1142 1142 options:
1143 1143
1144 1144 (some details hidden, use --verbose to show complete help)
1145 1145 #endif
1146 1146
1147 1147 Test commands that collide with topics (issue4240)
1148 1148
1149 1149 $ hg config -hq
1150 1150 hg config [-u] [NAME]...
1151 1151
1152 1152 show combined config settings from all hgrc files
1153 1153 $ hg showconfig -hq
1154 1154 hg config [-u] [NAME]...
1155 1155
1156 1156 show combined config settings from all hgrc files
1157 1157
1158 1158 Test a help topic
1159 1159
1160 1160 $ hg help revs
1161 1161 Specifying Single Revisions
1162 1162 """""""""""""""""""""""""""
1163 1163
1164 1164 Mercurial supports several ways to specify individual revisions.
1165 1165
1166 1166 A plain integer is treated as a revision number. Negative integers are
1167 1167 treated as sequential offsets from the tip, with -1 denoting the tip, -2
1168 1168 denoting the revision prior to the tip, and so forth.
1169 1169
1170 1170 A 40-digit hexadecimal string is treated as a unique revision identifier.
1171 1171
1172 1172 A hexadecimal string less than 40 characters long is treated as a unique
1173 1173 revision identifier and is referred to as a short-form identifier. A
1174 1174 short-form identifier is only valid if it is the prefix of exactly one
1175 1175 full-length identifier.
1176 1176
1177 1177 Any other string is treated as a bookmark, tag, or branch name. A bookmark
1178 1178 is a movable pointer to a revision. A tag is a permanent name associated
1179 1179 with a revision. A branch name denotes the tipmost open branch head of
1180 1180 that branch - or if they are all closed, the tipmost closed head of the
1181 1181 branch. Bookmark, tag, and branch names must not contain the ":"
1182 1182 character.
1183 1183
1184 1184 The reserved name "tip" always identifies the most recent revision.
1185 1185
1186 1186 The reserved name "null" indicates the null revision. This is the revision
1187 1187 of an empty repository, and the parent of revision 0.
1188 1188
1189 1189 The reserved name "." indicates the working directory parent. If no
1190 1190 working directory is checked out, it is equivalent to null. If an
1191 1191 uncommitted merge is in progress, "." is the revision of the first parent.
1192 1192
1193 1193 Test repeated config section name
1194 1194
1195 1195 $ hg help config.host
1196 1196 "http_proxy.host"
1197 1197 Host name and (optional) port of the proxy server, for example
1198 1198 "myproxy:8000".
1199 1199
1200 1200 "smtp.host"
1201 1201 Host name of mail server, e.g. "mail.example.com".
1202 1202
1203 1203 Unrelated trailing paragraphs shouldn't be included
1204 1204
1205 1205 $ hg help config.extramsg | grep '^$'
1206 1206
1207 1207
1208 1208 Test capitalized section name
1209 1209
1210 1210 $ hg help scripting.HGPLAIN > /dev/null
1211 1211
1212 1212 Help subsection:
1213 1213
1214 1214 $ hg help config.charsets |grep "Email example:" > /dev/null
1215 1215 [1]
1216 1216
1217 1217 Show nested definitions
1218 1218 ("profiling.type"[break]"ls"[break]"stat"[break])
1219 1219
1220 1220 $ hg help config.type | egrep '^$'|wc -l
1221 1221 \s*3 (re)
1222 1222
1223 1223 Separate sections from subsections
1224 1224
1225 1225 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1226 1226 "format"
1227 1227 --------
1228 1228
1229 1229 "usegeneraldelta"
1230 1230
1231 1231 "dotencode"
1232 1232
1233 1233 "usefncache"
1234 1234
1235 1235 "usestore"
1236 1236
1237 1237 "profiling"
1238 1238 -----------
1239 1239
1240 1240 "format"
1241 1241
1242 1242 "progress"
1243 1243 ----------
1244 1244
1245 1245 "format"
1246 1246
1247 1247
1248 1248 Last item in help config.*:
1249 1249
1250 1250 $ hg help config.`hg help config|grep '^ "'| \
1251 1251 > tail -1|sed 's![ "]*!!g'`| \
1252 1252 > grep "hg help -c config" > /dev/null
1253 1253 [1]
1254 1254
1255 1255 note to use help -c for general hg help config:
1256 1256
1257 1257 $ hg help config |grep "hg help -c config" > /dev/null
1258 1258
1259 1259 Test templating help
1260 1260
1261 1261 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1262 1262 desc String. The text of the changeset description.
1263 1263 diffstat String. Statistics of changes with the following format:
1264 1264 firstline Any text. Returns the first line of text.
1265 1265 nonempty Any text. Returns '(none)' if the string is empty.
1266 1266
1267 1267 Test deprecated items
1268 1268
1269 1269 $ hg help -v templating | grep currentbookmark
1270 1270 currentbookmark
1271 1271 $ hg help templating | (grep currentbookmark || true)
1272 1272
1273 1273 Test help hooks
1274 1274
1275 1275 $ cat > helphook1.py <<EOF
1276 1276 > from mercurial import help
1277 1277 >
1278 1278 > def rewrite(ui, topic, doc):
1279 1279 > return doc + '\nhelphook1\n'
1280 1280 >
1281 1281 > def extsetup(ui):
1282 1282 > help.addtopichook('revsets', rewrite)
1283 1283 > EOF
1284 1284 $ cat > helphook2.py <<EOF
1285 1285 > from mercurial import help
1286 1286 >
1287 1287 > def rewrite(ui, topic, doc):
1288 1288 > return doc + '\nhelphook2\n'
1289 1289 >
1290 1290 > def extsetup(ui):
1291 1291 > help.addtopichook('revsets', rewrite)
1292 1292 > EOF
1293 1293 $ echo '[extensions]' >> $HGRCPATH
1294 1294 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1295 1295 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1296 1296 $ hg help revsets | grep helphook
1297 1297 helphook1
1298 1298 helphook2
1299 1299
1300 1300 help -c should only show debug --debug
1301 1301
1302 1302 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1303 1303 [1]
1304 1304
1305 1305 help -c should only show deprecated for -v
1306 1306
1307 1307 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1308 1308 [1]
1309 1309
1310 1310 Test -s / --system
1311 1311
1312 1312 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1313 1313 > wc -l | sed -e 's/ //g'
1314 1314 0
1315 1315 $ hg help config.files --system unix | grep 'USER' | \
1316 1316 > wc -l | sed -e 's/ //g'
1317 1317 0
1318 1318
1319 1319 Test -e / -c / -k combinations
1320 1320
1321 1321 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1322 1322 Commands:
1323 1323 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1324 1324 Extensions:
1325 1325 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1326 1326 Topics:
1327 1327 Commands:
1328 1328 Extensions:
1329 1329 Extension Commands:
1330 1330 $ hg help -c schemes
1331 1331 abort: no such help topic: schemes
1332 1332 (try "hg help --keyword schemes")
1333 1333 [255]
1334 1334 $ hg help -e schemes |head -1
1335 1335 schemes extension - extend schemes with shortcuts to repository swarms
1336 1336 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1337 1337 Commands:
1338 1338 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1339 1339 Extensions:
1340 1340 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1341 1341 Extensions:
1342 1342 Commands:
1343 1343 $ hg help -c commit > /dev/null
1344 1344 $ hg help -e -c commit > /dev/null
1345 1345 $ hg help -e commit > /dev/null
1346 1346 abort: no such help topic: commit
1347 1347 (try "hg help --keyword commit")
1348 1348 [255]
1349 1349
1350 1350 Test keyword search help
1351 1351
1352 1352 $ cat > prefixedname.py <<EOF
1353 1353 > '''matched against word "clone"
1354 1354 > '''
1355 1355 > EOF
1356 1356 $ echo '[extensions]' >> $HGRCPATH
1357 1357 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1358 1358 $ hg help -k clone
1359 1359 Topics:
1360 1360
1361 1361 config Configuration Files
1362 1362 extensions Using Additional Features
1363 1363 glossary Glossary
1364 1364 phases Working with Phases
1365 1365 subrepos Subrepositories
1366 1366 urls URL Paths
1367 1367
1368 1368 Commands:
1369 1369
1370 1370 bookmarks create a new bookmark or list existing bookmarks
1371 1371 clone make a copy of an existing repository
1372 1372 paths show aliases for remote repositories
1373 1373 update update working directory (or switch revisions)
1374 1374
1375 1375 Extensions:
1376 1376
1377 1377 clonebundles advertise pre-generated bundles to seed clones
1378 1378 prefixedname matched against word "clone"
1379 1379 relink recreates hardlinks between repository clones
1380 1380
1381 1381 Extension Commands:
1382 1382
1383 1383 qclone clone main and patch repository at same time
1384 1384
1385 1385 Test unfound topic
1386 1386
1387 1387 $ hg help nonexistingtopicthatwillneverexisteverever
1388 1388 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1389 1389 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1390 1390 [255]
1391 1391
1392 1392 Test unfound keyword
1393 1393
1394 1394 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1395 1395 abort: no matches
1396 1396 (try "hg help" for a list of topics)
1397 1397 [255]
1398 1398
1399 1399 Test omit indicating for help
1400 1400
1401 1401 $ cat > addverboseitems.py <<EOF
1402 1402 > '''extension to test omit indicating.
1403 1403 >
1404 1404 > This paragraph is never omitted (for extension)
1405 1405 >
1406 1406 > .. container:: verbose
1407 1407 >
1408 1408 > This paragraph is omitted,
1409 1409 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1410 1410 >
1411 1411 > This paragraph is never omitted, too (for extension)
1412 1412 > '''
1413 1413 >
1414 1414 > from mercurial import help, commands
1415 1415 > testtopic = """This paragraph is never omitted (for topic).
1416 1416 >
1417 1417 > .. container:: verbose
1418 1418 >
1419 1419 > This paragraph is omitted,
1420 1420 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1421 1421 >
1422 1422 > This paragraph is never omitted, too (for topic)
1423 1423 > """
1424 1424 > def extsetup(ui):
1425 1425 > help.helptable.append((["topic-containing-verbose"],
1426 1426 > "This is the topic to test omit indicating.",
1427 1427 > lambda ui: testtopic))
1428 1428 > EOF
1429 1429 $ echo '[extensions]' >> $HGRCPATH
1430 1430 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1431 1431 $ hg help addverboseitems
1432 1432 addverboseitems extension - extension to test omit indicating.
1433 1433
1434 1434 This paragraph is never omitted (for extension)
1435 1435
1436 1436 This paragraph is never omitted, too (for extension)
1437 1437
1438 1438 (some details hidden, use --verbose to show complete help)
1439 1439
1440 1440 no commands defined
1441 1441 $ hg help -v addverboseitems
1442 1442 addverboseitems extension - extension to test omit indicating.
1443 1443
1444 1444 This paragraph is never omitted (for extension)
1445 1445
1446 1446 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1447 1447 extension)
1448 1448
1449 1449 This paragraph is never omitted, too (for extension)
1450 1450
1451 1451 no commands defined
1452 1452 $ hg help topic-containing-verbose
1453 1453 This is the topic to test omit indicating.
1454 1454 """"""""""""""""""""""""""""""""""""""""""
1455 1455
1456 1456 This paragraph is never omitted (for topic).
1457 1457
1458 1458 This paragraph is never omitted, too (for topic)
1459 1459
1460 1460 (some details hidden, use --verbose to show complete help)
1461 1461 $ hg help -v topic-containing-verbose
1462 1462 This is the topic to test omit indicating.
1463 1463 """"""""""""""""""""""""""""""""""""""""""
1464 1464
1465 1465 This paragraph is never omitted (for topic).
1466 1466
1467 1467 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1468 1468 topic)
1469 1469
1470 1470 This paragraph is never omitted, too (for topic)
1471 1471
1472 1472 Test section lookup
1473 1473
1474 1474 $ hg help revset.merge
1475 1475 "merge()"
1476 1476 Changeset is a merge changeset.
1477 1477
1478 1478 $ hg help glossary.dag
1479 1479 DAG
1480 1480 The repository of changesets of a distributed version control system
1481 1481 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1482 1482 of nodes and edges, where nodes correspond to changesets and edges
1483 1483 imply a parent -> child relation. This graph can be visualized by
1484 1484 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1485 1485 limited by the requirement for children to have at most two parents.
1486 1486
1487 1487
1488 1488 $ hg help hgrc.paths
1489 1489 "paths"
1490 1490 -------
1491 1491
1492 1492 Assigns symbolic names and behavior to repositories.
1493 1493
1494 1494 Options are symbolic names defining the URL or directory that is the
1495 1495 location of the repository. Example:
1496 1496
1497 1497 [paths]
1498 1498 my_server = https://example.com/my_repo
1499 1499 local_path = /home/me/repo
1500 1500
1501 1501 These symbolic names can be used from the command line. To pull from
1502 1502 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1503 1503 local_path'.
1504 1504
1505 1505 Options containing colons (":") denote sub-options that can influence
1506 1506 behavior for that specific path. Example:
1507 1507
1508 1508 [paths]
1509 1509 my_server = https://example.com/my_path
1510 1510 my_server:pushurl = ssh://example.com/my_path
1511 1511
1512 1512 The following sub-options can be defined:
1513 1513
1514 1514 "pushurl"
1515 1515 The URL to use for push operations. If not defined, the location
1516 1516 defined by the path's main entry is used.
1517 1517
1518 1518 "pushrev"
1519 1519 A revset defining which revisions to push by default.
1520 1520
1521 1521 When 'hg push' is executed without a "-r" argument, the revset defined
1522 1522 by this sub-option is evaluated to determine what to push.
1523 1523
1524 1524 For example, a value of "." will push the working directory's revision
1525 1525 by default.
1526 1526
1527 1527 Revsets specifying bookmarks will not result in the bookmark being
1528 1528 pushed.
1529 1529
1530 1530 The following special named paths exist:
1531 1531
1532 1532 "default"
1533 1533 The URL or directory to use when no source or remote is specified.
1534 1534
1535 1535 'hg clone' will automatically define this path to the location the
1536 1536 repository was cloned from.
1537 1537
1538 1538 "default-push"
1539 1539 (deprecated) The URL or directory for the default 'hg push' location.
1540 1540 "default:pushurl" should be used instead.
1541 1541
1542 1542 $ hg help glossary.mcguffin
1543 1543 abort: help section not found
1544 1544 [255]
1545 1545
1546 1546 $ hg help glossary.mc.guffin
1547 1547 abort: help section not found
1548 1548 [255]
1549 1549
1550 1550 $ hg help template.files
1551 1551 files List of strings. All files modified, added, or removed by
1552 1552 this changeset.
1553 1553
1554 1554 Test section lookup by translated message
1555 1555
1556 1556 str.lower() instead of encoding.lower(str) on translated message might
1557 1557 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1558 1558 as the second or later byte of multi-byte character.
1559 1559
1560 1560 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1561 1561 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1562 1562 replacement makes message meaningless.
1563 1563
1564 1564 This tests that section lookup by translated string isn't broken by
1565 1565 such str.lower().
1566 1566
1567 1567 $ python <<EOF
1568 1568 > def escape(s):
1569 1569 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1570 1570 > # translation of "record" in ja_JP.cp932
1571 1571 > upper = "\x8bL\x98^"
1572 1572 > # str.lower()-ed section name should be treated as different one
1573 1573 > lower = "\x8bl\x98^"
1574 1574 > with open('ambiguous.py', 'w') as fp:
1575 1575 > fp.write("""# ambiguous section names in ja_JP.cp932
1576 1576 > u'''summary of extension
1577 1577 >
1578 1578 > %s
1579 1579 > ----
1580 1580 >
1581 1581 > Upper name should show only this message
1582 1582 >
1583 1583 > %s
1584 1584 > ----
1585 1585 >
1586 1586 > Lower name should show only this message
1587 1587 >
1588 1588 > subsequent section
1589 1589 > ------------------
1590 1590 >
1591 1591 > This should be hidden at "hg help ambiguous" with section name.
1592 1592 > '''
1593 1593 > """ % (escape(upper), escape(lower)))
1594 1594 > EOF
1595 1595
1596 1596 $ cat >> $HGRCPATH <<EOF
1597 1597 > [extensions]
1598 1598 > ambiguous = ./ambiguous.py
1599 1599 > EOF
1600 1600
1601 1601 $ python <<EOF | sh
1602 1602 > upper = "\x8bL\x98^"
1603 1603 > print "hg --encoding cp932 help -e ambiguous.%s" % upper
1604 1604 > EOF
1605 1605 \x8bL\x98^ (esc)
1606 1606 ----
1607 1607
1608 1608 Upper name should show only this message
1609 1609
1610 1610
1611 1611 $ python <<EOF | sh
1612 1612 > lower = "\x8bl\x98^"
1613 1613 > print "hg --encoding cp932 help -e ambiguous.%s" % lower
1614 1614 > EOF
1615 1615 \x8bl\x98^ (esc)
1616 1616 ----
1617 1617
1618 1618 Lower name should show only this message
1619 1619
1620 1620
1621 1621 $ cat >> $HGRCPATH <<EOF
1622 1622 > [extensions]
1623 1623 > ambiguous = !
1624 1624 > EOF
1625 1625
1626 1626 Test dynamic list of merge tools only shows up once
1627 1627 $ hg help merge-tools
1628 1628 Merge Tools
1629 1629 """""""""""
1630 1630
1631 1631 To merge files Mercurial uses merge tools.
1632 1632
1633 1633 A merge tool combines two different versions of a file into a merged file.
1634 1634 Merge tools are given the two files and the greatest common ancestor of
1635 1635 the two file versions, so they can determine the changes made on both
1636 1636 branches.
1637 1637
1638 1638 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1639 1639 backout' and in several extensions.
1640 1640
1641 1641 Usually, the merge tool tries to automatically reconcile the files by
1642 1642 combining all non-overlapping changes that occurred separately in the two
1643 1643 different evolutions of the same initial base file. Furthermore, some
1644 1644 interactive merge programs make it easier to manually resolve conflicting
1645 1645 merges, either in a graphical way, or by inserting some conflict markers.
1646 1646 Mercurial does not include any interactive merge programs but relies on
1647 1647 external tools for that.
1648 1648
1649 1649 Available merge tools
1650 1650 =====================
1651 1651
1652 1652 External merge tools and their properties are configured in the merge-
1653 1653 tools configuration section - see hgrc(5) - but they can often just be
1654 1654 named by their executable.
1655 1655
1656 1656 A merge tool is generally usable if its executable can be found on the
1657 1657 system and if it can handle the merge. The executable is found if it is an
1658 1658 absolute or relative executable path or the name of an application in the
1659 1659 executable search path. The tool is assumed to be able to handle the merge
1660 1660 if it can handle symlinks if the file is a symlink, if it can handle
1661 1661 binary files if the file is binary, and if a GUI is available if the tool
1662 1662 requires a GUI.
1663 1663
1664 1664 There are some internal merge tools which can be used. The internal merge
1665 1665 tools are:
1666 1666
1667 1667 ":dump"
1668 1668 Creates three versions of the files to merge, containing the contents of
1669 1669 local, other and base. These files can then be used to perform a merge
1670 1670 manually. If the file to be merged is named "a.txt", these files will
1671 1671 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1672 1672 they will be placed in the same directory as "a.txt".
1673 1673
1674 1674 ":fail"
1675 1675 Rather than attempting to merge files that were modified on both
1676 1676 branches, it marks them as unresolved. The resolve command must be used
1677 1677 to resolve these conflicts.
1678 1678
1679 1679 ":local"
1680 1680 Uses the local 'p1()' version of files as the merged version.
1681 1681
1682 1682 ":merge"
1683 1683 Uses the internal non-interactive simple merge algorithm for merging
1684 1684 files. It will fail if there are any conflicts and leave markers in the
1685 1685 partially merged file. Markers will have two sections, one for each side
1686 1686 of merge.
1687 1687
1688 1688 ":merge-local"
1689 1689 Like :merge, but resolve all conflicts non-interactively in favor of the
1690 1690 local 'p1()' changes.
1691 1691
1692 1692 ":merge-other"
1693 1693 Like :merge, but resolve all conflicts non-interactively in favor of the
1694 1694 other 'p2()' changes.
1695 1695
1696 1696 ":merge3"
1697 1697 Uses the internal non-interactive simple merge algorithm for merging
1698 1698 files. It will fail if there are any conflicts and leave markers in the
1699 1699 partially merged file. Marker will have three sections, one from each
1700 1700 side of the merge and one for the base content.
1701 1701
1702 1702 ":other"
1703 1703 Uses the other 'p2()' version of files as the merged version.
1704 1704
1705 1705 ":prompt"
1706 1706 Asks the user which of the local 'p1()' or the other 'p2()' version to
1707 1707 keep as the merged version.
1708 1708
1709 1709 ":tagmerge"
1710 1710 Uses the internal tag merge algorithm (experimental).
1711 1711
1712 1712 ":union"
1713 1713 Uses the internal non-interactive simple merge algorithm for merging
1714 1714 files. It will use both left and right sides for conflict regions. No
1715 1715 markers are inserted.
1716 1716
1717 1717 Internal tools are always available and do not require a GUI but will by
1718 1718 default not handle symlinks or binary files.
1719 1719
1720 1720 Choosing a merge tool
1721 1721 =====================
1722 1722
1723 1723 Mercurial uses these rules when deciding which merge tool to use:
1724 1724
1725 1725 1. If a tool has been specified with the --tool option to merge or
1726 1726 resolve, it is used. If it is the name of a tool in the merge-tools
1727 1727 configuration, its configuration is used. Otherwise the specified tool
1728 1728 must be executable by the shell.
1729 1729 2. If the "HGMERGE" environment variable is present, its value is used and
1730 1730 must be executable by the shell.
1731 1731 3. If the filename of the file to be merged matches any of the patterns in
1732 1732 the merge-patterns configuration section, the first usable merge tool
1733 1733 corresponding to a matching pattern is used. Here, binary capabilities
1734 1734 of the merge tool are not considered.
1735 1735 4. If ui.merge is set it will be considered next. If the value is not the
1736 1736 name of a configured tool, the specified value is used and must be
1737 1737 executable by the shell. Otherwise the named tool is used if it is
1738 1738 usable.
1739 1739 5. If any usable merge tools are present in the merge-tools configuration
1740 1740 section, the one with the highest priority is used.
1741 1741 6. If a program named "hgmerge" can be found on the system, it is used -
1742 1742 but it will by default not be used for symlinks and binary files.
1743 1743 7. If the file to be merged is not binary and is not a symlink, then
1744 1744 internal ":merge" is used.
1745 1745 8. The merge of the file fails and must be resolved before commit.
1746 1746
1747 1747 Note:
1748 1748 After selecting a merge program, Mercurial will by default attempt to
1749 1749 merge the files using a simple merge algorithm first. Only if it
1750 1750 doesn't succeed because of conflicting changes Mercurial will actually
1751 1751 execute the merge program. Whether to use the simple merge algorithm
1752 1752 first can be controlled by the premerge setting of the merge tool.
1753 1753 Premerge is enabled by default unless the file is binary or a symlink.
1754 1754
1755 1755 See the merge-tools and ui sections of hgrc(5) for details on the
1756 1756 configuration of merge tools.
1757 1757
1758 1758 Test usage of section marks in help documents
1759 1759
1760 1760 $ cd "$TESTDIR"/../doc
1761 1761 $ python check-seclevel.py
1762 1762 $ cd $TESTTMP
1763 1763
1764 1764 #if serve
1765 1765
1766 1766 Test the help pages in hgweb.
1767 1767
1768 1768 Dish up an empty repo; serve it cold.
1769 1769
1770 1770 $ hg init "$TESTTMP/test"
1771 1771 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1772 1772 $ cat hg.pid >> $DAEMON_PIDS
1773 1773
1774 1774 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1775 1775 200 Script output follows
1776 1776
1777 1777 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1778 1778 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1779 1779 <head>
1780 1780 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1781 1781 <meta name="robots" content="index, nofollow" />
1782 1782 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1783 1783 <script type="text/javascript" src="/static/mercurial.js"></script>
1784 1784
1785 1785 <title>Help: Index</title>
1786 1786 </head>
1787 1787 <body>
1788 1788
1789 1789 <div class="container">
1790 1790 <div class="menu">
1791 1791 <div class="logo">
1792 1792 <a href="https://mercurial-scm.org/">
1793 1793 <img src="/static/hglogo.png" alt="mercurial" /></a>
1794 1794 </div>
1795 1795 <ul>
1796 1796 <li><a href="/shortlog">log</a></li>
1797 1797 <li><a href="/graph">graph</a></li>
1798 1798 <li><a href="/tags">tags</a></li>
1799 1799 <li><a href="/bookmarks">bookmarks</a></li>
1800 1800 <li><a href="/branches">branches</a></li>
1801 1801 </ul>
1802 1802 <ul>
1803 1803 <li class="active">help</li>
1804 1804 </ul>
1805 1805 </div>
1806 1806
1807 1807 <div class="main">
1808 1808 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1809 1809 <form class="search" action="/log">
1810 1810
1811 1811 <p><input name="rev" id="search1" type="text" size="30" /></p>
1812 1812 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1813 1813 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1814 1814 </form>
1815 1815 <table class="bigtable">
1816 1816 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1817 1817
1818 1818 <tr><td>
1819 1819 <a href="/help/config">
1820 1820 config
1821 1821 </a>
1822 1822 </td><td>
1823 1823 Configuration Files
1824 1824 </td></tr>
1825 1825 <tr><td>
1826 1826 <a href="/help/dates">
1827 1827 dates
1828 1828 </a>
1829 1829 </td><td>
1830 1830 Date Formats
1831 1831 </td></tr>
1832 1832 <tr><td>
1833 1833 <a href="/help/diffs">
1834 1834 diffs
1835 1835 </a>
1836 1836 </td><td>
1837 1837 Diff Formats
1838 1838 </td></tr>
1839 1839 <tr><td>
1840 1840 <a href="/help/environment">
1841 1841 environment
1842 1842 </a>
1843 1843 </td><td>
1844 1844 Environment Variables
1845 1845 </td></tr>
1846 1846 <tr><td>
1847 1847 <a href="/help/extensions">
1848 1848 extensions
1849 1849 </a>
1850 1850 </td><td>
1851 1851 Using Additional Features
1852 1852 </td></tr>
1853 1853 <tr><td>
1854 1854 <a href="/help/filesets">
1855 1855 filesets
1856 1856 </a>
1857 1857 </td><td>
1858 1858 Specifying File Sets
1859 1859 </td></tr>
1860 1860 <tr><td>
1861 1861 <a href="/help/glossary">
1862 1862 glossary
1863 1863 </a>
1864 1864 </td><td>
1865 1865 Glossary
1866 1866 </td></tr>
1867 1867 <tr><td>
1868 1868 <a href="/help/hgignore">
1869 1869 hgignore
1870 1870 </a>
1871 1871 </td><td>
1872 1872 Syntax for Mercurial Ignore Files
1873 1873 </td></tr>
1874 1874 <tr><td>
1875 1875 <a href="/help/hgweb">
1876 1876 hgweb
1877 1877 </a>
1878 1878 </td><td>
1879 1879 Configuring hgweb
1880 1880 </td></tr>
1881 1881 <tr><td>
1882 1882 <a href="/help/internals">
1883 1883 internals
1884 1884 </a>
1885 1885 </td><td>
1886 1886 Technical implementation topics
1887 1887 </td></tr>
1888 1888 <tr><td>
1889 1889 <a href="/help/merge-tools">
1890 1890 merge-tools
1891 1891 </a>
1892 1892 </td><td>
1893 1893 Merge Tools
1894 1894 </td></tr>
1895 1895 <tr><td>
1896 1896 <a href="/help/multirevs">
1897 1897 multirevs
1898 1898 </a>
1899 1899 </td><td>
1900 1900 Specifying Multiple Revisions
1901 1901 </td></tr>
1902 1902 <tr><td>
1903 1903 <a href="/help/patterns">
1904 1904 patterns
1905 1905 </a>
1906 1906 </td><td>
1907 1907 File Name Patterns
1908 1908 </td></tr>
1909 1909 <tr><td>
1910 1910 <a href="/help/phases">
1911 1911 phases
1912 1912 </a>
1913 1913 </td><td>
1914 1914 Working with Phases
1915 1915 </td></tr>
1916 1916 <tr><td>
1917 1917 <a href="/help/revisions">
1918 1918 revisions
1919 1919 </a>
1920 1920 </td><td>
1921 1921 Specifying Single Revisions
1922 1922 </td></tr>
1923 1923 <tr><td>
1924 1924 <a href="/help/revsets">
1925 1925 revsets
1926 1926 </a>
1927 1927 </td><td>
1928 1928 Specifying Revision Sets
1929 1929 </td></tr>
1930 1930 <tr><td>
1931 1931 <a href="/help/scripting">
1932 1932 scripting
1933 1933 </a>
1934 1934 </td><td>
1935 1935 Using Mercurial from scripts and automation
1936 1936 </td></tr>
1937 1937 <tr><td>
1938 1938 <a href="/help/subrepos">
1939 1939 subrepos
1940 1940 </a>
1941 1941 </td><td>
1942 1942 Subrepositories
1943 1943 </td></tr>
1944 1944 <tr><td>
1945 1945 <a href="/help/templating">
1946 1946 templating
1947 1947 </a>
1948 1948 </td><td>
1949 1949 Template Usage
1950 1950 </td></tr>
1951 1951 <tr><td>
1952 1952 <a href="/help/urls">
1953 1953 urls
1954 1954 </a>
1955 1955 </td><td>
1956 1956 URL Paths
1957 1957 </td></tr>
1958 1958 <tr><td>
1959 1959 <a href="/help/topic-containing-verbose">
1960 1960 topic-containing-verbose
1961 1961 </a>
1962 1962 </td><td>
1963 1963 This is the topic to test omit indicating.
1964 1964 </td></tr>
1965 1965
1966 1966
1967 1967 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1968 1968
1969 1969 <tr><td>
1970 1970 <a href="/help/add">
1971 1971 add
1972 1972 </a>
1973 1973 </td><td>
1974 1974 add the specified files on the next commit
1975 1975 </td></tr>
1976 1976 <tr><td>
1977 1977 <a href="/help/annotate">
1978 1978 annotate
1979 1979 </a>
1980 1980 </td><td>
1981 1981 show changeset information by line for each file
1982 1982 </td></tr>
1983 1983 <tr><td>
1984 1984 <a href="/help/clone">
1985 1985 clone
1986 1986 </a>
1987 1987 </td><td>
1988 1988 make a copy of an existing repository
1989 1989 </td></tr>
1990 1990 <tr><td>
1991 1991 <a href="/help/commit">
1992 1992 commit
1993 1993 </a>
1994 1994 </td><td>
1995 1995 commit the specified files or all outstanding changes
1996 1996 </td></tr>
1997 1997 <tr><td>
1998 1998 <a href="/help/diff">
1999 1999 diff
2000 2000 </a>
2001 2001 </td><td>
2002 2002 diff repository (or selected files)
2003 2003 </td></tr>
2004 2004 <tr><td>
2005 2005 <a href="/help/export">
2006 2006 export
2007 2007 </a>
2008 2008 </td><td>
2009 2009 dump the header and diffs for one or more changesets
2010 2010 </td></tr>
2011 2011 <tr><td>
2012 2012 <a href="/help/forget">
2013 2013 forget
2014 2014 </a>
2015 2015 </td><td>
2016 2016 forget the specified files on the next commit
2017 2017 </td></tr>
2018 2018 <tr><td>
2019 2019 <a href="/help/init">
2020 2020 init
2021 2021 </a>
2022 2022 </td><td>
2023 2023 create a new repository in the given directory
2024 2024 </td></tr>
2025 2025 <tr><td>
2026 2026 <a href="/help/log">
2027 2027 log
2028 2028 </a>
2029 2029 </td><td>
2030 2030 show revision history of entire repository or files
2031 2031 </td></tr>
2032 2032 <tr><td>
2033 2033 <a href="/help/merge">
2034 2034 merge
2035 2035 </a>
2036 2036 </td><td>
2037 2037 merge another revision into working directory
2038 2038 </td></tr>
2039 2039 <tr><td>
2040 2040 <a href="/help/pull">
2041 2041 pull
2042 2042 </a>
2043 2043 </td><td>
2044 2044 pull changes from the specified source
2045 2045 </td></tr>
2046 2046 <tr><td>
2047 2047 <a href="/help/push">
2048 2048 push
2049 2049 </a>
2050 2050 </td><td>
2051 2051 push changes to the specified destination
2052 2052 </td></tr>
2053 2053 <tr><td>
2054 2054 <a href="/help/remove">
2055 2055 remove
2056 2056 </a>
2057 2057 </td><td>
2058 2058 remove the specified files on the next commit
2059 2059 </td></tr>
2060 2060 <tr><td>
2061 2061 <a href="/help/serve">
2062 2062 serve
2063 2063 </a>
2064 2064 </td><td>
2065 2065 start stand-alone webserver
2066 2066 </td></tr>
2067 2067 <tr><td>
2068 2068 <a href="/help/status">
2069 2069 status
2070 2070 </a>
2071 2071 </td><td>
2072 2072 show changed files in the working directory
2073 2073 </td></tr>
2074 2074 <tr><td>
2075 2075 <a href="/help/summary">
2076 2076 summary
2077 2077 </a>
2078 2078 </td><td>
2079 2079 summarize working directory state
2080 2080 </td></tr>
2081 2081 <tr><td>
2082 2082 <a href="/help/update">
2083 2083 update
2084 2084 </a>
2085 2085 </td><td>
2086 2086 update working directory (or switch revisions)
2087 2087 </td></tr>
2088 2088
2089 2089
2090 2090
2091 2091 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2092 2092
2093 2093 <tr><td>
2094 2094 <a href="/help/addremove">
2095 2095 addremove
2096 2096 </a>
2097 2097 </td><td>
2098 2098 add all new files, delete all missing files
2099 2099 </td></tr>
2100 2100 <tr><td>
2101 2101 <a href="/help/archive">
2102 2102 archive
2103 2103 </a>
2104 2104 </td><td>
2105 2105 create an unversioned archive of a repository revision
2106 2106 </td></tr>
2107 2107 <tr><td>
2108 2108 <a href="/help/backout">
2109 2109 backout
2110 2110 </a>
2111 2111 </td><td>
2112 2112 reverse effect of earlier changeset
2113 2113 </td></tr>
2114 2114 <tr><td>
2115 2115 <a href="/help/bisect">
2116 2116 bisect
2117 2117 </a>
2118 2118 </td><td>
2119 2119 subdivision search of changesets
2120 2120 </td></tr>
2121 2121 <tr><td>
2122 2122 <a href="/help/bookmarks">
2123 2123 bookmarks
2124 2124 </a>
2125 2125 </td><td>
2126 2126 create a new bookmark or list existing bookmarks
2127 2127 </td></tr>
2128 2128 <tr><td>
2129 2129 <a href="/help/branch">
2130 2130 branch
2131 2131 </a>
2132 2132 </td><td>
2133 2133 set or show the current branch name
2134 2134 </td></tr>
2135 2135 <tr><td>
2136 2136 <a href="/help/branches">
2137 2137 branches
2138 2138 </a>
2139 2139 </td><td>
2140 2140 list repository named branches
2141 2141 </td></tr>
2142 2142 <tr><td>
2143 2143 <a href="/help/bundle">
2144 2144 bundle
2145 2145 </a>
2146 2146 </td><td>
2147 2147 create a changegroup file
2148 2148 </td></tr>
2149 2149 <tr><td>
2150 2150 <a href="/help/cat">
2151 2151 cat
2152 2152 </a>
2153 2153 </td><td>
2154 2154 output the current or given revision of files
2155 2155 </td></tr>
2156 2156 <tr><td>
2157 2157 <a href="/help/config">
2158 2158 config
2159 2159 </a>
2160 2160 </td><td>
2161 2161 show combined config settings from all hgrc files
2162 2162 </td></tr>
2163 2163 <tr><td>
2164 2164 <a href="/help/copy">
2165 2165 copy
2166 2166 </a>
2167 2167 </td><td>
2168 2168 mark files as copied for the next commit
2169 2169 </td></tr>
2170 2170 <tr><td>
2171 2171 <a href="/help/files">
2172 2172 files
2173 2173 </a>
2174 2174 </td><td>
2175 2175 list tracked files
2176 2176 </td></tr>
2177 2177 <tr><td>
2178 2178 <a href="/help/graft">
2179 2179 graft
2180 2180 </a>
2181 2181 </td><td>
2182 2182 copy changes from other branches onto the current branch
2183 2183 </td></tr>
2184 2184 <tr><td>
2185 2185 <a href="/help/grep">
2186 2186 grep
2187 2187 </a>
2188 2188 </td><td>
2189 2189 search for a pattern in specified files and revisions
2190 2190 </td></tr>
2191 2191 <tr><td>
2192 2192 <a href="/help/heads">
2193 2193 heads
2194 2194 </a>
2195 2195 </td><td>
2196 2196 show branch heads
2197 2197 </td></tr>
2198 2198 <tr><td>
2199 2199 <a href="/help/help">
2200 2200 help
2201 2201 </a>
2202 2202 </td><td>
2203 2203 show help for a given topic or a help overview
2204 2204 </td></tr>
2205 2205 <tr><td>
2206 2206 <a href="/help/hgalias">
2207 2207 hgalias
2208 2208 </a>
2209 2209 </td><td>
2210 2210 summarize working directory state
2211 2211 </td></tr>
2212 2212 <tr><td>
2213 2213 <a href="/help/identify">
2214 2214 identify
2215 2215 </a>
2216 2216 </td><td>
2217 2217 identify the working directory or specified revision
2218 2218 </td></tr>
2219 2219 <tr><td>
2220 2220 <a href="/help/import">
2221 2221 import
2222 2222 </a>
2223 2223 </td><td>
2224 2224 import an ordered set of patches
2225 2225 </td></tr>
2226 2226 <tr><td>
2227 2227 <a href="/help/incoming">
2228 2228 incoming
2229 2229 </a>
2230 2230 </td><td>
2231 2231 show new changesets found in source
2232 2232 </td></tr>
2233 2233 <tr><td>
2234 2234 <a href="/help/manifest">
2235 2235 manifest
2236 2236 </a>
2237 2237 </td><td>
2238 2238 output the current or given revision of the project manifest
2239 2239 </td></tr>
2240 2240 <tr><td>
2241 2241 <a href="/help/nohelp">
2242 2242 nohelp
2243 2243 </a>
2244 2244 </td><td>
2245 2245 (no help text available)
2246 2246 </td></tr>
2247 2247 <tr><td>
2248 2248 <a href="/help/outgoing">
2249 2249 outgoing
2250 2250 </a>
2251 2251 </td><td>
2252 2252 show changesets not found in the destination
2253 2253 </td></tr>
2254 2254 <tr><td>
2255 2255 <a href="/help/paths">
2256 2256 paths
2257 2257 </a>
2258 2258 </td><td>
2259 2259 show aliases for remote repositories
2260 2260 </td></tr>
2261 2261 <tr><td>
2262 2262 <a href="/help/phase">
2263 2263 phase
2264 2264 </a>
2265 2265 </td><td>
2266 2266 set or show the current phase name
2267 2267 </td></tr>
2268 2268 <tr><td>
2269 2269 <a href="/help/recover">
2270 2270 recover
2271 2271 </a>
2272 2272 </td><td>
2273 2273 roll back an interrupted transaction
2274 2274 </td></tr>
2275 2275 <tr><td>
2276 2276 <a href="/help/rename">
2277 2277 rename
2278 2278 </a>
2279 2279 </td><td>
2280 2280 rename files; equivalent of copy + remove
2281 2281 </td></tr>
2282 2282 <tr><td>
2283 2283 <a href="/help/resolve">
2284 2284 resolve
2285 2285 </a>
2286 2286 </td><td>
2287 2287 redo merges or set/view the merge status of files
2288 2288 </td></tr>
2289 2289 <tr><td>
2290 2290 <a href="/help/revert">
2291 2291 revert
2292 2292 </a>
2293 2293 </td><td>
2294 2294 restore files to their checkout state
2295 2295 </td></tr>
2296 2296 <tr><td>
2297 2297 <a href="/help/root">
2298 2298 root
2299 2299 </a>
2300 2300 </td><td>
2301 2301 print the root (top) of the current working directory
2302 2302 </td></tr>
2303 2303 <tr><td>
2304 2304 <a href="/help/shellalias">
2305 2305 shellalias
2306 2306 </a>
2307 2307 </td><td>
2308 2308 (no help text available)
2309 2309 </td></tr>
2310 2310 <tr><td>
2311 2311 <a href="/help/tag">
2312 2312 tag
2313 2313 </a>
2314 2314 </td><td>
2315 2315 add one or more tags for the current or given revision
2316 2316 </td></tr>
2317 2317 <tr><td>
2318 2318 <a href="/help/tags">
2319 2319 tags
2320 2320 </a>
2321 2321 </td><td>
2322 2322 list repository tags
2323 2323 </td></tr>
2324 2324 <tr><td>
2325 2325 <a href="/help/unbundle">
2326 2326 unbundle
2327 2327 </a>
2328 2328 </td><td>
2329 2329 apply one or more changegroup files
2330 2330 </td></tr>
2331 2331 <tr><td>
2332 2332 <a href="/help/verify">
2333 2333 verify
2334 2334 </a>
2335 2335 </td><td>
2336 2336 verify the integrity of the repository
2337 2337 </td></tr>
2338 2338 <tr><td>
2339 2339 <a href="/help/version">
2340 2340 version
2341 2341 </a>
2342 2342 </td><td>
2343 2343 output version and copyright information
2344 2344 </td></tr>
2345 2345
2346 2346
2347 2347 </table>
2348 2348 </div>
2349 2349 </div>
2350 2350
2351 2351 <script type="text/javascript">process_dates()</script>
2352 2352
2353 2353
2354 2354 </body>
2355 2355 </html>
2356 2356
2357 2357
2358 2358 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2359 2359 200 Script output follows
2360 2360
2361 2361 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2362 2362 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2363 2363 <head>
2364 2364 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2365 2365 <meta name="robots" content="index, nofollow" />
2366 2366 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2367 2367 <script type="text/javascript" src="/static/mercurial.js"></script>
2368 2368
2369 2369 <title>Help: add</title>
2370 2370 </head>
2371 2371 <body>
2372 2372
2373 2373 <div class="container">
2374 2374 <div class="menu">
2375 2375 <div class="logo">
2376 2376 <a href="https://mercurial-scm.org/">
2377 2377 <img src="/static/hglogo.png" alt="mercurial" /></a>
2378 2378 </div>
2379 2379 <ul>
2380 2380 <li><a href="/shortlog">log</a></li>
2381 2381 <li><a href="/graph">graph</a></li>
2382 2382 <li><a href="/tags">tags</a></li>
2383 2383 <li><a href="/bookmarks">bookmarks</a></li>
2384 2384 <li><a href="/branches">branches</a></li>
2385 2385 </ul>
2386 2386 <ul>
2387 2387 <li class="active"><a href="/help">help</a></li>
2388 2388 </ul>
2389 2389 </div>
2390 2390
2391 2391 <div class="main">
2392 2392 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2393 2393 <h3>Help: add</h3>
2394 2394
2395 2395 <form class="search" action="/log">
2396 2396
2397 2397 <p><input name="rev" id="search1" type="text" size="30" /></p>
2398 2398 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2399 2399 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2400 2400 </form>
2401 2401 <div id="doc">
2402 2402 <p>
2403 2403 hg add [OPTION]... [FILE]...
2404 2404 </p>
2405 2405 <p>
2406 2406 add the specified files on the next commit
2407 2407 </p>
2408 2408 <p>
2409 2409 Schedule files to be version controlled and added to the
2410 2410 repository.
2411 2411 </p>
2412 2412 <p>
2413 2413 The files will be added to the repository at the next commit. To
2414 2414 undo an add before that, see 'hg forget'.
2415 2415 </p>
2416 2416 <p>
2417 2417 If no names are given, add all files to the repository (except
2418 2418 files matching &quot;.hgignore&quot;).
2419 2419 </p>
2420 2420 <p>
2421 2421 Examples:
2422 2422 </p>
2423 2423 <ul>
2424 2424 <li> New (unknown) files are added automatically by 'hg add':
2425 2425 <pre>
2426 2426 \$ ls (re)
2427 2427 foo.c
2428 2428 \$ hg status (re)
2429 2429 ? foo.c
2430 2430 \$ hg add (re)
2431 2431 adding foo.c
2432 2432 \$ hg status (re)
2433 2433 A foo.c
2434 2434 </pre>
2435 2435 <li> Specific files to be added can be specified:
2436 2436 <pre>
2437 2437 \$ ls (re)
2438 2438 bar.c foo.c
2439 2439 \$ hg status (re)
2440 2440 ? bar.c
2441 2441 ? foo.c
2442 2442 \$ hg add bar.c (re)
2443 2443 \$ hg status (re)
2444 2444 A bar.c
2445 2445 ? foo.c
2446 2446 </pre>
2447 2447 </ul>
2448 2448 <p>
2449 2449 Returns 0 if all files are successfully added.
2450 2450 </p>
2451 2451 <p>
2452 2452 options ([+] can be repeated):
2453 2453 </p>
2454 2454 <table>
2455 2455 <tr><td>-I</td>
2456 2456 <td>--include PATTERN [+]</td>
2457 2457 <td>include names matching the given patterns</td></tr>
2458 2458 <tr><td>-X</td>
2459 2459 <td>--exclude PATTERN [+]</td>
2460 2460 <td>exclude names matching the given patterns</td></tr>
2461 2461 <tr><td>-S</td>
2462 2462 <td>--subrepos</td>
2463 2463 <td>recurse into subrepositories</td></tr>
2464 2464 <tr><td>-n</td>
2465 2465 <td>--dry-run</td>
2466 2466 <td>do not perform actions, just print output</td></tr>
2467 2467 </table>
2468 2468 <p>
2469 2469 global options ([+] can be repeated):
2470 2470 </p>
2471 2471 <table>
2472 2472 <tr><td>-R</td>
2473 2473 <td>--repository REPO</td>
2474 2474 <td>repository root directory or name of overlay bundle file</td></tr>
2475 2475 <tr><td></td>
2476 2476 <td>--cwd DIR</td>
2477 2477 <td>change working directory</td></tr>
2478 2478 <tr><td>-y</td>
2479 2479 <td>--noninteractive</td>
2480 2480 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2481 2481 <tr><td>-q</td>
2482 2482 <td>--quiet</td>
2483 2483 <td>suppress output</td></tr>
2484 2484 <tr><td>-v</td>
2485 2485 <td>--verbose</td>
2486 2486 <td>enable additional output</td></tr>
2487 2487 <tr><td></td>
2488 2488 <td>--config CONFIG [+]</td>
2489 2489 <td>set/override config option (use 'section.name=value')</td></tr>
2490 2490 <tr><td></td>
2491 2491 <td>--debug</td>
2492 2492 <td>enable debugging output</td></tr>
2493 2493 <tr><td></td>
2494 2494 <td>--debugger</td>
2495 2495 <td>start debugger</td></tr>
2496 2496 <tr><td></td>
2497 2497 <td>--encoding ENCODE</td>
2498 2498 <td>set the charset encoding (default: ascii)</td></tr>
2499 2499 <tr><td></td>
2500 2500 <td>--encodingmode MODE</td>
2501 2501 <td>set the charset encoding mode (default: strict)</td></tr>
2502 2502 <tr><td></td>
2503 2503 <td>--traceback</td>
2504 2504 <td>always print a traceback on exception</td></tr>
2505 2505 <tr><td></td>
2506 2506 <td>--time</td>
2507 2507 <td>time how long the command takes</td></tr>
2508 2508 <tr><td></td>
2509 2509 <td>--profile</td>
2510 2510 <td>print command execution profile</td></tr>
2511 2511 <tr><td></td>
2512 2512 <td>--version</td>
2513 2513 <td>output version information and exit</td></tr>
2514 2514 <tr><td>-h</td>
2515 2515 <td>--help</td>
2516 2516 <td>display help and exit</td></tr>
2517 2517 <tr><td></td>
2518 2518 <td>--hidden</td>
2519 2519 <td>consider hidden changesets</td></tr>
2520 2520 </table>
2521 2521
2522 2522 </div>
2523 2523 </div>
2524 2524 </div>
2525 2525
2526 2526 <script type="text/javascript">process_dates()</script>
2527 2527
2528 2528
2529 2529 </body>
2530 2530 </html>
2531 2531
2532 2532
2533 2533 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2534 2534 200 Script output follows
2535 2535
2536 2536 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2537 2537 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2538 2538 <head>
2539 2539 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2540 2540 <meta name="robots" content="index, nofollow" />
2541 2541 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2542 2542 <script type="text/javascript" src="/static/mercurial.js"></script>
2543 2543
2544 2544 <title>Help: remove</title>
2545 2545 </head>
2546 2546 <body>
2547 2547
2548 2548 <div class="container">
2549 2549 <div class="menu">
2550 2550 <div class="logo">
2551 2551 <a href="https://mercurial-scm.org/">
2552 2552 <img src="/static/hglogo.png" alt="mercurial" /></a>
2553 2553 </div>
2554 2554 <ul>
2555 2555 <li><a href="/shortlog">log</a></li>
2556 2556 <li><a href="/graph">graph</a></li>
2557 2557 <li><a href="/tags">tags</a></li>
2558 2558 <li><a href="/bookmarks">bookmarks</a></li>
2559 2559 <li><a href="/branches">branches</a></li>
2560 2560 </ul>
2561 2561 <ul>
2562 2562 <li class="active"><a href="/help">help</a></li>
2563 2563 </ul>
2564 2564 </div>
2565 2565
2566 2566 <div class="main">
2567 2567 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2568 2568 <h3>Help: remove</h3>
2569 2569
2570 2570 <form class="search" action="/log">
2571 2571
2572 2572 <p><input name="rev" id="search1" type="text" size="30" /></p>
2573 2573 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2574 2574 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2575 2575 </form>
2576 2576 <div id="doc">
2577 2577 <p>
2578 2578 hg remove [OPTION]... FILE...
2579 2579 </p>
2580 2580 <p>
2581 2581 aliases: rm
2582 2582 </p>
2583 2583 <p>
2584 2584 remove the specified files on the next commit
2585 2585 </p>
2586 2586 <p>
2587 2587 Schedule the indicated files for removal from the current branch.
2588 2588 </p>
2589 2589 <p>
2590 2590 This command schedules the files to be removed at the next commit.
2591 2591 To undo a remove before that, see 'hg revert'. To undo added
2592 2592 files, see 'hg forget'.
2593 2593 </p>
2594 2594 <p>
2595 2595 -A/--after can be used to remove only files that have already
2596 2596 been deleted, -f/--force can be used to force deletion, and -Af
2597 2597 can be used to remove files from the next revision without
2598 2598 deleting them from the working directory.
2599 2599 </p>
2600 2600 <p>
2601 2601 The following table details the behavior of remove for different
2602 2602 file states (columns) and option combinations (rows). The file
2603 2603 states are Added [A], Clean [C], Modified [M] and Missing [!]
2604 2604 (as reported by 'hg status'). The actions are Warn, Remove
2605 2605 (from branch) and Delete (from disk):
2606 2606 </p>
2607 2607 <table>
2608 2608 <tr><td>opt/state</td>
2609 2609 <td>A</td>
2610 2610 <td>C</td>
2611 2611 <td>M</td>
2612 2612 <td>!</td></tr>
2613 2613 <tr><td>none</td>
2614 2614 <td>W</td>
2615 2615 <td>RD</td>
2616 2616 <td>W</td>
2617 2617 <td>R</td></tr>
2618 2618 <tr><td>-f</td>
2619 2619 <td>R</td>
2620 2620 <td>RD</td>
2621 2621 <td>RD</td>
2622 2622 <td>R</td></tr>
2623 2623 <tr><td>-A</td>
2624 2624 <td>W</td>
2625 2625 <td>W</td>
2626 2626 <td>W</td>
2627 2627 <td>R</td></tr>
2628 2628 <tr><td>-Af</td>
2629 2629 <td>R</td>
2630 2630 <td>R</td>
2631 2631 <td>R</td>
2632 2632 <td>R</td></tr>
2633 2633 </table>
2634 2634 <p>
2635 2635 <b>Note:</b>
2636 2636 </p>
2637 2637 <p>
2638 2638 'hg remove' never deletes files in Added [A] state from the
2639 2639 working directory, not even if &quot;--force&quot; is specified.
2640 2640 </p>
2641 2641 <p>
2642 2642 Returns 0 on success, 1 if any warnings encountered.
2643 2643 </p>
2644 2644 <p>
2645 2645 options ([+] can be repeated):
2646 2646 </p>
2647 2647 <table>
2648 2648 <tr><td>-A</td>
2649 2649 <td>--after</td>
2650 2650 <td>record delete for missing files</td></tr>
2651 2651 <tr><td>-f</td>
2652 2652 <td>--force</td>
2653 2653 <td>forget added files, delete modified files</td></tr>
2654 2654 <tr><td>-S</td>
2655 2655 <td>--subrepos</td>
2656 2656 <td>recurse into subrepositories</td></tr>
2657 2657 <tr><td>-I</td>
2658 2658 <td>--include PATTERN [+]</td>
2659 2659 <td>include names matching the given patterns</td></tr>
2660 2660 <tr><td>-X</td>
2661 2661 <td>--exclude PATTERN [+]</td>
2662 2662 <td>exclude names matching the given patterns</td></tr>
2663 2663 </table>
2664 2664 <p>
2665 2665 global options ([+] can be repeated):
2666 2666 </p>
2667 2667 <table>
2668 2668 <tr><td>-R</td>
2669 2669 <td>--repository REPO</td>
2670 2670 <td>repository root directory or name of overlay bundle file</td></tr>
2671 2671 <tr><td></td>
2672 2672 <td>--cwd DIR</td>
2673 2673 <td>change working directory</td></tr>
2674 2674 <tr><td>-y</td>
2675 2675 <td>--noninteractive</td>
2676 2676 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2677 2677 <tr><td>-q</td>
2678 2678 <td>--quiet</td>
2679 2679 <td>suppress output</td></tr>
2680 2680 <tr><td>-v</td>
2681 2681 <td>--verbose</td>
2682 2682 <td>enable additional output</td></tr>
2683 2683 <tr><td></td>
2684 2684 <td>--config CONFIG [+]</td>
2685 2685 <td>set/override config option (use 'section.name=value')</td></tr>
2686 2686 <tr><td></td>
2687 2687 <td>--debug</td>
2688 2688 <td>enable debugging output</td></tr>
2689 2689 <tr><td></td>
2690 2690 <td>--debugger</td>
2691 2691 <td>start debugger</td></tr>
2692 2692 <tr><td></td>
2693 2693 <td>--encoding ENCODE</td>
2694 2694 <td>set the charset encoding (default: ascii)</td></tr>
2695 2695 <tr><td></td>
2696 2696 <td>--encodingmode MODE</td>
2697 2697 <td>set the charset encoding mode (default: strict)</td></tr>
2698 2698 <tr><td></td>
2699 2699 <td>--traceback</td>
2700 2700 <td>always print a traceback on exception</td></tr>
2701 2701 <tr><td></td>
2702 2702 <td>--time</td>
2703 2703 <td>time how long the command takes</td></tr>
2704 2704 <tr><td></td>
2705 2705 <td>--profile</td>
2706 2706 <td>print command execution profile</td></tr>
2707 2707 <tr><td></td>
2708 2708 <td>--version</td>
2709 2709 <td>output version information and exit</td></tr>
2710 2710 <tr><td>-h</td>
2711 2711 <td>--help</td>
2712 2712 <td>display help and exit</td></tr>
2713 2713 <tr><td></td>
2714 2714 <td>--hidden</td>
2715 2715 <td>consider hidden changesets</td></tr>
2716 2716 </table>
2717 2717
2718 2718 </div>
2719 2719 </div>
2720 2720 </div>
2721 2721
2722 2722 <script type="text/javascript">process_dates()</script>
2723 2723
2724 2724
2725 2725 </body>
2726 2726 </html>
2727 2727
2728 2728
2729 2729 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2730 2730 200 Script output follows
2731 2731
2732 2732 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2733 2733 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2734 2734 <head>
2735 2735 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2736 2736 <meta name="robots" content="index, nofollow" />
2737 2737 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2738 2738 <script type="text/javascript" src="/static/mercurial.js"></script>
2739 2739
2740 2740 <title>Help: revisions</title>
2741 2741 </head>
2742 2742 <body>
2743 2743
2744 2744 <div class="container">
2745 2745 <div class="menu">
2746 2746 <div class="logo">
2747 2747 <a href="https://mercurial-scm.org/">
2748 2748 <img src="/static/hglogo.png" alt="mercurial" /></a>
2749 2749 </div>
2750 2750 <ul>
2751 2751 <li><a href="/shortlog">log</a></li>
2752 2752 <li><a href="/graph">graph</a></li>
2753 2753 <li><a href="/tags">tags</a></li>
2754 2754 <li><a href="/bookmarks">bookmarks</a></li>
2755 2755 <li><a href="/branches">branches</a></li>
2756 2756 </ul>
2757 2757 <ul>
2758 2758 <li class="active"><a href="/help">help</a></li>
2759 2759 </ul>
2760 2760 </div>
2761 2761
2762 2762 <div class="main">
2763 2763 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2764 2764 <h3>Help: revisions</h3>
2765 2765
2766 2766 <form class="search" action="/log">
2767 2767
2768 2768 <p><input name="rev" id="search1" type="text" size="30" /></p>
2769 2769 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2770 2770 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2771 2771 </form>
2772 2772 <div id="doc">
2773 2773 <h1>Specifying Single Revisions</h1>
2774 2774 <p>
2775 2775 Mercurial supports several ways to specify individual revisions.
2776 2776 </p>
2777 2777 <p>
2778 2778 A plain integer is treated as a revision number. Negative integers are
2779 2779 treated as sequential offsets from the tip, with -1 denoting the tip,
2780 2780 -2 denoting the revision prior to the tip, and so forth.
2781 2781 </p>
2782 2782 <p>
2783 2783 A 40-digit hexadecimal string is treated as a unique revision
2784 2784 identifier.
2785 2785 </p>
2786 2786 <p>
2787 2787 A hexadecimal string less than 40 characters long is treated as a
2788 2788 unique revision identifier and is referred to as a short-form
2789 2789 identifier. A short-form identifier is only valid if it is the prefix
2790 2790 of exactly one full-length identifier.
2791 2791 </p>
2792 2792 <p>
2793 2793 Any other string is treated as a bookmark, tag, or branch name. A
2794 2794 bookmark is a movable pointer to a revision. A tag is a permanent name
2795 2795 associated with a revision. A branch name denotes the tipmost open branch head
2796 2796 of that branch - or if they are all closed, the tipmost closed head of the
2797 2797 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2798 2798 </p>
2799 2799 <p>
2800 2800 The reserved name &quot;tip&quot; always identifies the most recent revision.
2801 2801 </p>
2802 2802 <p>
2803 2803 The reserved name &quot;null&quot; indicates the null revision. This is the
2804 2804 revision of an empty repository, and the parent of revision 0.
2805 2805 </p>
2806 2806 <p>
2807 2807 The reserved name &quot;.&quot; indicates the working directory parent. If no
2808 2808 working directory is checked out, it is equivalent to null. If an
2809 2809 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2810 2810 parent.
2811 2811 </p>
2812 2812
2813 2813 </div>
2814 2814 </div>
2815 2815 </div>
2816 2816
2817 2817 <script type="text/javascript">process_dates()</script>
2818 2818
2819 2819
2820 2820 </body>
2821 2821 </html>
2822 2822
2823 2823
2824 2824 Sub-topic indexes rendered properly
2825 2825
2826 2826 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2827 2827 200 Script output follows
2828 2828
2829 2829 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2830 2830 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2831 2831 <head>
2832 2832 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2833 2833 <meta name="robots" content="index, nofollow" />
2834 2834 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2835 2835 <script type="text/javascript" src="/static/mercurial.js"></script>
2836 2836
2837 2837 <title>Help: internals</title>
2838 2838 </head>
2839 2839 <body>
2840 2840
2841 2841 <div class="container">
2842 2842 <div class="menu">
2843 2843 <div class="logo">
2844 2844 <a href="https://mercurial-scm.org/">
2845 2845 <img src="/static/hglogo.png" alt="mercurial" /></a>
2846 2846 </div>
2847 2847 <ul>
2848 2848 <li><a href="/shortlog">log</a></li>
2849 2849 <li><a href="/graph">graph</a></li>
2850 2850 <li><a href="/tags">tags</a></li>
2851 2851 <li><a href="/bookmarks">bookmarks</a></li>
2852 2852 <li><a href="/branches">branches</a></li>
2853 2853 </ul>
2854 2854 <ul>
2855 2855 <li><a href="/help">help</a></li>
2856 2856 </ul>
2857 2857 </div>
2858 2858
2859 2859 <div class="main">
2860 2860 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2861 2861 <form class="search" action="/log">
2862 2862
2863 2863 <p><input name="rev" id="search1" type="text" size="30" /></p>
2864 2864 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2865 2865 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2866 2866 </form>
2867 2867 <table class="bigtable">
2868 2868 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
2869 2869
2870 2870 <tr><td>
2871 2871 <a href="/help/internals.bundles">
2872 2872 bundles
2873 2873 </a>
2874 2874 </td><td>
2875 container for exchange of repository data
2875 Bundles
2876 2876 </td></tr>
2877 2877 <tr><td>
2878 2878 <a href="/help/internals.changegroups">
2879 2879 changegroups
2880 2880 </a>
2881 2881 </td><td>
2882 representation of revlog data
2882 Changegroups
2883 2883 </td></tr>
2884 2884 <tr><td>
2885 2885 <a href="/help/internals.requirements">
2886 2886 requirements
2887 2887 </a>
2888 2888 </td><td>
2889 repository requirements
2889 Repository Requirements
2890 2890 </td></tr>
2891 2891 <tr><td>
2892 2892 <a href="/help/internals.revlogs">
2893 2893 revlogs
2894 2894 </a>
2895 2895 </td><td>
2896 revision storage mechanism
2896 Revision Logs
2897 2897 </td></tr>
2898 2898
2899 2899
2900 2900
2901 2901
2902 2902
2903 2903 </table>
2904 2904 </div>
2905 2905 </div>
2906 2906
2907 2907 <script type="text/javascript">process_dates()</script>
2908 2908
2909 2909
2910 2910 </body>
2911 2911 </html>
2912 2912
2913 2913
2914 2914 Sub-topic topics rendered properly
2915 2915
2916 2916 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2917 2917 200 Script output follows
2918 2918
2919 2919 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2920 2920 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2921 2921 <head>
2922 2922 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2923 2923 <meta name="robots" content="index, nofollow" />
2924 2924 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2925 2925 <script type="text/javascript" src="/static/mercurial.js"></script>
2926 2926
2927 2927 <title>Help: internals.changegroups</title>
2928 2928 </head>
2929 2929 <body>
2930 2930
2931 2931 <div class="container">
2932 2932 <div class="menu">
2933 2933 <div class="logo">
2934 2934 <a href="https://mercurial-scm.org/">
2935 2935 <img src="/static/hglogo.png" alt="mercurial" /></a>
2936 2936 </div>
2937 2937 <ul>
2938 2938 <li><a href="/shortlog">log</a></li>
2939 2939 <li><a href="/graph">graph</a></li>
2940 2940 <li><a href="/tags">tags</a></li>
2941 2941 <li><a href="/bookmarks">bookmarks</a></li>
2942 2942 <li><a href="/branches">branches</a></li>
2943 2943 </ul>
2944 2944 <ul>
2945 2945 <li class="active"><a href="/help">help</a></li>
2946 2946 </ul>
2947 2947 </div>
2948 2948
2949 2949 <div class="main">
2950 2950 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2951 2951 <h3>Help: internals.changegroups</h3>
2952 2952
2953 2953 <form class="search" action="/log">
2954 2954
2955 2955 <p><input name="rev" id="search1" type="text" size="30" /></p>
2956 2956 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2957 2957 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2958 2958 </form>
2959 2959 <div id="doc">
2960 <h1>representation of revlog data</h1>
2961 <h2>Changegroups</h2>
2960 <h1>Changegroups</h1>
2962 2961 <p>
2963 2962 Changegroups are representations of repository revlog data, specifically
2964 2963 the changelog, manifest, and filelogs.
2965 2964 </p>
2966 2965 <p>
2967 2966 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2968 2967 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2969 2968 the only difference being a header on entries in the changeset
2970 2969 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2971 2970 includes revlog flags in the delta header.
2972 2971 </p>
2973 2972 <p>
2974 2973 Changegroups consists of 3 logical segments:
2975 2974 </p>
2976 2975 <pre>
2977 2976 +---------------------------------+
2978 2977 | | | |
2979 2978 | changeset | manifest | filelogs |
2980 2979 | | | |
2981 2980 +---------------------------------+
2982 2981 </pre>
2983 2982 <p>
2984 2983 The principle building block of each segment is a *chunk*. A *chunk*
2985 2984 is a framed piece of data:
2986 2985 </p>
2987 2986 <pre>
2988 2987 +---------------------------------------+
2989 2988 | | |
2990 2989 | length | data |
2991 2990 | (32 bits) | &lt;length&gt; bytes |
2992 2991 | | |
2993 2992 +---------------------------------------+
2994 2993 </pre>
2995 2994 <p>
2996 2995 Each chunk starts with a 32-bit big-endian signed integer indicating
2997 2996 the length of the raw data that follows.
2998 2997 </p>
2999 2998 <p>
3000 2999 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
3001 3000 call this an *empty chunk*.
3002 3001 </p>
3003 <h3>Delta Groups</h3>
3002 <h2>Delta Groups</h2>
3004 3003 <p>
3005 3004 A *delta group* expresses the content of a revlog as a series of deltas,
3006 3005 or patches against previous revisions.
3007 3006 </p>
3008 3007 <p>
3009 3008 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3010 3009 to signal the end of the delta group:
3011 3010 </p>
3012 3011 <pre>
3013 3012 +------------------------------------------------------------------------+
3014 3013 | | | | | |
3015 3014 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3016 3015 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
3017 3016 | | | | | |
3018 3017 +------------------------------------------------------------+-----------+
3019 3018 </pre>
3020 3019 <p>
3021 3020 Each *chunk*'s data consists of the following:
3022 3021 </p>
3023 3022 <pre>
3024 3023 +-----------------------------------------+
3025 3024 | | | |
3026 3025 | delta header | mdiff header | delta |
3027 3026 | (various) | (12 bytes) | (various) |
3028 3027 | | | |
3029 3028 +-----------------------------------------+
3030 3029 </pre>
3031 3030 <p>
3032 3031 The *length* field is the byte length of the remaining 3 logical pieces
3033 3032 of data. The *delta* is a diff from an existing entry in the changelog.
3034 3033 </p>
3035 3034 <p>
3036 3035 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3037 3036 &quot;3&quot; of the changegroup format.
3038 3037 </p>
3039 3038 <p>
3040 3039 Version 1:
3041 3040 </p>
3042 3041 <pre>
3043 3042 +------------------------------------------------------+
3044 3043 | | | | |
3045 3044 | node | p1 node | p2 node | link node |
3046 3045 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3047 3046 | | | | |
3048 3047 +------------------------------------------------------+
3049 3048 </pre>
3050 3049 <p>
3051 3050 Version 2:
3052 3051 </p>
3053 3052 <pre>
3054 3053 +------------------------------------------------------------------+
3055 3054 | | | | | |
3056 3055 | node | p1 node | p2 node | base node | link node |
3057 3056 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3058 3057 | | | | | |
3059 3058 +------------------------------------------------------------------+
3060 3059 </pre>
3061 3060 <p>
3062 3061 Version 3:
3063 3062 </p>
3064 3063 <pre>
3065 3064 +------------------------------------------------------------------------------+
3066 3065 | | | | | | |
3067 3066 | node | p1 node | p2 node | base node | link node | flags |
3068 3067 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3069 3068 | | | | | | |
3070 3069 +------------------------------------------------------------------------------+
3071 3070 </pre>
3072 3071 <p>
3073 3072 The *mdiff header* consists of 3 32-bit big-endian signed integers
3074 3073 describing offsets at which to apply the following delta content:
3075 3074 </p>
3076 3075 <pre>
3077 3076 +-------------------------------------+
3078 3077 | | | |
3079 3078 | offset | old length | new length |
3080 3079 | (32 bits) | (32 bits) | (32 bits) |
3081 3080 | | | |
3082 3081 +-------------------------------------+
3083 3082 </pre>
3084 3083 <p>
3085 3084 In version 1, the delta is always applied against the previous node from
3086 3085 the changegroup or the first parent if this is the first entry in the
3087 3086 changegroup.
3088 3087 </p>
3089 3088 <p>
3090 3089 In version 2, the delta base node is encoded in the entry in the
3091 3090 changegroup. This allows the delta to be expressed against any parent,
3092 3091 which can result in smaller deltas and more efficient encoding of data.
3093 3092 </p>
3094 <h3>Changeset Segment</h3>
3093 <h2>Changeset Segment</h2>
3095 3094 <p>
3096 3095 The *changeset segment* consists of a single *delta group* holding
3097 3096 changelog data. It is followed by an *empty chunk* to denote the
3098 3097 boundary to the *manifests segment*.
3099 3098 </p>
3100 <h3>Manifest Segment</h3>
3099 <h2>Manifest Segment</h2>
3101 3100 <p>
3102 3101 The *manifest segment* consists of a single *delta group* holding
3103 3102 manifest data. It is followed by an *empty chunk* to denote the boundary
3104 3103 to the *filelogs segment*.
3105 3104 </p>
3106 <h3>Filelogs Segment</h3>
3105 <h2>Filelogs Segment</h2>
3107 3106 <p>
3108 3107 The *filelogs* segment consists of multiple sub-segments, each
3109 3108 corresponding to an individual file whose data is being described:
3110 3109 </p>
3111 3110 <pre>
3112 3111 +--------------------------------------+
3113 3112 | | | | |
3114 3113 | filelog0 | filelog1 | filelog2 | ... |
3115 3114 | | | | |
3116 3115 +--------------------------------------+
3117 3116 </pre>
3118 3117 <p>
3119 3118 In version &quot;3&quot; of the changegroup format, filelogs may include
3120 3119 directory logs when treemanifests are in use. directory logs are
3121 3120 identified by having a trailing '/' on their filename (see below).
3122 3121 </p>
3123 3122 <p>
3124 3123 The final filelog sub-segment is followed by an *empty chunk* to denote
3125 3124 the end of the segment and the overall changegroup.
3126 3125 </p>
3127 3126 <p>
3128 3127 Each filelog sub-segment consists of the following:
3129 3128 </p>
3130 3129 <pre>
3131 3130 +------------------------------------------+
3132 3131 | | | |
3133 3132 | filename size | filename | delta group |
3134 3133 | (32 bits) | (various) | (various) |
3135 3134 | | | |
3136 3135 +------------------------------------------+
3137 3136 </pre>
3138 3137 <p>
3139 3138 That is, a *chunk* consisting of the filename (not terminated or padded)
3140 3139 followed by N chunks constituting the *delta group* for this file.
3141 3140 </p>
3142 3141
3143 3142 </div>
3144 3143 </div>
3145 3144 </div>
3146 3145
3147 3146 <script type="text/javascript">process_dates()</script>
3148 3147
3149 3148
3150 3149 </body>
3151 3150 </html>
3152 3151
3153 3152
3154 3153 $ killdaemons.py
3155 3154
3156 3155 #endif
General Comments 0
You need to be logged in to leave comments. Login now