##// END OF EJS Templates
verify: introduce an experimental --full flag...
marmoute -
r42332:496ac8a0 default
parent child Browse files
Show More
@@ -1,6250 +1,6256 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 os
13 13 import re
14 14 import sys
15 15
16 16 from .i18n import _
17 17 from .node import (
18 18 hex,
19 19 nullid,
20 20 nullrev,
21 21 short,
22 22 wdirhex,
23 23 wdirrev,
24 24 )
25 25 from . import (
26 26 archival,
27 27 bookmarks,
28 28 bundle2,
29 29 changegroup,
30 30 cmdutil,
31 31 copies,
32 32 debugcommands as debugcommandsmod,
33 33 destutil,
34 34 dirstateguard,
35 35 discovery,
36 36 encoding,
37 37 error,
38 38 exchange,
39 39 extensions,
40 40 filemerge,
41 41 formatter,
42 42 graphmod,
43 43 hbisect,
44 44 help,
45 45 hg,
46 46 logcmdutil,
47 47 merge as mergemod,
48 48 narrowspec,
49 49 obsolete,
50 50 obsutil,
51 51 patch,
52 52 phases,
53 53 pycompat,
54 54 rcutil,
55 55 registrar,
56 56 repair,
57 57 revsetlang,
58 58 rewriteutil,
59 59 scmutil,
60 60 server,
61 61 state as statemod,
62 62 streamclone,
63 63 tags as tagsmod,
64 64 ui as uimod,
65 65 util,
66 verify as verifymod,
66 67 wireprotoserver,
67 68 )
68 69 from .utils import (
69 70 dateutil,
70 71 stringutil,
71 72 )
72 73
73 74 table = {}
74 75 table.update(debugcommandsmod.command._table)
75 76
76 77 command = registrar.command(table)
77 78 INTENT_READONLY = registrar.INTENT_READONLY
78 79
79 80 # common command options
80 81
81 82 globalopts = [
82 83 ('R', 'repository', '',
83 84 _('repository root directory or name of overlay bundle file'),
84 85 _('REPO')),
85 86 ('', 'cwd', '',
86 87 _('change working directory'), _('DIR')),
87 88 ('y', 'noninteractive', None,
88 89 _('do not prompt, automatically pick the first choice for all prompts')),
89 90 ('q', 'quiet', None, _('suppress output')),
90 91 ('v', 'verbose', None, _('enable additional output')),
91 92 ('', 'color', '',
92 93 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
93 94 # and should not be translated
94 95 _("when to colorize (boolean, always, auto, never, or debug)"),
95 96 _('TYPE')),
96 97 ('', 'config', [],
97 98 _('set/override config option (use \'section.name=value\')'),
98 99 _('CONFIG')),
99 100 ('', 'debug', None, _('enable debugging output')),
100 101 ('', 'debugger', None, _('start debugger')),
101 102 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
102 103 _('ENCODE')),
103 104 ('', 'encodingmode', encoding.encodingmode,
104 105 _('set the charset encoding mode'), _('MODE')),
105 106 ('', 'traceback', None, _('always print a traceback on exception')),
106 107 ('', 'time', None, _('time how long the command takes')),
107 108 ('', 'profile', None, _('print command execution profile')),
108 109 ('', 'version', None, _('output version information and exit')),
109 110 ('h', 'help', None, _('display help and exit')),
110 111 ('', 'hidden', False, _('consider hidden changesets')),
111 112 ('', 'pager', 'auto',
112 113 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
113 114 ]
114 115
115 116 dryrunopts = cmdutil.dryrunopts
116 117 remoteopts = cmdutil.remoteopts
117 118 walkopts = cmdutil.walkopts
118 119 commitopts = cmdutil.commitopts
119 120 commitopts2 = cmdutil.commitopts2
120 121 formatteropts = cmdutil.formatteropts
121 122 templateopts = cmdutil.templateopts
122 123 logopts = cmdutil.logopts
123 124 diffopts = cmdutil.diffopts
124 125 diffwsopts = cmdutil.diffwsopts
125 126 diffopts2 = cmdutil.diffopts2
126 127 mergetoolopts = cmdutil.mergetoolopts
127 128 similarityopts = cmdutil.similarityopts
128 129 subrepoopts = cmdutil.subrepoopts
129 130 debugrevlogopts = cmdutil.debugrevlogopts
130 131
131 132 # Commands start here, listed alphabetically
132 133
133 134 @command('add',
134 135 walkopts + subrepoopts + dryrunopts,
135 136 _('[OPTION]... [FILE]...'),
136 137 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
137 138 helpbasic=True, inferrepo=True)
138 139 def add(ui, repo, *pats, **opts):
139 140 """add the specified files on the next commit
140 141
141 142 Schedule files to be version controlled and added to the
142 143 repository.
143 144
144 145 The files will be added to the repository at the next commit. To
145 146 undo an add before that, see :hg:`forget`.
146 147
147 148 If no names are given, add all files to the repository (except
148 149 files matching ``.hgignore``).
149 150
150 151 .. container:: verbose
151 152
152 153 Examples:
153 154
154 155 - New (unknown) files are added
155 156 automatically by :hg:`add`::
156 157
157 158 $ ls
158 159 foo.c
159 160 $ hg status
160 161 ? foo.c
161 162 $ hg add
162 163 adding foo.c
163 164 $ hg status
164 165 A foo.c
165 166
166 167 - Specific files to be added can be specified::
167 168
168 169 $ ls
169 170 bar.c foo.c
170 171 $ hg status
171 172 ? bar.c
172 173 ? foo.c
173 174 $ hg add bar.c
174 175 $ hg status
175 176 A bar.c
176 177 ? foo.c
177 178
178 179 Returns 0 if all files are successfully added.
179 180 """
180 181
181 182 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
182 183 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
183 184 rejected = cmdutil.add(ui, repo, m, "", uipathfn, False, **opts)
184 185 return rejected and 1 or 0
185 186
186 187 @command('addremove',
187 188 similarityopts + subrepoopts + walkopts + dryrunopts,
188 189 _('[OPTION]... [FILE]...'),
189 190 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
190 191 inferrepo=True)
191 192 def addremove(ui, repo, *pats, **opts):
192 193 """add all new files, delete all missing files
193 194
194 195 Add all new files and remove all missing files from the
195 196 repository.
196 197
197 198 Unless names are given, new files are ignored if they match any of
198 199 the patterns in ``.hgignore``. As with add, these changes take
199 200 effect at the next commit.
200 201
201 202 Use the -s/--similarity option to detect renamed files. This
202 203 option takes a percentage between 0 (disabled) and 100 (files must
203 204 be identical) as its parameter. With a parameter greater than 0,
204 205 this compares every removed file with every added file and records
205 206 those similar enough as renames. Detecting renamed files this way
206 207 can be expensive. After using this option, :hg:`status -C` can be
207 208 used to check which files were identified as moved or renamed. If
208 209 not specified, -s/--similarity defaults to 100 and only renames of
209 210 identical files are detected.
210 211
211 212 .. container:: verbose
212 213
213 214 Examples:
214 215
215 216 - A number of files (bar.c and foo.c) are new,
216 217 while foobar.c has been removed (without using :hg:`remove`)
217 218 from the repository::
218 219
219 220 $ ls
220 221 bar.c foo.c
221 222 $ hg status
222 223 ! foobar.c
223 224 ? bar.c
224 225 ? foo.c
225 226 $ hg addremove
226 227 adding bar.c
227 228 adding foo.c
228 229 removing foobar.c
229 230 $ hg status
230 231 A bar.c
231 232 A foo.c
232 233 R foobar.c
233 234
234 235 - A file foobar.c was moved to foo.c without using :hg:`rename`.
235 236 Afterwards, it was edited slightly::
236 237
237 238 $ ls
238 239 foo.c
239 240 $ hg status
240 241 ! foobar.c
241 242 ? foo.c
242 243 $ hg addremove --similarity 90
243 244 removing foobar.c
244 245 adding foo.c
245 246 recording removal of foobar.c as rename to foo.c (94% similar)
246 247 $ hg status -C
247 248 A foo.c
248 249 foobar.c
249 250 R foobar.c
250 251
251 252 Returns 0 if all files are successfully added.
252 253 """
253 254 opts = pycompat.byteskwargs(opts)
254 255 if not opts.get('similarity'):
255 256 opts['similarity'] = '100'
256 257 matcher = scmutil.match(repo[None], pats, opts)
257 258 relative = scmutil.anypats(pats, opts)
258 259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
259 260 return scmutil.addremove(repo, matcher, "", uipathfn, opts)
260 261
261 262 @command('annotate|blame',
262 263 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
263 264 ('', 'follow', None,
264 265 _('follow copies/renames and list the filename (DEPRECATED)')),
265 266 ('', 'no-follow', None, _("don't follow copies and renames")),
266 267 ('a', 'text', None, _('treat all files as text')),
267 268 ('u', 'user', None, _('list the author (long with -v)')),
268 269 ('f', 'file', None, _('list the filename')),
269 270 ('d', 'date', None, _('list the date (short with -q)')),
270 271 ('n', 'number', None, _('list the revision number (default)')),
271 272 ('c', 'changeset', None, _('list the changeset')),
272 273 ('l', 'line-number', None, _('show line number at the first appearance')),
273 274 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
274 275 ] + diffwsopts + walkopts + formatteropts,
275 276 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
276 277 helpcategory=command.CATEGORY_FILE_CONTENTS,
277 278 helpbasic=True, inferrepo=True)
278 279 def annotate(ui, repo, *pats, **opts):
279 280 """show changeset information by line for each file
280 281
281 282 List changes in files, showing the revision id responsible for
282 283 each line.
283 284
284 285 This command is useful for discovering when a change was made and
285 286 by whom.
286 287
287 288 If you include --file, --user, or --date, the revision number is
288 289 suppressed unless you also include --number.
289 290
290 291 Without the -a/--text option, annotate will avoid processing files
291 292 it detects as binary. With -a, annotate will annotate the file
292 293 anyway, although the results will probably be neither useful
293 294 nor desirable.
294 295
295 296 .. container:: verbose
296 297
297 298 Template:
298 299
299 300 The following keywords are supported in addition to the common template
300 301 keywords and functions. See also :hg:`help templates`.
301 302
302 303 :lines: List of lines with annotation data.
303 304 :path: String. Repository-absolute path of the specified file.
304 305
305 306 And each entry of ``{lines}`` provides the following sub-keywords in
306 307 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
307 308
308 309 :line: String. Line content.
309 310 :lineno: Integer. Line number at that revision.
310 311 :path: String. Repository-absolute path of the file at that revision.
311 312
312 313 See :hg:`help templates.operators` for the list expansion syntax.
313 314
314 315 Returns 0 on success.
315 316 """
316 317 opts = pycompat.byteskwargs(opts)
317 318 if not pats:
318 319 raise error.Abort(_('at least one filename or pattern is required'))
319 320
320 321 if opts.get('follow'):
321 322 # --follow is deprecated and now just an alias for -f/--file
322 323 # to mimic the behavior of Mercurial before version 1.5
323 324 opts['file'] = True
324 325
325 326 if (not opts.get('user') and not opts.get('changeset')
326 327 and not opts.get('date') and not opts.get('file')):
327 328 opts['number'] = True
328 329
329 330 linenumber = opts.get('line_number') is not None
330 331 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
331 332 raise error.Abort(_('at least one of -n/-c is required for -l'))
332 333
333 334 rev = opts.get('rev')
334 335 if rev:
335 336 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
336 337 ctx = scmutil.revsingle(repo, rev)
337 338
338 339 ui.pager('annotate')
339 340 rootfm = ui.formatter('annotate', opts)
340 341 if ui.debugflag:
341 342 shorthex = pycompat.identity
342 343 else:
343 344 def shorthex(h):
344 345 return h[:12]
345 346 if ui.quiet:
346 347 datefunc = dateutil.shortdate
347 348 else:
348 349 datefunc = dateutil.datestr
349 350 if ctx.rev() is None:
350 351 if opts.get('changeset'):
351 352 # omit "+" suffix which is appended to node hex
352 353 def formatrev(rev):
353 354 if rev == wdirrev:
354 355 return '%d' % ctx.p1().rev()
355 356 else:
356 357 return '%d' % rev
357 358 else:
358 359 def formatrev(rev):
359 360 if rev == wdirrev:
360 361 return '%d+' % ctx.p1().rev()
361 362 else:
362 363 return '%d ' % rev
363 364 def formathex(h):
364 365 if h == wdirhex:
365 366 return '%s+' % shorthex(hex(ctx.p1().node()))
366 367 else:
367 368 return '%s ' % shorthex(h)
368 369 else:
369 370 formatrev = b'%d'.__mod__
370 371 formathex = shorthex
371 372
372 373 opmap = [
373 374 ('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
374 375 ('rev', ' ', lambda x: scmutil.intrev(x.fctx), formatrev),
375 376 ('node', ' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
376 377 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
377 378 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
378 379 ('lineno', ':', lambda x: x.lineno, pycompat.bytestr),
379 380 ]
380 381 opnamemap = {
381 382 'rev': 'number',
382 383 'node': 'changeset',
383 384 'path': 'file',
384 385 'lineno': 'line_number',
385 386 }
386 387
387 388 if rootfm.isplain():
388 389 def makefunc(get, fmt):
389 390 return lambda x: fmt(get(x))
390 391 else:
391 392 def makefunc(get, fmt):
392 393 return get
393 394 datahint = rootfm.datahint()
394 395 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
395 396 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
396 397 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
397 398 fields = ' '.join(fn for fn, sep, get, fmt in opmap
398 399 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
399 400
400 401 def bad(x, y):
401 402 raise error.Abort("%s: %s" % (x, y))
402 403
403 404 m = scmutil.match(ctx, pats, opts, badfn=bad)
404 405
405 406 follow = not opts.get('no_follow')
406 407 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
407 408 whitespace=True)
408 409 skiprevs = opts.get('skip')
409 410 if skiprevs:
410 411 skiprevs = scmutil.revrange(repo, skiprevs)
411 412
412 413 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
413 414 for abs in ctx.walk(m):
414 415 fctx = ctx[abs]
415 416 rootfm.startitem()
416 417 rootfm.data(path=abs)
417 418 if not opts.get('text') and fctx.isbinary():
418 419 rootfm.plain(_("%s: binary file\n") % uipathfn(abs))
419 420 continue
420 421
421 422 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
422 423 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
423 424 diffopts=diffopts)
424 425 if not lines:
425 426 fm.end()
426 427 continue
427 428 formats = []
428 429 pieces = []
429 430
430 431 for f, sep in funcmap:
431 432 l = [f(n) for n in lines]
432 433 if fm.isplain():
433 434 sizes = [encoding.colwidth(x) for x in l]
434 435 ml = max(sizes)
435 436 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
436 437 else:
437 438 formats.append(['%s' for x in l])
438 439 pieces.append(l)
439 440
440 441 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
441 442 fm.startitem()
442 443 fm.context(fctx=n.fctx)
443 444 fm.write(fields, "".join(f), *p)
444 445 if n.skip:
445 446 fmt = "* %s"
446 447 else:
447 448 fmt = ": %s"
448 449 fm.write('line', fmt, n.text)
449 450
450 451 if not lines[-1].text.endswith('\n'):
451 452 fm.plain('\n')
452 453 fm.end()
453 454
454 455 rootfm.end()
455 456
456 457 @command('archive',
457 458 [('', 'no-decode', None, _('do not pass files through decoders')),
458 459 ('p', 'prefix', '', _('directory prefix for files in archive'),
459 460 _('PREFIX')),
460 461 ('r', 'rev', '', _('revision to distribute'), _('REV')),
461 462 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
462 463 ] + subrepoopts + walkopts,
463 464 _('[OPTION]... DEST'),
464 465 helpcategory=command.CATEGORY_IMPORT_EXPORT)
465 466 def archive(ui, repo, dest, **opts):
466 467 '''create an unversioned archive of a repository revision
467 468
468 469 By default, the revision used is the parent of the working
469 470 directory; use -r/--rev to specify a different revision.
470 471
471 472 The archive type is automatically detected based on file
472 473 extension (to override, use -t/--type).
473 474
474 475 .. container:: verbose
475 476
476 477 Examples:
477 478
478 479 - create a zip file containing the 1.0 release::
479 480
480 481 hg archive -r 1.0 project-1.0.zip
481 482
482 483 - create a tarball excluding .hg files::
483 484
484 485 hg archive project.tar.gz -X ".hg*"
485 486
486 487 Valid types are:
487 488
488 489 :``files``: a directory full of files (default)
489 490 :``tar``: tar archive, uncompressed
490 491 :``tbz2``: tar archive, compressed using bzip2
491 492 :``tgz``: tar archive, compressed using gzip
492 493 :``uzip``: zip archive, uncompressed
493 494 :``zip``: zip archive, compressed using deflate
494 495
495 496 The exact name of the destination archive or directory is given
496 497 using a format string; see :hg:`help export` for details.
497 498
498 499 Each member added to an archive file has a directory prefix
499 500 prepended. Use -p/--prefix to specify a format string for the
500 501 prefix. The default is the basename of the archive, with suffixes
501 502 removed.
502 503
503 504 Returns 0 on success.
504 505 '''
505 506
506 507 opts = pycompat.byteskwargs(opts)
507 508 rev = opts.get('rev')
508 509 if rev:
509 510 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
510 511 ctx = scmutil.revsingle(repo, rev)
511 512 if not ctx:
512 513 raise error.Abort(_('no working directory: please specify a revision'))
513 514 node = ctx.node()
514 515 dest = cmdutil.makefilename(ctx, dest)
515 516 if os.path.realpath(dest) == repo.root:
516 517 raise error.Abort(_('repository root cannot be destination'))
517 518
518 519 kind = opts.get('type') or archival.guesskind(dest) or 'files'
519 520 prefix = opts.get('prefix')
520 521
521 522 if dest == '-':
522 523 if kind == 'files':
523 524 raise error.Abort(_('cannot archive plain files to stdout'))
524 525 dest = cmdutil.makefileobj(ctx, dest)
525 526 if not prefix:
526 527 prefix = os.path.basename(repo.root) + '-%h'
527 528
528 529 prefix = cmdutil.makefilename(ctx, prefix)
529 530 match = scmutil.match(ctx, [], opts)
530 531 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
531 532 match, prefix, subrepos=opts.get('subrepos'))
532 533
533 534 @command('backout',
534 535 [('', 'merge', None, _('merge with old dirstate parent after backout')),
535 536 ('', 'commit', None,
536 537 _('commit if no conflicts were encountered (DEPRECATED)')),
537 538 ('', 'no-commit', None, _('do not commit')),
538 539 ('', 'parent', '',
539 540 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
540 541 ('r', 'rev', '', _('revision to backout'), _('REV')),
541 542 ('e', 'edit', False, _('invoke editor on commit messages')),
542 543 ] + mergetoolopts + walkopts + commitopts + commitopts2,
543 544 _('[OPTION]... [-r] REV'),
544 545 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
545 546 def backout(ui, repo, node=None, rev=None, **opts):
546 547 '''reverse effect of earlier changeset
547 548
548 549 Prepare a new changeset with the effect of REV undone in the
549 550 current working directory. If no conflicts were encountered,
550 551 it will be committed immediately.
551 552
552 553 If REV is the parent of the working directory, then this new changeset
553 554 is committed automatically (unless --no-commit is specified).
554 555
555 556 .. note::
556 557
557 558 :hg:`backout` cannot be used to fix either an unwanted or
558 559 incorrect merge.
559 560
560 561 .. container:: verbose
561 562
562 563 Examples:
563 564
564 565 - Reverse the effect of the parent of the working directory.
565 566 This backout will be committed immediately::
566 567
567 568 hg backout -r .
568 569
569 570 - Reverse the effect of previous bad revision 23::
570 571
571 572 hg backout -r 23
572 573
573 574 - Reverse the effect of previous bad revision 23 and
574 575 leave changes uncommitted::
575 576
576 577 hg backout -r 23 --no-commit
577 578 hg commit -m "Backout revision 23"
578 579
579 580 By default, the pending changeset will have one parent,
580 581 maintaining a linear history. With --merge, the pending
581 582 changeset will instead have two parents: the old parent of the
582 583 working directory and a new child of REV that simply undoes REV.
583 584
584 585 Before version 1.7, the behavior without --merge was equivalent
585 586 to specifying --merge followed by :hg:`update --clean .` to
586 587 cancel the merge and leave the child of REV as a head to be
587 588 merged separately.
588 589
589 590 See :hg:`help dates` for a list of formats valid for -d/--date.
590 591
591 592 See :hg:`help revert` for a way to restore files to the state
592 593 of another revision.
593 594
594 595 Returns 0 on success, 1 if nothing to backout or there are unresolved
595 596 files.
596 597 '''
597 598 with repo.wlock(), repo.lock():
598 599 return _dobackout(ui, repo, node, rev, **opts)
599 600
600 601 def _dobackout(ui, repo, node=None, rev=None, **opts):
601 602 opts = pycompat.byteskwargs(opts)
602 603 if opts.get('commit') and opts.get('no_commit'):
603 604 raise error.Abort(_("cannot use --commit with --no-commit"))
604 605 if opts.get('merge') and opts.get('no_commit'):
605 606 raise error.Abort(_("cannot use --merge with --no-commit"))
606 607
607 608 if rev and node:
608 609 raise error.Abort(_("please specify just one revision"))
609 610
610 611 if not rev:
611 612 rev = node
612 613
613 614 if not rev:
614 615 raise error.Abort(_("please specify a revision to backout"))
615 616
616 617 date = opts.get('date')
617 618 if date:
618 619 opts['date'] = dateutil.parsedate(date)
619 620
620 621 cmdutil.checkunfinished(repo)
621 622 cmdutil.bailifchanged(repo)
622 623 node = scmutil.revsingle(repo, rev).node()
623 624
624 625 op1, op2 = repo.dirstate.parents()
625 626 if not repo.changelog.isancestor(node, op1):
626 627 raise error.Abort(_('cannot backout change that is not an ancestor'))
627 628
628 629 p1, p2 = repo.changelog.parents(node)
629 630 if p1 == nullid:
630 631 raise error.Abort(_('cannot backout a change with no parents'))
631 632 if p2 != nullid:
632 633 if not opts.get('parent'):
633 634 raise error.Abort(_('cannot backout a merge changeset'))
634 635 p = repo.lookup(opts['parent'])
635 636 if p not in (p1, p2):
636 637 raise error.Abort(_('%s is not a parent of %s') %
637 638 (short(p), short(node)))
638 639 parent = p
639 640 else:
640 641 if opts.get('parent'):
641 642 raise error.Abort(_('cannot use --parent on non-merge changeset'))
642 643 parent = p1
643 644
644 645 # the backout should appear on the same branch
645 646 branch = repo.dirstate.branch()
646 647 bheads = repo.branchheads(branch)
647 648 rctx = scmutil.revsingle(repo, hex(parent))
648 649 if not opts.get('merge') and op1 != node:
649 650 with dirstateguard.dirstateguard(repo, 'backout'):
650 651 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
651 652 with ui.configoverride(overrides, 'backout'):
652 653 stats = mergemod.update(repo, parent, branchmerge=True,
653 654 force=True, ancestor=node,
654 655 mergeancestor=False)
655 656 repo.setparents(op1, op2)
656 657 hg._showstats(repo, stats)
657 658 if stats.unresolvedcount:
658 659 repo.ui.status(_("use 'hg resolve' to retry unresolved "
659 660 "file merges\n"))
660 661 return 1
661 662 else:
662 663 hg.clean(repo, node, show_stats=False)
663 664 repo.dirstate.setbranch(branch)
664 665 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
665 666
666 667 if opts.get('no_commit'):
667 668 msg = _("changeset %s backed out, "
668 669 "don't forget to commit.\n")
669 670 ui.status(msg % short(node))
670 671 return 0
671 672
672 673 def commitfunc(ui, repo, message, match, opts):
673 674 editform = 'backout'
674 675 e = cmdutil.getcommiteditor(editform=editform,
675 676 **pycompat.strkwargs(opts))
676 677 if not message:
677 678 # we don't translate commit messages
678 679 message = "Backed out changeset %s" % short(node)
679 680 e = cmdutil.getcommiteditor(edit=True, editform=editform)
680 681 return repo.commit(message, opts.get('user'), opts.get('date'),
681 682 match, editor=e)
682 683 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
683 684 if not newnode:
684 685 ui.status(_("nothing changed\n"))
685 686 return 1
686 687 cmdutil.commitstatus(repo, newnode, branch, bheads)
687 688
688 689 def nice(node):
689 690 return '%d:%s' % (repo.changelog.rev(node), short(node))
690 691 ui.status(_('changeset %s backs out changeset %s\n') %
691 692 (nice(repo.changelog.tip()), nice(node)))
692 693 if opts.get('merge') and op1 != node:
693 694 hg.clean(repo, op1, show_stats=False)
694 695 ui.status(_('merging with changeset %s\n')
695 696 % nice(repo.changelog.tip()))
696 697 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
697 698 with ui.configoverride(overrides, 'backout'):
698 699 return hg.merge(repo, hex(repo.changelog.tip()))
699 700 return 0
700 701
701 702 @command('bisect',
702 703 [('r', 'reset', False, _('reset bisect state')),
703 704 ('g', 'good', False, _('mark changeset good')),
704 705 ('b', 'bad', False, _('mark changeset bad')),
705 706 ('s', 'skip', False, _('skip testing changeset')),
706 707 ('e', 'extend', False, _('extend the bisect range')),
707 708 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
708 709 ('U', 'noupdate', False, _('do not update to target'))],
709 710 _("[-gbsr] [-U] [-c CMD] [REV]"),
710 711 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
711 712 def bisect(ui, repo, rev=None, extra=None, command=None,
712 713 reset=None, good=None, bad=None, skip=None, extend=None,
713 714 noupdate=None):
714 715 """subdivision search of changesets
715 716
716 717 This command helps to find changesets which introduce problems. To
717 718 use, mark the earliest changeset you know exhibits the problem as
718 719 bad, then mark the latest changeset which is free from the problem
719 720 as good. Bisect will update your working directory to a revision
720 721 for testing (unless the -U/--noupdate option is specified). Once
721 722 you have performed tests, mark the working directory as good or
722 723 bad, and bisect will either update to another candidate changeset
723 724 or announce that it has found the bad revision.
724 725
725 726 As a shortcut, you can also use the revision argument to mark a
726 727 revision as good or bad without checking it out first.
727 728
728 729 If you supply a command, it will be used for automatic bisection.
729 730 The environment variable HG_NODE will contain the ID of the
730 731 changeset being tested. The exit status of the command will be
731 732 used to mark revisions as good or bad: status 0 means good, 125
732 733 means to skip the revision, 127 (command not found) will abort the
733 734 bisection, and any other non-zero exit status means the revision
734 735 is bad.
735 736
736 737 .. container:: verbose
737 738
738 739 Some examples:
739 740
740 741 - start a bisection with known bad revision 34, and good revision 12::
741 742
742 743 hg bisect --bad 34
743 744 hg bisect --good 12
744 745
745 746 - advance the current bisection by marking current revision as good or
746 747 bad::
747 748
748 749 hg bisect --good
749 750 hg bisect --bad
750 751
751 752 - mark the current revision, or a known revision, to be skipped (e.g. if
752 753 that revision is not usable because of another issue)::
753 754
754 755 hg bisect --skip
755 756 hg bisect --skip 23
756 757
757 758 - skip all revisions that do not touch directories ``foo`` or ``bar``::
758 759
759 760 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
760 761
761 762 - forget the current bisection::
762 763
763 764 hg bisect --reset
764 765
765 766 - use 'make && make tests' to automatically find the first broken
766 767 revision::
767 768
768 769 hg bisect --reset
769 770 hg bisect --bad 34
770 771 hg bisect --good 12
771 772 hg bisect --command "make && make tests"
772 773
773 774 - see all changesets whose states are already known in the current
774 775 bisection::
775 776
776 777 hg log -r "bisect(pruned)"
777 778
778 779 - see the changeset currently being bisected (especially useful
779 780 if running with -U/--noupdate)::
780 781
781 782 hg log -r "bisect(current)"
782 783
783 784 - see all changesets that took part in the current bisection::
784 785
785 786 hg log -r "bisect(range)"
786 787
787 788 - you can even get a nice graph::
788 789
789 790 hg log --graph -r "bisect(range)"
790 791
791 792 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
792 793
793 794 Returns 0 on success.
794 795 """
795 796 # backward compatibility
796 797 if rev in "good bad reset init".split():
797 798 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
798 799 cmd, rev, extra = rev, extra, None
799 800 if cmd == "good":
800 801 good = True
801 802 elif cmd == "bad":
802 803 bad = True
803 804 else:
804 805 reset = True
805 806 elif extra:
806 807 raise error.Abort(_('incompatible arguments'))
807 808
808 809 incompatibles = {
809 810 '--bad': bad,
810 811 '--command': bool(command),
811 812 '--extend': extend,
812 813 '--good': good,
813 814 '--reset': reset,
814 815 '--skip': skip,
815 816 }
816 817
817 818 enabled = [x for x in incompatibles if incompatibles[x]]
818 819
819 820 if len(enabled) > 1:
820 821 raise error.Abort(_('%s and %s are incompatible') %
821 822 tuple(sorted(enabled)[0:2]))
822 823
823 824 if reset:
824 825 hbisect.resetstate(repo)
825 826 return
826 827
827 828 state = hbisect.load_state(repo)
828 829
829 830 # update state
830 831 if good or bad or skip:
831 832 if rev:
832 833 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
833 834 else:
834 835 nodes = [repo.lookup('.')]
835 836 if good:
836 837 state['good'] += nodes
837 838 elif bad:
838 839 state['bad'] += nodes
839 840 elif skip:
840 841 state['skip'] += nodes
841 842 hbisect.save_state(repo, state)
842 843 if not (state['good'] and state['bad']):
843 844 return
844 845
845 846 def mayupdate(repo, node, show_stats=True):
846 847 """common used update sequence"""
847 848 if noupdate:
848 849 return
849 850 cmdutil.checkunfinished(repo)
850 851 cmdutil.bailifchanged(repo)
851 852 return hg.clean(repo, node, show_stats=show_stats)
852 853
853 854 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
854 855
855 856 if command:
856 857 changesets = 1
857 858 if noupdate:
858 859 try:
859 860 node = state['current'][0]
860 861 except LookupError:
861 862 raise error.Abort(_('current bisect revision is unknown - '
862 863 'start a new bisect to fix'))
863 864 else:
864 865 node, p2 = repo.dirstate.parents()
865 866 if p2 != nullid:
866 867 raise error.Abort(_('current bisect revision is a merge'))
867 868 if rev:
868 869 node = repo[scmutil.revsingle(repo, rev, node)].node()
869 870 try:
870 871 while changesets:
871 872 # update state
872 873 state['current'] = [node]
873 874 hbisect.save_state(repo, state)
874 875 status = ui.system(command, environ={'HG_NODE': hex(node)},
875 876 blockedtag='bisect_check')
876 877 if status == 125:
877 878 transition = "skip"
878 879 elif status == 0:
879 880 transition = "good"
880 881 # status < 0 means process was killed
881 882 elif status == 127:
882 883 raise error.Abort(_("failed to execute %s") % command)
883 884 elif status < 0:
884 885 raise error.Abort(_("%s killed") % command)
885 886 else:
886 887 transition = "bad"
887 888 state[transition].append(node)
888 889 ctx = repo[node]
889 890 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
890 891 transition))
891 892 hbisect.checkstate(state)
892 893 # bisect
893 894 nodes, changesets, bgood = hbisect.bisect(repo, state)
894 895 # update to next check
895 896 node = nodes[0]
896 897 mayupdate(repo, node, show_stats=False)
897 898 finally:
898 899 state['current'] = [node]
899 900 hbisect.save_state(repo, state)
900 901 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
901 902 return
902 903
903 904 hbisect.checkstate(state)
904 905
905 906 # actually bisect
906 907 nodes, changesets, good = hbisect.bisect(repo, state)
907 908 if extend:
908 909 if not changesets:
909 910 extendnode = hbisect.extendrange(repo, state, nodes, good)
910 911 if extendnode is not None:
911 912 ui.write(_("Extending search to changeset %d:%s\n")
912 913 % (extendnode.rev(), extendnode))
913 914 state['current'] = [extendnode.node()]
914 915 hbisect.save_state(repo, state)
915 916 return mayupdate(repo, extendnode.node())
916 917 raise error.Abort(_("nothing to extend"))
917 918
918 919 if changesets == 0:
919 920 hbisect.printresult(ui, repo, state, displayer, nodes, good)
920 921 else:
921 922 assert len(nodes) == 1 # only a single node can be tested next
922 923 node = nodes[0]
923 924 # compute the approximate number of remaining tests
924 925 tests, size = 0, 2
925 926 while size <= changesets:
926 927 tests, size = tests + 1, size * 2
927 928 rev = repo.changelog.rev(node)
928 929 ui.write(_("Testing changeset %d:%s "
929 930 "(%d changesets remaining, ~%d tests)\n")
930 931 % (rev, short(node), changesets, tests))
931 932 state['current'] = [node]
932 933 hbisect.save_state(repo, state)
933 934 return mayupdate(repo, node)
934 935
935 936 @command('bookmarks|bookmark',
936 937 [('f', 'force', False, _('force')),
937 938 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
938 939 ('d', 'delete', False, _('delete a given bookmark')),
939 940 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
940 941 ('i', 'inactive', False, _('mark a bookmark inactive')),
941 942 ('l', 'list', False, _('list existing bookmarks')),
942 943 ] + formatteropts,
943 944 _('hg bookmarks [OPTIONS]... [NAME]...'),
944 945 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
945 946 def bookmark(ui, repo, *names, **opts):
946 947 '''create a new bookmark or list existing bookmarks
947 948
948 949 Bookmarks are labels on changesets to help track lines of development.
949 950 Bookmarks are unversioned and can be moved, renamed and deleted.
950 951 Deleting or moving a bookmark has no effect on the associated changesets.
951 952
952 953 Creating or updating to a bookmark causes it to be marked as 'active'.
953 954 The active bookmark is indicated with a '*'.
954 955 When a commit is made, the active bookmark will advance to the new commit.
955 956 A plain :hg:`update` will also advance an active bookmark, if possible.
956 957 Updating away from a bookmark will cause it to be deactivated.
957 958
958 959 Bookmarks can be pushed and pulled between repositories (see
959 960 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
960 961 diverged, a new 'divergent bookmark' of the form 'name@path' will
961 962 be created. Using :hg:`merge` will resolve the divergence.
962 963
963 964 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
964 965 the active bookmark's name.
965 966
966 967 A bookmark named '@' has the special property that :hg:`clone` will
967 968 check it out by default if it exists.
968 969
969 970 .. container:: verbose
970 971
971 972 Template:
972 973
973 974 The following keywords are supported in addition to the common template
974 975 keywords and functions such as ``{bookmark}``. See also
975 976 :hg:`help templates`.
976 977
977 978 :active: Boolean. True if the bookmark is active.
978 979
979 980 Examples:
980 981
981 982 - create an active bookmark for a new line of development::
982 983
983 984 hg book new-feature
984 985
985 986 - create an inactive bookmark as a place marker::
986 987
987 988 hg book -i reviewed
988 989
989 990 - create an inactive bookmark on another changeset::
990 991
991 992 hg book -r .^ tested
992 993
993 994 - rename bookmark turkey to dinner::
994 995
995 996 hg book -m turkey dinner
996 997
997 998 - move the '@' bookmark from another branch::
998 999
999 1000 hg book -f @
1000 1001
1001 1002 - print only the active bookmark name::
1002 1003
1003 1004 hg book -ql .
1004 1005 '''
1005 1006 opts = pycompat.byteskwargs(opts)
1006 1007 force = opts.get('force')
1007 1008 rev = opts.get('rev')
1008 1009 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1009 1010
1010 1011 selactions = [k for k in ['delete', 'rename', 'list'] if opts.get(k)]
1011 1012 if len(selactions) > 1:
1012 1013 raise error.Abort(_('--%s and --%s are incompatible')
1013 1014 % tuple(selactions[:2]))
1014 1015 if selactions:
1015 1016 action = selactions[0]
1016 1017 elif names or rev:
1017 1018 action = 'add'
1018 1019 elif inactive:
1019 1020 action = 'inactive' # meaning deactivate
1020 1021 else:
1021 1022 action = 'list'
1022 1023
1023 1024 if rev and action in {'delete', 'rename', 'list'}:
1024 1025 raise error.Abort(_("--rev is incompatible with --%s") % action)
1025 1026 if inactive and action in {'delete', 'list'}:
1026 1027 raise error.Abort(_("--inactive is incompatible with --%s") % action)
1027 1028 if not names and action in {'add', 'delete'}:
1028 1029 raise error.Abort(_("bookmark name required"))
1029 1030
1030 1031 if action in {'add', 'delete', 'rename', 'inactive'}:
1031 1032 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
1032 1033 if action == 'delete':
1033 1034 names = pycompat.maplist(repo._bookmarks.expandname, names)
1034 1035 bookmarks.delete(repo, tr, names)
1035 1036 elif action == 'rename':
1036 1037 if not names:
1037 1038 raise error.Abort(_("new bookmark name required"))
1038 1039 elif len(names) > 1:
1039 1040 raise error.Abort(_("only one new bookmark name allowed"))
1040 1041 oldname = repo._bookmarks.expandname(opts['rename'])
1041 1042 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1042 1043 elif action == 'add':
1043 1044 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1044 1045 elif action == 'inactive':
1045 1046 if len(repo._bookmarks) == 0:
1046 1047 ui.status(_("no bookmarks set\n"))
1047 1048 elif not repo._activebookmark:
1048 1049 ui.status(_("no active bookmark\n"))
1049 1050 else:
1050 1051 bookmarks.deactivate(repo)
1051 1052 elif action == 'list':
1052 1053 names = pycompat.maplist(repo._bookmarks.expandname, names)
1053 1054 with ui.formatter('bookmarks', opts) as fm:
1054 1055 bookmarks.printbookmarks(ui, repo, fm, names)
1055 1056 else:
1056 1057 raise error.ProgrammingError('invalid action: %s' % action)
1057 1058
1058 1059 @command('branch',
1059 1060 [('f', 'force', None,
1060 1061 _('set branch name even if it shadows an existing branch')),
1061 1062 ('C', 'clean', None, _('reset branch name to parent branch name')),
1062 1063 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1063 1064 ],
1064 1065 _('[-fC] [NAME]'),
1065 1066 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
1066 1067 def branch(ui, repo, label=None, **opts):
1067 1068 """set or show the current branch name
1068 1069
1069 1070 .. note::
1070 1071
1071 1072 Branch names are permanent and global. Use :hg:`bookmark` to create a
1072 1073 light-weight bookmark instead. See :hg:`help glossary` for more
1073 1074 information about named branches and bookmarks.
1074 1075
1075 1076 With no argument, show the current branch name. With one argument,
1076 1077 set the working directory branch name (the branch will not exist
1077 1078 in the repository until the next commit). Standard practice
1078 1079 recommends that primary development take place on the 'default'
1079 1080 branch.
1080 1081
1081 1082 Unless -f/--force is specified, branch will not let you set a
1082 1083 branch name that already exists.
1083 1084
1084 1085 Use -C/--clean to reset the working directory branch to that of
1085 1086 the parent of the working directory, negating a previous branch
1086 1087 change.
1087 1088
1088 1089 Use the command :hg:`update` to switch to an existing branch. Use
1089 1090 :hg:`commit --close-branch` to mark this branch head as closed.
1090 1091 When all heads of a branch are closed, the branch will be
1091 1092 considered closed.
1092 1093
1093 1094 Returns 0 on success.
1094 1095 """
1095 1096 opts = pycompat.byteskwargs(opts)
1096 1097 revs = opts.get('rev')
1097 1098 if label:
1098 1099 label = label.strip()
1099 1100
1100 1101 if not opts.get('clean') and not label:
1101 1102 if revs:
1102 1103 raise error.Abort(_("no branch name specified for the revisions"))
1103 1104 ui.write("%s\n" % repo.dirstate.branch())
1104 1105 return
1105 1106
1106 1107 with repo.wlock():
1107 1108 if opts.get('clean'):
1108 1109 label = repo['.'].branch()
1109 1110 repo.dirstate.setbranch(label)
1110 1111 ui.status(_('reset working directory to branch %s\n') % label)
1111 1112 elif label:
1112 1113
1113 1114 scmutil.checknewlabel(repo, label, 'branch')
1114 1115 if revs:
1115 1116 return cmdutil.changebranch(ui, repo, revs, label)
1116 1117
1117 1118 if not opts.get('force') and label in repo.branchmap():
1118 1119 if label not in [p.branch() for p in repo[None].parents()]:
1119 1120 raise error.Abort(_('a branch of the same name already'
1120 1121 ' exists'),
1121 1122 # i18n: "it" refers to an existing branch
1122 1123 hint=_("use 'hg update' to switch to it"))
1123 1124
1124 1125 repo.dirstate.setbranch(label)
1125 1126 ui.status(_('marked working directory as branch %s\n') % label)
1126 1127
1127 1128 # find any open named branches aside from default
1128 1129 for n, h, t, c in repo.branchmap().iterbranches():
1129 1130 if n != "default" and not c:
1130 1131 return 0
1131 1132 ui.status(_('(branches are permanent and global, '
1132 1133 'did you want a bookmark?)\n'))
1133 1134
1134 1135 @command('branches',
1135 1136 [('a', 'active', False,
1136 1137 _('show only branches that have unmerged heads (DEPRECATED)')),
1137 1138 ('c', 'closed', False, _('show normal and closed branches')),
1138 1139 ('r', 'rev', [], _('show branch name(s) of the given rev'))
1139 1140 ] + formatteropts,
1140 1141 _('[-c]'),
1141 1142 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1142 1143 intents={INTENT_READONLY})
1143 1144 def branches(ui, repo, active=False, closed=False, **opts):
1144 1145 """list repository named branches
1145 1146
1146 1147 List the repository's named branches, indicating which ones are
1147 1148 inactive. If -c/--closed is specified, also list branches which have
1148 1149 been marked closed (see :hg:`commit --close-branch`).
1149 1150
1150 1151 Use the command :hg:`update` to switch to an existing branch.
1151 1152
1152 1153 .. container:: verbose
1153 1154
1154 1155 Template:
1155 1156
1156 1157 The following keywords are supported in addition to the common template
1157 1158 keywords and functions such as ``{branch}``. See also
1158 1159 :hg:`help templates`.
1159 1160
1160 1161 :active: Boolean. True if the branch is active.
1161 1162 :closed: Boolean. True if the branch is closed.
1162 1163 :current: Boolean. True if it is the current branch.
1163 1164
1164 1165 Returns 0.
1165 1166 """
1166 1167
1167 1168 opts = pycompat.byteskwargs(opts)
1168 1169 revs = opts.get('rev')
1169 1170 selectedbranches = None
1170 1171 if revs:
1171 1172 revs = scmutil.revrange(repo, revs)
1172 1173 getbi = repo.revbranchcache().branchinfo
1173 1174 selectedbranches = {getbi(r)[0] for r in revs}
1174 1175
1175 1176 ui.pager('branches')
1176 1177 fm = ui.formatter('branches', opts)
1177 1178 hexfunc = fm.hexfunc
1178 1179
1179 1180 allheads = set(repo.heads())
1180 1181 branches = []
1181 1182 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1182 1183 if selectedbranches is not None and tag not in selectedbranches:
1183 1184 continue
1184 1185 isactive = False
1185 1186 if not isclosed:
1186 1187 openheads = set(repo.branchmap().iteropen(heads))
1187 1188 isactive = bool(openheads & allheads)
1188 1189 branches.append((tag, repo[tip], isactive, not isclosed))
1189 1190 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1190 1191 reverse=True)
1191 1192
1192 1193 for tag, ctx, isactive, isopen in branches:
1193 1194 if active and not isactive:
1194 1195 continue
1195 1196 if isactive:
1196 1197 label = 'branches.active'
1197 1198 notice = ''
1198 1199 elif not isopen:
1199 1200 if not closed:
1200 1201 continue
1201 1202 label = 'branches.closed'
1202 1203 notice = _(' (closed)')
1203 1204 else:
1204 1205 label = 'branches.inactive'
1205 1206 notice = _(' (inactive)')
1206 1207 current = (tag == repo.dirstate.branch())
1207 1208 if current:
1208 1209 label = 'branches.current'
1209 1210
1210 1211 fm.startitem()
1211 1212 fm.write('branch', '%s', tag, label=label)
1212 1213 rev = ctx.rev()
1213 1214 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1214 1215 fmt = ' ' * padsize + ' %d:%s'
1215 1216 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1216 1217 label='log.changeset changeset.%s' % ctx.phasestr())
1217 1218 fm.context(ctx=ctx)
1218 1219 fm.data(active=isactive, closed=not isopen, current=current)
1219 1220 if not ui.quiet:
1220 1221 fm.plain(notice)
1221 1222 fm.plain('\n')
1222 1223 fm.end()
1223 1224
1224 1225 @command('bundle',
1225 1226 [('f', 'force', None, _('run even when the destination is unrelated')),
1226 1227 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1227 1228 _('REV')),
1228 1229 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1229 1230 _('BRANCH')),
1230 1231 ('', 'base', [],
1231 1232 _('a base changeset assumed to be available at the destination'),
1232 1233 _('REV')),
1233 1234 ('a', 'all', None, _('bundle all changesets in the repository')),
1234 1235 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1235 1236 ] + remoteopts,
1236 1237 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1237 1238 helpcategory=command.CATEGORY_IMPORT_EXPORT)
1238 1239 def bundle(ui, repo, fname, dest=None, **opts):
1239 1240 """create a bundle file
1240 1241
1241 1242 Generate a bundle file containing data to be transferred to another
1242 1243 repository.
1243 1244
1244 1245 To create a bundle containing all changesets, use -a/--all
1245 1246 (or --base null). Otherwise, hg assumes the destination will have
1246 1247 all the nodes you specify with --base parameters. Otherwise, hg
1247 1248 will assume the repository has all the nodes in destination, or
1248 1249 default-push/default if no destination is specified, where destination
1249 1250 is the repository you provide through DEST option.
1250 1251
1251 1252 You can change bundle format with the -t/--type option. See
1252 1253 :hg:`help bundlespec` for documentation on this format. By default,
1253 1254 the most appropriate format is used and compression defaults to
1254 1255 bzip2.
1255 1256
1256 1257 The bundle file can then be transferred using conventional means
1257 1258 and applied to another repository with the unbundle or pull
1258 1259 command. This is useful when direct push and pull are not
1259 1260 available or when exporting an entire repository is undesirable.
1260 1261
1261 1262 Applying bundles preserves all changeset contents including
1262 1263 permissions, copy/rename information, and revision history.
1263 1264
1264 1265 Returns 0 on success, 1 if no changes found.
1265 1266 """
1266 1267 opts = pycompat.byteskwargs(opts)
1267 1268 revs = None
1268 1269 if 'rev' in opts:
1269 1270 revstrings = opts['rev']
1270 1271 revs = scmutil.revrange(repo, revstrings)
1271 1272 if revstrings and not revs:
1272 1273 raise error.Abort(_('no commits to bundle'))
1273 1274
1274 1275 bundletype = opts.get('type', 'bzip2').lower()
1275 1276 try:
1276 1277 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1277 1278 except error.UnsupportedBundleSpecification as e:
1278 1279 raise error.Abort(pycompat.bytestr(e),
1279 1280 hint=_("see 'hg help bundlespec' for supported "
1280 1281 "values for --type"))
1281 1282 cgversion = bundlespec.contentopts["cg.version"]
1282 1283
1283 1284 # Packed bundles are a pseudo bundle format for now.
1284 1285 if cgversion == 's1':
1285 1286 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1286 1287 hint=_("use 'hg debugcreatestreamclonebundle'"))
1287 1288
1288 1289 if opts.get('all'):
1289 1290 if dest:
1290 1291 raise error.Abort(_("--all is incompatible with specifying "
1291 1292 "a destination"))
1292 1293 if opts.get('base'):
1293 1294 ui.warn(_("ignoring --base because --all was specified\n"))
1294 1295 base = [nullrev]
1295 1296 else:
1296 1297 base = scmutil.revrange(repo, opts.get('base'))
1297 1298 if cgversion not in changegroup.supportedoutgoingversions(repo):
1298 1299 raise error.Abort(_("repository does not support bundle version %s") %
1299 1300 cgversion)
1300 1301
1301 1302 if base:
1302 1303 if dest:
1303 1304 raise error.Abort(_("--base is incompatible with specifying "
1304 1305 "a destination"))
1305 1306 common = [repo[rev].node() for rev in base]
1306 1307 heads = [repo[r].node() for r in revs] if revs else None
1307 1308 outgoing = discovery.outgoing(repo, common, heads)
1308 1309 else:
1309 1310 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1310 1311 dest, branches = hg.parseurl(dest, opts.get('branch'))
1311 1312 other = hg.peer(repo, opts, dest)
1312 1313 revs = [repo[r].hex() for r in revs]
1313 1314 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1314 1315 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1315 1316 outgoing = discovery.findcommonoutgoing(repo, other,
1316 1317 onlyheads=heads,
1317 1318 force=opts.get('force'),
1318 1319 portable=True)
1319 1320
1320 1321 if not outgoing.missing:
1321 1322 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1322 1323 return 1
1323 1324
1324 1325 if cgversion == '01': #bundle1
1325 1326 bversion = 'HG10' + bundlespec.wirecompression
1326 1327 bcompression = None
1327 1328 elif cgversion in ('02', '03'):
1328 1329 bversion = 'HG20'
1329 1330 bcompression = bundlespec.wirecompression
1330 1331 else:
1331 1332 raise error.ProgrammingError(
1332 1333 'bundle: unexpected changegroup version %s' % cgversion)
1333 1334
1334 1335 # TODO compression options should be derived from bundlespec parsing.
1335 1336 # This is a temporary hack to allow adjusting bundle compression
1336 1337 # level without a) formalizing the bundlespec changes to declare it
1337 1338 # b) introducing a command flag.
1338 1339 compopts = {}
1339 1340 complevel = ui.configint('experimental',
1340 1341 'bundlecomplevel.' + bundlespec.compression)
1341 1342 if complevel is None:
1342 1343 complevel = ui.configint('experimental', 'bundlecomplevel')
1343 1344 if complevel is not None:
1344 1345 compopts['level'] = complevel
1345 1346
1346 1347 # Allow overriding the bundling of obsmarker in phases through
1347 1348 # configuration while we don't have a bundle version that include them
1348 1349 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1349 1350 bundlespec.contentopts['obsolescence'] = True
1350 1351 if repo.ui.configbool('experimental', 'bundle-phases'):
1351 1352 bundlespec.contentopts['phases'] = True
1352 1353
1353 1354 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1354 1355 bundlespec.contentopts, compression=bcompression,
1355 1356 compopts=compopts)
1356 1357
1357 1358 @command('cat',
1358 1359 [('o', 'output', '',
1359 1360 _('print output to file with formatted name'), _('FORMAT')),
1360 1361 ('r', 'rev', '', _('print the given revision'), _('REV')),
1361 1362 ('', 'decode', None, _('apply any matching decode filter')),
1362 1363 ] + walkopts + formatteropts,
1363 1364 _('[OPTION]... FILE...'),
1364 1365 helpcategory=command.CATEGORY_FILE_CONTENTS,
1365 1366 inferrepo=True,
1366 1367 intents={INTENT_READONLY})
1367 1368 def cat(ui, repo, file1, *pats, **opts):
1368 1369 """output the current or given revision of files
1369 1370
1370 1371 Print the specified files as they were at the given revision. If
1371 1372 no revision is given, the parent of the working directory is used.
1372 1373
1373 1374 Output may be to a file, in which case the name of the file is
1374 1375 given using a template string. See :hg:`help templates`. In addition
1375 1376 to the common template keywords, the following formatting rules are
1376 1377 supported:
1377 1378
1378 1379 :``%%``: literal "%" character
1379 1380 :``%s``: basename of file being printed
1380 1381 :``%d``: dirname of file being printed, or '.' if in repository root
1381 1382 :``%p``: root-relative path name of file being printed
1382 1383 :``%H``: changeset hash (40 hexadecimal digits)
1383 1384 :``%R``: changeset revision number
1384 1385 :``%h``: short-form changeset hash (12 hexadecimal digits)
1385 1386 :``%r``: zero-padded changeset revision number
1386 1387 :``%b``: basename of the exporting repository
1387 1388 :``\\``: literal "\\" character
1388 1389
1389 1390 .. container:: verbose
1390 1391
1391 1392 Template:
1392 1393
1393 1394 The following keywords are supported in addition to the common template
1394 1395 keywords and functions. See also :hg:`help templates`.
1395 1396
1396 1397 :data: String. File content.
1397 1398 :path: String. Repository-absolute path of the file.
1398 1399
1399 1400 Returns 0 on success.
1400 1401 """
1401 1402 opts = pycompat.byteskwargs(opts)
1402 1403 rev = opts.get('rev')
1403 1404 if rev:
1404 1405 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1405 1406 ctx = scmutil.revsingle(repo, rev)
1406 1407 m = scmutil.match(ctx, (file1,) + pats, opts)
1407 1408 fntemplate = opts.pop('output', '')
1408 1409 if cmdutil.isstdiofilename(fntemplate):
1409 1410 fntemplate = ''
1410 1411
1411 1412 if fntemplate:
1412 1413 fm = formatter.nullformatter(ui, 'cat', opts)
1413 1414 else:
1414 1415 ui.pager('cat')
1415 1416 fm = ui.formatter('cat', opts)
1416 1417 with fm:
1417 1418 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1418 1419 **pycompat.strkwargs(opts))
1419 1420
1420 1421 @command('clone',
1421 1422 [('U', 'noupdate', None, _('the clone will include an empty working '
1422 1423 'directory (only a repository)')),
1423 1424 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1424 1425 _('REV')),
1425 1426 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1426 1427 ' and its ancestors'), _('REV')),
1427 1428 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1428 1429 ' changesets and their ancestors'), _('BRANCH')),
1429 1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 1431 ('', 'uncompressed', None,
1431 1432 _('an alias to --stream (DEPRECATED)')),
1432 1433 ('', 'stream', None,
1433 1434 _('clone with minimal data processing')),
1434 1435 ] + remoteopts,
1435 1436 _('[OPTION]... SOURCE [DEST]'),
1436 1437 helpcategory=command.CATEGORY_REPO_CREATION,
1437 1438 helpbasic=True, norepo=True)
1438 1439 def clone(ui, source, dest=None, **opts):
1439 1440 """make a copy of an existing repository
1440 1441
1441 1442 Create a copy of an existing repository in a new directory.
1442 1443
1443 1444 If no destination directory name is specified, it defaults to the
1444 1445 basename of the source.
1445 1446
1446 1447 The location of the source is added to the new repository's
1447 1448 ``.hg/hgrc`` file, as the default to be used for future pulls.
1448 1449
1449 1450 Only local paths and ``ssh://`` URLs are supported as
1450 1451 destinations. For ``ssh://`` destinations, no working directory or
1451 1452 ``.hg/hgrc`` will be created on the remote side.
1452 1453
1453 1454 If the source repository has a bookmark called '@' set, that
1454 1455 revision will be checked out in the new repository by default.
1455 1456
1456 1457 To check out a particular version, use -u/--update, or
1457 1458 -U/--noupdate to create a clone with no working directory.
1458 1459
1459 1460 To pull only a subset of changesets, specify one or more revisions
1460 1461 identifiers with -r/--rev or branches with -b/--branch. The
1461 1462 resulting clone will contain only the specified changesets and
1462 1463 their ancestors. These options (or 'clone src#rev dest') imply
1463 1464 --pull, even for local source repositories.
1464 1465
1465 1466 In normal clone mode, the remote normalizes repository data into a common
1466 1467 exchange format and the receiving end translates this data into its local
1467 1468 storage format. --stream activates a different clone mode that essentially
1468 1469 copies repository files from the remote with minimal data processing. This
1469 1470 significantly reduces the CPU cost of a clone both remotely and locally.
1470 1471 However, it often increases the transferred data size by 30-40%. This can
1471 1472 result in substantially faster clones where I/O throughput is plentiful,
1472 1473 especially for larger repositories. A side-effect of --stream clones is
1473 1474 that storage settings and requirements on the remote are applied locally:
1474 1475 a modern client may inherit legacy or inefficient storage used by the
1475 1476 remote or a legacy Mercurial client may not be able to clone from a
1476 1477 modern Mercurial remote.
1477 1478
1478 1479 .. note::
1479 1480
1480 1481 Specifying a tag will include the tagged changeset but not the
1481 1482 changeset containing the tag.
1482 1483
1483 1484 .. container:: verbose
1484 1485
1485 1486 For efficiency, hardlinks are used for cloning whenever the
1486 1487 source and destination are on the same filesystem (note this
1487 1488 applies only to the repository data, not to the working
1488 1489 directory). Some filesystems, such as AFS, implement hardlinking
1489 1490 incorrectly, but do not report errors. In these cases, use the
1490 1491 --pull option to avoid hardlinking.
1491 1492
1492 1493 Mercurial will update the working directory to the first applicable
1493 1494 revision from this list:
1494 1495
1495 1496 a) null if -U or the source repository has no changesets
1496 1497 b) if -u . and the source repository is local, the first parent of
1497 1498 the source repository's working directory
1498 1499 c) the changeset specified with -u (if a branch name, this means the
1499 1500 latest head of that branch)
1500 1501 d) the changeset specified with -r
1501 1502 e) the tipmost head specified with -b
1502 1503 f) the tipmost head specified with the url#branch source syntax
1503 1504 g) the revision marked with the '@' bookmark, if present
1504 1505 h) the tipmost head of the default branch
1505 1506 i) tip
1506 1507
1507 1508 When cloning from servers that support it, Mercurial may fetch
1508 1509 pre-generated data from a server-advertised URL or inline from the
1509 1510 same stream. When this is done, hooks operating on incoming changesets
1510 1511 and changegroups may fire more than once, once for each pre-generated
1511 1512 bundle and as well as for any additional remaining data. In addition,
1512 1513 if an error occurs, the repository may be rolled back to a partial
1513 1514 clone. This behavior may change in future releases.
1514 1515 See :hg:`help -e clonebundles` for more.
1515 1516
1516 1517 Examples:
1517 1518
1518 1519 - clone a remote repository to a new directory named hg/::
1519 1520
1520 1521 hg clone https://www.mercurial-scm.org/repo/hg/
1521 1522
1522 1523 - create a lightweight local clone::
1523 1524
1524 1525 hg clone project/ project-feature/
1525 1526
1526 1527 - clone from an absolute path on an ssh server (note double-slash)::
1527 1528
1528 1529 hg clone ssh://user@server//home/projects/alpha/
1529 1530
1530 1531 - do a streaming clone while checking out a specified version::
1531 1532
1532 1533 hg clone --stream http://server/repo -u 1.5
1533 1534
1534 1535 - create a repository without changesets after a particular revision::
1535 1536
1536 1537 hg clone -r 04e544 experimental/ good/
1537 1538
1538 1539 - clone (and track) a particular named branch::
1539 1540
1540 1541 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1541 1542
1542 1543 See :hg:`help urls` for details on specifying URLs.
1543 1544
1544 1545 Returns 0 on success.
1545 1546 """
1546 1547 opts = pycompat.byteskwargs(opts)
1547 1548 if opts.get('noupdate') and opts.get('updaterev'):
1548 1549 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1549 1550
1550 1551 # --include/--exclude can come from narrow or sparse.
1551 1552 includepats, excludepats = None, None
1552 1553
1553 1554 # hg.clone() differentiates between None and an empty set. So make sure
1554 1555 # patterns are sets if narrow is requested without patterns.
1555 1556 if opts.get('narrow'):
1556 1557 includepats = set()
1557 1558 excludepats = set()
1558 1559
1559 1560 if opts.get('include'):
1560 1561 includepats = narrowspec.parsepatterns(opts.get('include'))
1561 1562 if opts.get('exclude'):
1562 1563 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1563 1564
1564 1565 r = hg.clone(ui, opts, source, dest,
1565 1566 pull=opts.get('pull'),
1566 1567 stream=opts.get('stream') or opts.get('uncompressed'),
1567 1568 revs=opts.get('rev'),
1568 1569 update=opts.get('updaterev') or not opts.get('noupdate'),
1569 1570 branch=opts.get('branch'),
1570 1571 shareopts=opts.get('shareopts'),
1571 1572 storeincludepats=includepats,
1572 1573 storeexcludepats=excludepats,
1573 1574 depth=opts.get('depth') or None)
1574 1575
1575 1576 return r is None
1576 1577
1577 1578 @command('commit|ci',
1578 1579 [('A', 'addremove', None,
1579 1580 _('mark new/missing files as added/removed before committing')),
1580 1581 ('', 'close-branch', None,
1581 1582 _('mark a branch head as closed')),
1582 1583 ('', 'amend', None, _('amend the parent of the working directory')),
1583 1584 ('s', 'secret', None, _('use the secret phase for committing')),
1584 1585 ('e', 'edit', None, _('invoke editor on commit messages')),
1585 1586 ('i', 'interactive', None, _('use interactive mode')),
1586 1587 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1587 1588 _('[OPTION]... [FILE]...'),
1588 1589 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True,
1589 1590 inferrepo=True)
1590 1591 def commit(ui, repo, *pats, **opts):
1591 1592 """commit the specified files or all outstanding changes
1592 1593
1593 1594 Commit changes to the given files into the repository. Unlike a
1594 1595 centralized SCM, this operation is a local operation. See
1595 1596 :hg:`push` for a way to actively distribute your changes.
1596 1597
1597 1598 If a list of files is omitted, all changes reported by :hg:`status`
1598 1599 will be committed.
1599 1600
1600 1601 If you are committing the result of a merge, do not provide any
1601 1602 filenames or -I/-X filters.
1602 1603
1603 1604 If no commit message is specified, Mercurial starts your
1604 1605 configured editor where you can enter a message. In case your
1605 1606 commit fails, you will find a backup of your message in
1606 1607 ``.hg/last-message.txt``.
1607 1608
1608 1609 The --close-branch flag can be used to mark the current branch
1609 1610 head closed. When all heads of a branch are closed, the branch
1610 1611 will be considered closed and no longer listed.
1611 1612
1612 1613 The --amend flag can be used to amend the parent of the
1613 1614 working directory with a new commit that contains the changes
1614 1615 in the parent in addition to those currently reported by :hg:`status`,
1615 1616 if there are any. The old commit is stored in a backup bundle in
1616 1617 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1617 1618 on how to restore it).
1618 1619
1619 1620 Message, user and date are taken from the amended commit unless
1620 1621 specified. When a message isn't specified on the command line,
1621 1622 the editor will open with the message of the amended commit.
1622 1623
1623 1624 It is not possible to amend public changesets (see :hg:`help phases`)
1624 1625 or changesets that have children.
1625 1626
1626 1627 See :hg:`help dates` for a list of formats valid for -d/--date.
1627 1628
1628 1629 Returns 0 on success, 1 if nothing changed.
1629 1630
1630 1631 .. container:: verbose
1631 1632
1632 1633 Examples:
1633 1634
1634 1635 - commit all files ending in .py::
1635 1636
1636 1637 hg commit --include "set:**.py"
1637 1638
1638 1639 - commit all non-binary files::
1639 1640
1640 1641 hg commit --exclude "set:binary()"
1641 1642
1642 1643 - amend the current commit and set the date to now::
1643 1644
1644 1645 hg commit --amend --date now
1645 1646 """
1646 1647 with repo.wlock(), repo.lock():
1647 1648 return _docommit(ui, repo, *pats, **opts)
1648 1649
1649 1650 def _docommit(ui, repo, *pats, **opts):
1650 1651 if opts.get(r'interactive'):
1651 1652 opts.pop(r'interactive')
1652 1653 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1653 1654 cmdutil.recordfilter, *pats,
1654 1655 **opts)
1655 1656 # ret can be 0 (no changes to record) or the value returned by
1656 1657 # commit(), 1 if nothing changed or None on success.
1657 1658 return 1 if ret == 0 else ret
1658 1659
1659 1660 opts = pycompat.byteskwargs(opts)
1660 1661 if opts.get('subrepos'):
1661 1662 if opts.get('amend'):
1662 1663 raise error.Abort(_('cannot amend with --subrepos'))
1663 1664 # Let --subrepos on the command line override config setting.
1664 1665 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1665 1666
1666 1667 cmdutil.checkunfinished(repo, commit=True)
1667 1668
1668 1669 branch = repo[None].branch()
1669 1670 bheads = repo.branchheads(branch)
1670 1671
1671 1672 extra = {}
1672 1673 if opts.get('close_branch'):
1673 1674 extra['close'] = '1'
1674 1675
1675 1676 if not bheads:
1676 1677 raise error.Abort(_('can only close branch heads'))
1677 1678 elif opts.get('amend'):
1678 1679 if (repo['.'].p1().branch() != branch and
1679 1680 repo['.'].p2().branch() != branch):
1680 1681 raise error.Abort(_('can only close branch heads'))
1681 1682
1682 1683 if opts.get('amend'):
1683 1684 if ui.configbool('ui', 'commitsubrepos'):
1684 1685 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1685 1686
1686 1687 old = repo['.']
1687 1688 rewriteutil.precheck(repo, [old.rev()], 'amend')
1688 1689
1689 1690 # Currently histedit gets confused if an amend happens while histedit
1690 1691 # is in progress. Since we have a checkunfinished command, we are
1691 1692 # temporarily honoring it.
1692 1693 #
1693 1694 # Note: eventually this guard will be removed. Please do not expect
1694 1695 # this behavior to remain.
1695 1696 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1696 1697 cmdutil.checkunfinished(repo)
1697 1698
1698 1699 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1699 1700 if node == old.node():
1700 1701 ui.status(_("nothing changed\n"))
1701 1702 return 1
1702 1703 else:
1703 1704 def commitfunc(ui, repo, message, match, opts):
1704 1705 overrides = {}
1705 1706 if opts.get('secret'):
1706 1707 overrides[('phases', 'new-commit')] = 'secret'
1707 1708
1708 1709 baseui = repo.baseui
1709 1710 with baseui.configoverride(overrides, 'commit'):
1710 1711 with ui.configoverride(overrides, 'commit'):
1711 1712 editform = cmdutil.mergeeditform(repo[None],
1712 1713 'commit.normal')
1713 1714 editor = cmdutil.getcommiteditor(
1714 1715 editform=editform, **pycompat.strkwargs(opts))
1715 1716 return repo.commit(message,
1716 1717 opts.get('user'),
1717 1718 opts.get('date'),
1718 1719 match,
1719 1720 editor=editor,
1720 1721 extra=extra)
1721 1722
1722 1723 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1723 1724
1724 1725 if not node:
1725 1726 stat = cmdutil.postcommitstatus(repo, pats, opts)
1726 1727 if stat[3]:
1727 1728 ui.status(_("nothing changed (%d missing files, see "
1728 1729 "'hg status')\n") % len(stat[3]))
1729 1730 else:
1730 1731 ui.status(_("nothing changed\n"))
1731 1732 return 1
1732 1733
1733 1734 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1734 1735
1735 1736 @command('config|showconfig|debugconfig',
1736 1737 [('u', 'untrusted', None, _('show untrusted configuration options')),
1737 1738 ('e', 'edit', None, _('edit user config')),
1738 1739 ('l', 'local', None, _('edit repository config')),
1739 1740 ('g', 'global', None, _('edit global config'))] + formatteropts,
1740 1741 _('[-u] [NAME]...'),
1741 1742 helpcategory=command.CATEGORY_HELP,
1742 1743 optionalrepo=True,
1743 1744 intents={INTENT_READONLY})
1744 1745 def config(ui, repo, *values, **opts):
1745 1746 """show combined config settings from all hgrc files
1746 1747
1747 1748 With no arguments, print names and values of all config items.
1748 1749
1749 1750 With one argument of the form section.name, print just the value
1750 1751 of that config item.
1751 1752
1752 1753 With multiple arguments, print names and values of all config
1753 1754 items with matching section names or section.names.
1754 1755
1755 1756 With --edit, start an editor on the user-level config file. With
1756 1757 --global, edit the system-wide config file. With --local, edit the
1757 1758 repository-level config file.
1758 1759
1759 1760 With --debug, the source (filename and line number) is printed
1760 1761 for each config item.
1761 1762
1762 1763 See :hg:`help config` for more information about config files.
1763 1764
1764 1765 .. container:: verbose
1765 1766
1766 1767 Template:
1767 1768
1768 1769 The following keywords are supported. See also :hg:`help templates`.
1769 1770
1770 1771 :name: String. Config name.
1771 1772 :source: String. Filename and line number where the item is defined.
1772 1773 :value: String. Config value.
1773 1774
1774 1775 Returns 0 on success, 1 if NAME does not exist.
1775 1776
1776 1777 """
1777 1778
1778 1779 opts = pycompat.byteskwargs(opts)
1779 1780 if opts.get('edit') or opts.get('local') or opts.get('global'):
1780 1781 if opts.get('local') and opts.get('global'):
1781 1782 raise error.Abort(_("can't use --local and --global together"))
1782 1783
1783 1784 if opts.get('local'):
1784 1785 if not repo:
1785 1786 raise error.Abort(_("can't use --local outside a repository"))
1786 1787 paths = [repo.vfs.join('hgrc')]
1787 1788 elif opts.get('global'):
1788 1789 paths = rcutil.systemrcpath()
1789 1790 else:
1790 1791 paths = rcutil.userrcpath()
1791 1792
1792 1793 for f in paths:
1793 1794 if os.path.exists(f):
1794 1795 break
1795 1796 else:
1796 1797 if opts.get('global'):
1797 1798 samplehgrc = uimod.samplehgrcs['global']
1798 1799 elif opts.get('local'):
1799 1800 samplehgrc = uimod.samplehgrcs['local']
1800 1801 else:
1801 1802 samplehgrc = uimod.samplehgrcs['user']
1802 1803
1803 1804 f = paths[0]
1804 1805 fp = open(f, "wb")
1805 1806 fp.write(util.tonativeeol(samplehgrc))
1806 1807 fp.close()
1807 1808
1808 1809 editor = ui.geteditor()
1809 1810 ui.system("%s \"%s\"" % (editor, f),
1810 1811 onerr=error.Abort, errprefix=_("edit failed"),
1811 1812 blockedtag='config_edit')
1812 1813 return
1813 1814 ui.pager('config')
1814 1815 fm = ui.formatter('config', opts)
1815 1816 for t, f in rcutil.rccomponents():
1816 1817 if t == 'path':
1817 1818 ui.debug('read config from: %s\n' % f)
1818 1819 elif t == 'items':
1819 1820 for section, name, value, source in f:
1820 1821 ui.debug('set config by: %s\n' % source)
1821 1822 else:
1822 1823 raise error.ProgrammingError('unknown rctype: %s' % t)
1823 1824 untrusted = bool(opts.get('untrusted'))
1824 1825
1825 1826 selsections = selentries = []
1826 1827 if values:
1827 1828 selsections = [v for v in values if '.' not in v]
1828 1829 selentries = [v for v in values if '.' in v]
1829 1830 uniquesel = (len(selentries) == 1 and not selsections)
1830 1831 selsections = set(selsections)
1831 1832 selentries = set(selentries)
1832 1833
1833 1834 matched = False
1834 1835 for section, name, value in ui.walkconfig(untrusted=untrusted):
1835 1836 source = ui.configsource(section, name, untrusted)
1836 1837 value = pycompat.bytestr(value)
1837 1838 if fm.isplain():
1838 1839 source = source or 'none'
1839 1840 value = value.replace('\n', '\\n')
1840 1841 entryname = section + '.' + name
1841 1842 if values and not (section in selsections or entryname in selentries):
1842 1843 continue
1843 1844 fm.startitem()
1844 1845 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1845 1846 if uniquesel:
1846 1847 fm.data(name=entryname)
1847 1848 fm.write('value', '%s\n', value)
1848 1849 else:
1849 1850 fm.write('name value', '%s=%s\n', entryname, value)
1850 1851 matched = True
1851 1852 fm.end()
1852 1853 if matched:
1853 1854 return 0
1854 1855 return 1
1855 1856
1856 1857 @command('copy|cp',
1857 1858 [('A', 'after', None, _('record a copy that has already occurred')),
1858 1859 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1859 1860 ] + walkopts + dryrunopts,
1860 1861 _('[OPTION]... [SOURCE]... DEST'),
1861 1862 helpcategory=command.CATEGORY_FILE_CONTENTS)
1862 1863 def copy(ui, repo, *pats, **opts):
1863 1864 """mark files as copied for the next commit
1864 1865
1865 1866 Mark dest as having copies of source files. If dest is a
1866 1867 directory, copies are put in that directory. If dest is a file,
1867 1868 the source must be a single file.
1868 1869
1869 1870 By default, this command copies the contents of files as they
1870 1871 exist in the working directory. If invoked with -A/--after, the
1871 1872 operation is recorded, but no copying is performed.
1872 1873
1873 1874 This command takes effect with the next commit. To undo a copy
1874 1875 before that, see :hg:`revert`.
1875 1876
1876 1877 Returns 0 on success, 1 if errors are encountered.
1877 1878 """
1878 1879 opts = pycompat.byteskwargs(opts)
1879 1880 with repo.wlock(False):
1880 1881 return cmdutil.copy(ui, repo, pats, opts)
1881 1882
1882 1883 @command(
1883 1884 'debugcommands', [], _('[COMMAND]'),
1884 1885 helpcategory=command.CATEGORY_HELP,
1885 1886 norepo=True)
1886 1887 def debugcommands(ui, cmd='', *args):
1887 1888 """list all available commands and options"""
1888 1889 for cmd, vals in sorted(table.iteritems()):
1889 1890 cmd = cmd.split('|')[0]
1890 1891 opts = ', '.join([i[1] for i in vals[1]])
1891 1892 ui.write('%s: %s\n' % (cmd, opts))
1892 1893
1893 1894 @command('debugcomplete',
1894 1895 [('o', 'options', None, _('show the command options'))],
1895 1896 _('[-o] CMD'),
1896 1897 helpcategory=command.CATEGORY_HELP,
1897 1898 norepo=True)
1898 1899 def debugcomplete(ui, cmd='', **opts):
1899 1900 """returns the completion list associated with the given command"""
1900 1901
1901 1902 if opts.get(r'options'):
1902 1903 options = []
1903 1904 otables = [globalopts]
1904 1905 if cmd:
1905 1906 aliases, entry = cmdutil.findcmd(cmd, table, False)
1906 1907 otables.append(entry[1])
1907 1908 for t in otables:
1908 1909 for o in t:
1909 1910 if "(DEPRECATED)" in o[3]:
1910 1911 continue
1911 1912 if o[0]:
1912 1913 options.append('-%s' % o[0])
1913 1914 options.append('--%s' % o[1])
1914 1915 ui.write("%s\n" % "\n".join(options))
1915 1916 return
1916 1917
1917 1918 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1918 1919 if ui.verbose:
1919 1920 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1920 1921 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1921 1922
1922 1923 @command('diff',
1923 1924 [('r', 'rev', [], _('revision'), _('REV')),
1924 1925 ('c', 'change', '', _('change made by revision'), _('REV'))
1925 1926 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1926 1927 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1927 1928 helpcategory=command.CATEGORY_FILE_CONTENTS,
1928 1929 helpbasic=True, inferrepo=True, intents={INTENT_READONLY})
1929 1930 def diff(ui, repo, *pats, **opts):
1930 1931 """diff repository (or selected files)
1931 1932
1932 1933 Show differences between revisions for the specified files.
1933 1934
1934 1935 Differences between files are shown using the unified diff format.
1935 1936
1936 1937 .. note::
1937 1938
1938 1939 :hg:`diff` may generate unexpected results for merges, as it will
1939 1940 default to comparing against the working directory's first
1940 1941 parent changeset if no revisions are specified.
1941 1942
1942 1943 When two revision arguments are given, then changes are shown
1943 1944 between those revisions. If only one revision is specified then
1944 1945 that revision is compared to the working directory, and, when no
1945 1946 revisions are specified, the working directory files are compared
1946 1947 to its first parent.
1947 1948
1948 1949 Alternatively you can specify -c/--change with a revision to see
1949 1950 the changes in that changeset relative to its first parent.
1950 1951
1951 1952 Without the -a/--text option, diff will avoid generating diffs of
1952 1953 files it detects as binary. With -a, diff will generate a diff
1953 1954 anyway, probably with undesirable results.
1954 1955
1955 1956 Use the -g/--git option to generate diffs in the git extended diff
1956 1957 format. For more information, read :hg:`help diffs`.
1957 1958
1958 1959 .. container:: verbose
1959 1960
1960 1961 Examples:
1961 1962
1962 1963 - compare a file in the current working directory to its parent::
1963 1964
1964 1965 hg diff foo.c
1965 1966
1966 1967 - compare two historical versions of a directory, with rename info::
1967 1968
1968 1969 hg diff --git -r 1.0:1.2 lib/
1969 1970
1970 1971 - get change stats relative to the last change on some date::
1971 1972
1972 1973 hg diff --stat -r "date('may 2')"
1973 1974
1974 1975 - diff all newly-added files that contain a keyword::
1975 1976
1976 1977 hg diff "set:added() and grep(GNU)"
1977 1978
1978 1979 - compare a revision and its parents::
1979 1980
1980 1981 hg diff -c 9353 # compare against first parent
1981 1982 hg diff -r 9353^:9353 # same using revset syntax
1982 1983 hg diff -r 9353^2:9353 # compare against the second parent
1983 1984
1984 1985 Returns 0 on success.
1985 1986 """
1986 1987
1987 1988 opts = pycompat.byteskwargs(opts)
1988 1989 revs = opts.get('rev')
1989 1990 change = opts.get('change')
1990 1991 stat = opts.get('stat')
1991 1992 reverse = opts.get('reverse')
1992 1993
1993 1994 if revs and change:
1994 1995 msg = _('cannot specify --rev and --change at the same time')
1995 1996 raise error.Abort(msg)
1996 1997 elif change:
1997 1998 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1998 1999 ctx2 = scmutil.revsingle(repo, change, None)
1999 2000 ctx1 = ctx2.p1()
2000 2001 else:
2001 2002 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
2002 2003 ctx1, ctx2 = scmutil.revpair(repo, revs)
2003 2004 node1, node2 = ctx1.node(), ctx2.node()
2004 2005
2005 2006 if reverse:
2006 2007 node1, node2 = node2, node1
2007 2008
2008 2009 diffopts = patch.diffallopts(ui, opts)
2009 2010 m = scmutil.match(ctx2, pats, opts)
2010 2011 m = repo.narrowmatch(m)
2011 2012 ui.pager('diff')
2012 2013 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2013 2014 listsubrepos=opts.get('subrepos'),
2014 2015 root=opts.get('root'))
2015 2016
2016 2017 @command('export',
2017 2018 [('B', 'bookmark', '',
2018 2019 _('export changes only reachable by given bookmark'), _('BOOKMARK')),
2019 2020 ('o', 'output', '',
2020 2021 _('print output to file with formatted name'), _('FORMAT')),
2021 2022 ('', 'switch-parent', None, _('diff against the second parent')),
2022 2023 ('r', 'rev', [], _('revisions to export'), _('REV')),
2023 2024 ] + diffopts + formatteropts,
2024 2025 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2025 2026 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2026 2027 helpbasic=True, intents={INTENT_READONLY})
2027 2028 def export(ui, repo, *changesets, **opts):
2028 2029 """dump the header and diffs for one or more changesets
2029 2030
2030 2031 Print the changeset header and diffs for one or more revisions.
2031 2032 If no revision is given, the parent of the working directory is used.
2032 2033
2033 2034 The information shown in the changeset header is: author, date,
2034 2035 branch name (if non-default), changeset hash, parent(s) and commit
2035 2036 comment.
2036 2037
2037 2038 .. note::
2038 2039
2039 2040 :hg:`export` may generate unexpected diff output for merge
2040 2041 changesets, as it will compare the merge changeset against its
2041 2042 first parent only.
2042 2043
2043 2044 Output may be to a file, in which case the name of the file is
2044 2045 given using a template string. See :hg:`help templates`. In addition
2045 2046 to the common template keywords, the following formatting rules are
2046 2047 supported:
2047 2048
2048 2049 :``%%``: literal "%" character
2049 2050 :``%H``: changeset hash (40 hexadecimal digits)
2050 2051 :``%N``: number of patches being generated
2051 2052 :``%R``: changeset revision number
2052 2053 :``%b``: basename of the exporting repository
2053 2054 :``%h``: short-form changeset hash (12 hexadecimal digits)
2054 2055 :``%m``: first line of the commit message (only alphanumeric characters)
2055 2056 :``%n``: zero-padded sequence number, starting at 1
2056 2057 :``%r``: zero-padded changeset revision number
2057 2058 :``\\``: literal "\\" character
2058 2059
2059 2060 Without the -a/--text option, export will avoid generating diffs
2060 2061 of files it detects as binary. With -a, export will generate a
2061 2062 diff anyway, probably with undesirable results.
2062 2063
2063 2064 With -B/--bookmark changesets reachable by the given bookmark are
2064 2065 selected.
2065 2066
2066 2067 Use the -g/--git option to generate diffs in the git extended diff
2067 2068 format. See :hg:`help diffs` for more information.
2068 2069
2069 2070 With the --switch-parent option, the diff will be against the
2070 2071 second parent. It can be useful to review a merge.
2071 2072
2072 2073 .. container:: verbose
2073 2074
2074 2075 Template:
2075 2076
2076 2077 The following keywords are supported in addition to the common template
2077 2078 keywords and functions. See also :hg:`help templates`.
2078 2079
2079 2080 :diff: String. Diff content.
2080 2081 :parents: List of strings. Parent nodes of the changeset.
2081 2082
2082 2083 Examples:
2083 2084
2084 2085 - use export and import to transplant a bugfix to the current
2085 2086 branch::
2086 2087
2087 2088 hg export -r 9353 | hg import -
2088 2089
2089 2090 - export all the changesets between two revisions to a file with
2090 2091 rename information::
2091 2092
2092 2093 hg export --git -r 123:150 > changes.txt
2093 2094
2094 2095 - split outgoing changes into a series of patches with
2095 2096 descriptive names::
2096 2097
2097 2098 hg export -r "outgoing()" -o "%n-%m.patch"
2098 2099
2099 2100 Returns 0 on success.
2100 2101 """
2101 2102 opts = pycompat.byteskwargs(opts)
2102 2103 bookmark = opts.get('bookmark')
2103 2104 changesets += tuple(opts.get('rev', []))
2104 2105
2105 2106 if bookmark and changesets:
2106 2107 raise error.Abort(_("-r and -B are mutually exclusive"))
2107 2108
2108 2109 if bookmark:
2109 2110 if bookmark not in repo._bookmarks:
2110 2111 raise error.Abort(_("bookmark '%s' not found") % bookmark)
2111 2112
2112 2113 revs = scmutil.bookmarkrevs(repo, bookmark)
2113 2114 else:
2114 2115 if not changesets:
2115 2116 changesets = ['.']
2116 2117
2117 2118 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
2118 2119 revs = scmutil.revrange(repo, changesets)
2119 2120
2120 2121 if not revs:
2121 2122 raise error.Abort(_("export requires at least one changeset"))
2122 2123 if len(revs) > 1:
2123 2124 ui.note(_('exporting patches:\n'))
2124 2125 else:
2125 2126 ui.note(_('exporting patch:\n'))
2126 2127
2127 2128 fntemplate = opts.get('output')
2128 2129 if cmdutil.isstdiofilename(fntemplate):
2129 2130 fntemplate = ''
2130 2131
2131 2132 if fntemplate:
2132 2133 fm = formatter.nullformatter(ui, 'export', opts)
2133 2134 else:
2134 2135 ui.pager('export')
2135 2136 fm = ui.formatter('export', opts)
2136 2137 with fm:
2137 2138 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2138 2139 switch_parent=opts.get('switch_parent'),
2139 2140 opts=patch.diffallopts(ui, opts))
2140 2141
2141 2142 @command('files',
2142 2143 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2143 2144 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2144 2145 ] + walkopts + formatteropts + subrepoopts,
2145 2146 _('[OPTION]... [FILE]...'),
2146 2147 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2147 2148 intents={INTENT_READONLY})
2148 2149 def files(ui, repo, *pats, **opts):
2149 2150 """list tracked files
2150 2151
2151 2152 Print files under Mercurial control in the working directory or
2152 2153 specified revision for given files (excluding removed files).
2153 2154 Files can be specified as filenames or filesets.
2154 2155
2155 2156 If no files are given to match, this command prints the names
2156 2157 of all files under Mercurial control.
2157 2158
2158 2159 .. container:: verbose
2159 2160
2160 2161 Template:
2161 2162
2162 2163 The following keywords are supported in addition to the common template
2163 2164 keywords and functions. See also :hg:`help templates`.
2164 2165
2165 2166 :flags: String. Character denoting file's symlink and executable bits.
2166 2167 :path: String. Repository-absolute path of the file.
2167 2168 :size: Integer. Size of the file in bytes.
2168 2169
2169 2170 Examples:
2170 2171
2171 2172 - list all files under the current directory::
2172 2173
2173 2174 hg files .
2174 2175
2175 2176 - shows sizes and flags for current revision::
2176 2177
2177 2178 hg files -vr .
2178 2179
2179 2180 - list all files named README::
2180 2181
2181 2182 hg files -I "**/README"
2182 2183
2183 2184 - list all binary files::
2184 2185
2185 2186 hg files "set:binary()"
2186 2187
2187 2188 - find files containing a regular expression::
2188 2189
2189 2190 hg files "set:grep('bob')"
2190 2191
2191 2192 - search tracked file contents with xargs and grep::
2192 2193
2193 2194 hg files -0 | xargs -0 grep foo
2194 2195
2195 2196 See :hg:`help patterns` and :hg:`help filesets` for more information
2196 2197 on specifying file patterns.
2197 2198
2198 2199 Returns 0 if a match is found, 1 otherwise.
2199 2200
2200 2201 """
2201 2202
2202 2203 opts = pycompat.byteskwargs(opts)
2203 2204 rev = opts.get('rev')
2204 2205 if rev:
2205 2206 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2206 2207 ctx = scmutil.revsingle(repo, rev, None)
2207 2208
2208 2209 end = '\n'
2209 2210 if opts.get('print0'):
2210 2211 end = '\0'
2211 2212 fmt = '%s' + end
2212 2213
2213 2214 m = scmutil.match(ctx, pats, opts)
2214 2215 ui.pager('files')
2215 2216 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2216 2217 with ui.formatter('files', opts) as fm:
2217 2218 return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt,
2218 2219 opts.get('subrepos'))
2219 2220
2220 2221 @command(
2221 2222 'forget',
2222 2223 [('i', 'interactive', None, _('use interactive mode')),
2223 2224 ] + walkopts + dryrunopts,
2224 2225 _('[OPTION]... FILE...'),
2225 2226 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2226 2227 helpbasic=True, inferrepo=True)
2227 2228 def forget(ui, repo, *pats, **opts):
2228 2229 """forget the specified files on the next commit
2229 2230
2230 2231 Mark the specified files so they will no longer be tracked
2231 2232 after the next commit.
2232 2233
2233 2234 This only removes files from the current branch, not from the
2234 2235 entire project history, and it does not delete them from the
2235 2236 working directory.
2236 2237
2237 2238 To delete the file from the working directory, see :hg:`remove`.
2238 2239
2239 2240 To undo a forget before the next commit, see :hg:`add`.
2240 2241
2241 2242 .. container:: verbose
2242 2243
2243 2244 Examples:
2244 2245
2245 2246 - forget newly-added binary files::
2246 2247
2247 2248 hg forget "set:added() and binary()"
2248 2249
2249 2250 - forget files that would be excluded by .hgignore::
2250 2251
2251 2252 hg forget "set:hgignore()"
2252 2253
2253 2254 Returns 0 on success.
2254 2255 """
2255 2256
2256 2257 opts = pycompat.byteskwargs(opts)
2257 2258 if not pats:
2258 2259 raise error.Abort(_('no files specified'))
2259 2260
2260 2261 m = scmutil.match(repo[None], pats, opts)
2261 2262 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2262 2263 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2263 2264 rejected = cmdutil.forget(ui, repo, m, prefix="", uipathfn=uipathfn,
2264 2265 explicitonly=False, dryrun=dryrun,
2265 2266 interactive=interactive)[0]
2266 2267 return rejected and 1 or 0
2267 2268
2268 2269 @command(
2269 2270 'graft',
2270 2271 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2271 2272 ('', 'base', '',
2272 2273 _('base revision when doing the graft merge (ADVANCED)'), _('REV')),
2273 2274 ('c', 'continue', False, _('resume interrupted graft')),
2274 2275 ('', 'stop', False, _('stop interrupted graft')),
2275 2276 ('', 'abort', False, _('abort interrupted graft')),
2276 2277 ('e', 'edit', False, _('invoke editor on commit messages')),
2277 2278 ('', 'log', None, _('append graft info to log message')),
2278 2279 ('', 'no-commit', None,
2279 2280 _("don't commit, just apply the changes in working directory")),
2280 2281 ('f', 'force', False, _('force graft')),
2281 2282 ('D', 'currentdate', False,
2282 2283 _('record the current date as commit date')),
2283 2284 ('U', 'currentuser', False,
2284 2285 _('record the current user as committer'))]
2285 2286 + commitopts2 + mergetoolopts + dryrunopts,
2286 2287 _('[OPTION]... [-r REV]... REV...'),
2287 2288 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
2288 2289 def graft(ui, repo, *revs, **opts):
2289 2290 '''copy changes from other branches onto the current branch
2290 2291
2291 2292 This command uses Mercurial's merge logic to copy individual
2292 2293 changes from other branches without merging branches in the
2293 2294 history graph. This is sometimes known as 'backporting' or
2294 2295 'cherry-picking'. By default, graft will copy user, date, and
2295 2296 description from the source changesets.
2296 2297
2297 2298 Changesets that are ancestors of the current revision, that have
2298 2299 already been grafted, or that are merges will be skipped.
2299 2300
2300 2301 If --log is specified, log messages will have a comment appended
2301 2302 of the form::
2302 2303
2303 2304 (grafted from CHANGESETHASH)
2304 2305
2305 2306 If --force is specified, revisions will be grafted even if they
2306 2307 are already ancestors of, or have been grafted to, the destination.
2307 2308 This is useful when the revisions have since been backed out.
2308 2309
2309 2310 If a graft merge results in conflicts, the graft process is
2310 2311 interrupted so that the current merge can be manually resolved.
2311 2312 Once all conflicts are addressed, the graft process can be
2312 2313 continued with the -c/--continue option.
2313 2314
2314 2315 The -c/--continue option reapplies all the earlier options.
2315 2316
2316 2317 .. container:: verbose
2317 2318
2318 2319 The --base option exposes more of how graft internally uses merge with a
2319 2320 custom base revision. --base can be used to specify another ancestor than
2320 2321 the first and only parent.
2321 2322
2322 2323 The command::
2323 2324
2324 2325 hg graft -r 345 --base 234
2325 2326
2326 2327 is thus pretty much the same as::
2327 2328
2328 2329 hg diff -r 234 -r 345 | hg import
2329 2330
2330 2331 but using merge to resolve conflicts and track moved files.
2331 2332
2332 2333 The result of a merge can thus be backported as a single commit by
2333 2334 specifying one of the merge parents as base, and thus effectively
2334 2335 grafting the changes from the other side.
2335 2336
2336 2337 It is also possible to collapse multiple changesets and clean up history
2337 2338 by specifying another ancestor as base, much like rebase --collapse
2338 2339 --keep.
2339 2340
2340 2341 The commit message can be tweaked after the fact using commit --amend .
2341 2342
2342 2343 For using non-ancestors as the base to backout changes, see the backout
2343 2344 command and the hidden --parent option.
2344 2345
2345 2346 .. container:: verbose
2346 2347
2347 2348 Examples:
2348 2349
2349 2350 - copy a single change to the stable branch and edit its description::
2350 2351
2351 2352 hg update stable
2352 2353 hg graft --edit 9393
2353 2354
2354 2355 - graft a range of changesets with one exception, updating dates::
2355 2356
2356 2357 hg graft -D "2085::2093 and not 2091"
2357 2358
2358 2359 - continue a graft after resolving conflicts::
2359 2360
2360 2361 hg graft -c
2361 2362
2362 2363 - show the source of a grafted changeset::
2363 2364
2364 2365 hg log --debug -r .
2365 2366
2366 2367 - show revisions sorted by date::
2367 2368
2368 2369 hg log -r "sort(all(), date)"
2369 2370
2370 2371 - backport the result of a merge as a single commit::
2371 2372
2372 2373 hg graft -r 123 --base 123^
2373 2374
2374 2375 - land a feature branch as one changeset::
2375 2376
2376 2377 hg up -cr default
2377 2378 hg graft -r featureX --base "ancestor('featureX', 'default')"
2378 2379
2379 2380 See :hg:`help revisions` for more about specifying revisions.
2380 2381
2381 2382 Returns 0 on successful completion.
2382 2383 '''
2383 2384 with repo.wlock():
2384 2385 return _dograft(ui, repo, *revs, **opts)
2385 2386
2386 2387 def _dograft(ui, repo, *revs, **opts):
2387 2388 opts = pycompat.byteskwargs(opts)
2388 2389 if revs and opts.get('rev'):
2389 2390 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2390 2391 'revision ordering!\n'))
2391 2392
2392 2393 revs = list(revs)
2393 2394 revs.extend(opts.get('rev'))
2394 2395 basectx = None
2395 2396 if opts.get('base'):
2396 2397 basectx = scmutil.revsingle(repo, opts['base'], None)
2397 2398 # a dict of data to be stored in state file
2398 2399 statedata = {}
2399 2400 # list of new nodes created by ongoing graft
2400 2401 statedata['newnodes'] = []
2401 2402
2402 2403 if opts.get('user') and opts.get('currentuser'):
2403 2404 raise error.Abort(_('--user and --currentuser are mutually exclusive'))
2404 2405 if opts.get('date') and opts.get('currentdate'):
2405 2406 raise error.Abort(_('--date and --currentdate are mutually exclusive'))
2406 2407 if not opts.get('user') and opts.get('currentuser'):
2407 2408 opts['user'] = ui.username()
2408 2409 if not opts.get('date') and opts.get('currentdate'):
2409 2410 opts['date'] = "%d %d" % dateutil.makedate()
2410 2411
2411 2412 editor = cmdutil.getcommiteditor(editform='graft',
2412 2413 **pycompat.strkwargs(opts))
2413 2414
2414 2415 cont = False
2415 2416 if opts.get('no_commit'):
2416 2417 if opts.get('edit'):
2417 2418 raise error.Abort(_("cannot specify --no-commit and "
2418 2419 "--edit together"))
2419 2420 if opts.get('currentuser'):
2420 2421 raise error.Abort(_("cannot specify --no-commit and "
2421 2422 "--currentuser together"))
2422 2423 if opts.get('currentdate'):
2423 2424 raise error.Abort(_("cannot specify --no-commit and "
2424 2425 "--currentdate together"))
2425 2426 if opts.get('log'):
2426 2427 raise error.Abort(_("cannot specify --no-commit and "
2427 2428 "--log together"))
2428 2429
2429 2430 graftstate = statemod.cmdstate(repo, 'graftstate')
2430 2431
2431 2432 if opts.get('stop'):
2432 2433 if opts.get('continue'):
2433 2434 raise error.Abort(_("cannot use '--continue' and "
2434 2435 "'--stop' together"))
2435 2436 if opts.get('abort'):
2436 2437 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2437 2438
2438 2439 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2439 2440 opts.get('date'), opts.get('currentdate'),
2440 2441 opts.get('currentuser'), opts.get('rev'))):
2441 2442 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2442 2443 return _stopgraft(ui, repo, graftstate)
2443 2444 elif opts.get('abort'):
2444 2445 if opts.get('continue'):
2445 2446 raise error.Abort(_("cannot use '--continue' and "
2446 2447 "'--abort' together"))
2447 2448 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2448 2449 opts.get('date'), opts.get('currentdate'),
2449 2450 opts.get('currentuser'), opts.get('rev'))):
2450 2451 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2451 2452
2452 2453 return _abortgraft(ui, repo, graftstate)
2453 2454 elif opts.get('continue'):
2454 2455 cont = True
2455 2456 if revs:
2456 2457 raise error.Abort(_("can't specify --continue and revisions"))
2457 2458 # read in unfinished revisions
2458 2459 if graftstate.exists():
2459 2460 statedata = _readgraftstate(repo, graftstate)
2460 2461 if statedata.get('date'):
2461 2462 opts['date'] = statedata['date']
2462 2463 if statedata.get('user'):
2463 2464 opts['user'] = statedata['user']
2464 2465 if statedata.get('log'):
2465 2466 opts['log'] = True
2466 2467 if statedata.get('no_commit'):
2467 2468 opts['no_commit'] = statedata.get('no_commit')
2468 2469 nodes = statedata['nodes']
2469 2470 revs = [repo[node].rev() for node in nodes]
2470 2471 else:
2471 2472 cmdutil.wrongtooltocontinue(repo, _('graft'))
2472 2473 else:
2473 2474 if not revs:
2474 2475 raise error.Abort(_('no revisions specified'))
2475 2476 cmdutil.checkunfinished(repo)
2476 2477 cmdutil.bailifchanged(repo)
2477 2478 revs = scmutil.revrange(repo, revs)
2478 2479
2479 2480 skipped = set()
2480 2481 if basectx is None:
2481 2482 # check for merges
2482 2483 for rev in repo.revs('%ld and merge()', revs):
2483 2484 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2484 2485 skipped.add(rev)
2485 2486 revs = [r for r in revs if r not in skipped]
2486 2487 if not revs:
2487 2488 return -1
2488 2489 if basectx is not None and len(revs) != 1:
2489 2490 raise error.Abort(_('only one revision allowed with --base '))
2490 2491
2491 2492 # Don't check in the --continue case, in effect retaining --force across
2492 2493 # --continues. That's because without --force, any revisions we decided to
2493 2494 # skip would have been filtered out here, so they wouldn't have made their
2494 2495 # way to the graftstate. With --force, any revisions we would have otherwise
2495 2496 # skipped would not have been filtered out, and if they hadn't been applied
2496 2497 # already, they'd have been in the graftstate.
2497 2498 if not (cont or opts.get('force')) and basectx is None:
2498 2499 # check for ancestors of dest branch
2499 2500 crev = repo['.'].rev()
2500 2501 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2501 2502 # XXX make this lazy in the future
2502 2503 # don't mutate while iterating, create a copy
2503 2504 for rev in list(revs):
2504 2505 if rev in ancestors:
2505 2506 ui.warn(_('skipping ancestor revision %d:%s\n') %
2506 2507 (rev, repo[rev]))
2507 2508 # XXX remove on list is slow
2508 2509 revs.remove(rev)
2509 2510 if not revs:
2510 2511 return -1
2511 2512
2512 2513 # analyze revs for earlier grafts
2513 2514 ids = {}
2514 2515 for ctx in repo.set("%ld", revs):
2515 2516 ids[ctx.hex()] = ctx.rev()
2516 2517 n = ctx.extra().get('source')
2517 2518 if n:
2518 2519 ids[n] = ctx.rev()
2519 2520
2520 2521 # check ancestors for earlier grafts
2521 2522 ui.debug('scanning for duplicate grafts\n')
2522 2523
2523 2524 # The only changesets we can be sure doesn't contain grafts of any
2524 2525 # revs, are the ones that are common ancestors of *all* revs:
2525 2526 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2526 2527 ctx = repo[rev]
2527 2528 n = ctx.extra().get('source')
2528 2529 if n in ids:
2529 2530 try:
2530 2531 r = repo[n].rev()
2531 2532 except error.RepoLookupError:
2532 2533 r = None
2533 2534 if r in revs:
2534 2535 ui.warn(_('skipping revision %d:%s '
2535 2536 '(already grafted to %d:%s)\n')
2536 2537 % (r, repo[r], rev, ctx))
2537 2538 revs.remove(r)
2538 2539 elif ids[n] in revs:
2539 2540 if r is None:
2540 2541 ui.warn(_('skipping already grafted revision %d:%s '
2541 2542 '(%d:%s also has unknown origin %s)\n')
2542 2543 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2543 2544 else:
2544 2545 ui.warn(_('skipping already grafted revision %d:%s '
2545 2546 '(%d:%s also has origin %d:%s)\n')
2546 2547 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2547 2548 revs.remove(ids[n])
2548 2549 elif ctx.hex() in ids:
2549 2550 r = ids[ctx.hex()]
2550 2551 if r in revs:
2551 2552 ui.warn(_('skipping already grafted revision %d:%s '
2552 2553 '(was grafted from %d:%s)\n') %
2553 2554 (r, repo[r], rev, ctx))
2554 2555 revs.remove(r)
2555 2556 if not revs:
2556 2557 return -1
2557 2558
2558 2559 if opts.get('no_commit'):
2559 2560 statedata['no_commit'] = True
2560 2561 for pos, ctx in enumerate(repo.set("%ld", revs)):
2561 2562 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2562 2563 ctx.description().split('\n', 1)[0])
2563 2564 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2564 2565 if names:
2565 2566 desc += ' (%s)' % ' '.join(names)
2566 2567 ui.status(_('grafting %s\n') % desc)
2567 2568 if opts.get('dry_run'):
2568 2569 continue
2569 2570
2570 2571 source = ctx.extra().get('source')
2571 2572 extra = {}
2572 2573 if source:
2573 2574 extra['source'] = source
2574 2575 extra['intermediate-source'] = ctx.hex()
2575 2576 else:
2576 2577 extra['source'] = ctx.hex()
2577 2578 user = ctx.user()
2578 2579 if opts.get('user'):
2579 2580 user = opts['user']
2580 2581 statedata['user'] = user
2581 2582 date = ctx.date()
2582 2583 if opts.get('date'):
2583 2584 date = opts['date']
2584 2585 statedata['date'] = date
2585 2586 message = ctx.description()
2586 2587 if opts.get('log'):
2587 2588 message += '\n(grafted from %s)' % ctx.hex()
2588 2589 statedata['log'] = True
2589 2590
2590 2591 # we don't merge the first commit when continuing
2591 2592 if not cont:
2592 2593 # perform the graft merge with p1(rev) as 'ancestor'
2593 2594 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2594 2595 base = ctx.p1() if basectx is None else basectx
2595 2596 with ui.configoverride(overrides, 'graft'):
2596 2597 stats = mergemod.graft(repo, ctx, base, ['local', 'graft'])
2597 2598 # report any conflicts
2598 2599 if stats.unresolvedcount > 0:
2599 2600 # write out state for --continue
2600 2601 nodes = [repo[rev].hex() for rev in revs[pos:]]
2601 2602 statedata['nodes'] = nodes
2602 2603 stateversion = 1
2603 2604 graftstate.save(stateversion, statedata)
2604 2605 hint = _("use 'hg resolve' and 'hg graft --continue'")
2605 2606 raise error.Abort(
2606 2607 _("unresolved conflicts, can't continue"),
2607 2608 hint=hint)
2608 2609 else:
2609 2610 cont = False
2610 2611
2611 2612 # commit if --no-commit is false
2612 2613 if not opts.get('no_commit'):
2613 2614 node = repo.commit(text=message, user=user, date=date, extra=extra,
2614 2615 editor=editor)
2615 2616 if node is None:
2616 2617 ui.warn(
2617 2618 _('note: graft of %d:%s created no changes to commit\n') %
2618 2619 (ctx.rev(), ctx))
2619 2620 # checking that newnodes exist because old state files won't have it
2620 2621 elif statedata.get('newnodes') is not None:
2621 2622 statedata['newnodes'].append(node)
2622 2623
2623 2624 # remove state when we complete successfully
2624 2625 if not opts.get('dry_run'):
2625 2626 graftstate.delete()
2626 2627
2627 2628 return 0
2628 2629
2629 2630 def _abortgraft(ui, repo, graftstate):
2630 2631 """abort the interrupted graft and rollbacks to the state before interrupted
2631 2632 graft"""
2632 2633 if not graftstate.exists():
2633 2634 raise error.Abort(_("no interrupted graft to abort"))
2634 2635 statedata = _readgraftstate(repo, graftstate)
2635 2636 newnodes = statedata.get('newnodes')
2636 2637 if newnodes is None:
2637 2638 # and old graft state which does not have all the data required to abort
2638 2639 # the graft
2639 2640 raise error.Abort(_("cannot abort using an old graftstate"))
2640 2641
2641 2642 # changeset from which graft operation was started
2642 2643 if len(newnodes) > 0:
2643 2644 startctx = repo[newnodes[0]].p1()
2644 2645 else:
2645 2646 startctx = repo['.']
2646 2647 # whether to strip or not
2647 2648 cleanup = False
2648 2649 if newnodes:
2649 2650 newnodes = [repo[r].rev() for r in newnodes]
2650 2651 cleanup = True
2651 2652 # checking that none of the newnodes turned public or is public
2652 2653 immutable = [c for c in newnodes if not repo[c].mutable()]
2653 2654 if immutable:
2654 2655 repo.ui.warn(_("cannot clean up public changesets %s\n")
2655 2656 % ', '.join(bytes(repo[r]) for r in immutable),
2656 2657 hint=_("see 'hg help phases' for details"))
2657 2658 cleanup = False
2658 2659
2659 2660 # checking that no new nodes are created on top of grafted revs
2660 2661 desc = set(repo.changelog.descendants(newnodes))
2661 2662 if desc - set(newnodes):
2662 2663 repo.ui.warn(_("new changesets detected on destination "
2663 2664 "branch, can't strip\n"))
2664 2665 cleanup = False
2665 2666
2666 2667 if cleanup:
2667 2668 with repo.wlock(), repo.lock():
2668 2669 hg.updaterepo(repo, startctx.node(), overwrite=True)
2669 2670 # stripping the new nodes created
2670 2671 strippoints = [c.node() for c in repo.set("roots(%ld)",
2671 2672 newnodes)]
2672 2673 repair.strip(repo.ui, repo, strippoints, backup=False)
2673 2674
2674 2675 if not cleanup:
2675 2676 # we don't update to the startnode if we can't strip
2676 2677 startctx = repo['.']
2677 2678 hg.updaterepo(repo, startctx.node(), overwrite=True)
2678 2679
2679 2680 ui.status(_("graft aborted\n"))
2680 2681 ui.status(_("working directory is now at %s\n") % startctx.hex()[:12])
2681 2682 graftstate.delete()
2682 2683 return 0
2683 2684
2684 2685 def _readgraftstate(repo, graftstate):
2685 2686 """read the graft state file and return a dict of the data stored in it"""
2686 2687 try:
2687 2688 return graftstate.read()
2688 2689 except error.CorruptedState:
2689 2690 nodes = repo.vfs.read('graftstate').splitlines()
2690 2691 return {'nodes': nodes}
2691 2692
2692 2693 def _stopgraft(ui, repo, graftstate):
2693 2694 """stop the interrupted graft"""
2694 2695 if not graftstate.exists():
2695 2696 raise error.Abort(_("no interrupted graft found"))
2696 2697 pctx = repo['.']
2697 2698 hg.updaterepo(repo, pctx.node(), overwrite=True)
2698 2699 graftstate.delete()
2699 2700 ui.status(_("stopped the interrupted graft\n"))
2700 2701 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2701 2702 return 0
2702 2703
2703 2704 @command('grep',
2704 2705 [('0', 'print0', None, _('end fields with NUL')),
2705 2706 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2706 2707 ('', 'diff', None, _('print all revisions when the term was introduced '
2707 2708 'or removed')),
2708 2709 ('a', 'text', None, _('treat all files as text')),
2709 2710 ('f', 'follow', None,
2710 2711 _('follow changeset history,'
2711 2712 ' or file history across copies and renames')),
2712 2713 ('i', 'ignore-case', None, _('ignore case when matching')),
2713 2714 ('l', 'files-with-matches', None,
2714 2715 _('print only filenames and revisions that match')),
2715 2716 ('n', 'line-number', None, _('print matching line numbers')),
2716 2717 ('r', 'rev', [],
2717 2718 _('only search files changed within revision range'), _('REV')),
2718 2719 ('', 'all-files', None,
2719 2720 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2720 2721 ('u', 'user', None, _('list the author (long with -v)')),
2721 2722 ('d', 'date', None, _('list the date (short with -q)')),
2722 2723 ] + formatteropts + walkopts,
2723 2724 _('[OPTION]... PATTERN [FILE]...'),
2724 2725 helpcategory=command.CATEGORY_FILE_CONTENTS,
2725 2726 inferrepo=True,
2726 2727 intents={INTENT_READONLY})
2727 2728 def grep(ui, repo, pattern, *pats, **opts):
2728 2729 """search revision history for a pattern in specified files
2729 2730
2730 2731 Search revision history for a regular expression in the specified
2731 2732 files or the entire project.
2732 2733
2733 2734 By default, grep prints the most recent revision number for each
2734 2735 file in which it finds a match. To get it to print every revision
2735 2736 that contains a change in match status ("-" for a match that becomes
2736 2737 a non-match, or "+" for a non-match that becomes a match), use the
2737 2738 --diff flag.
2738 2739
2739 2740 PATTERN can be any Python (roughly Perl-compatible) regular
2740 2741 expression.
2741 2742
2742 2743 If no FILEs are specified (and -f/--follow isn't set), all files in
2743 2744 the repository are searched, including those that don't exist in the
2744 2745 current branch or have been deleted in a prior changeset.
2745 2746
2746 2747 .. container:: verbose
2747 2748
2748 2749 Template:
2749 2750
2750 2751 The following keywords are supported in addition to the common template
2751 2752 keywords and functions. See also :hg:`help templates`.
2752 2753
2753 2754 :change: String. Character denoting insertion ``+`` or removal ``-``.
2754 2755 Available if ``--diff`` is specified.
2755 2756 :lineno: Integer. Line number of the match.
2756 2757 :path: String. Repository-absolute path of the file.
2757 2758 :texts: List of text chunks.
2758 2759
2759 2760 And each entry of ``{texts}`` provides the following sub-keywords.
2760 2761
2761 2762 :matched: Boolean. True if the chunk matches the specified pattern.
2762 2763 :text: String. Chunk content.
2763 2764
2764 2765 See :hg:`help templates.operators` for the list expansion syntax.
2765 2766
2766 2767 Returns 0 if a match is found, 1 otherwise.
2767 2768 """
2768 2769 opts = pycompat.byteskwargs(opts)
2769 2770 diff = opts.get('all') or opts.get('diff')
2770 2771 all_files = opts.get('all_files')
2771 2772 if diff and opts.get('all_files'):
2772 2773 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2773 2774 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2774 2775 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2775 2776 # experimental config: commands.grep.all-files
2776 2777 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2777 2778 plaingrep = opts.get('all_files') and not opts.get('rev')
2778 2779 if plaingrep:
2779 2780 opts['rev'] = ['wdir()']
2780 2781
2781 2782 reflags = re.M
2782 2783 if opts.get('ignore_case'):
2783 2784 reflags |= re.I
2784 2785 try:
2785 2786 regexp = util.re.compile(pattern, reflags)
2786 2787 except re.error as inst:
2787 2788 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2788 2789 return 1
2789 2790 sep, eol = ':', '\n'
2790 2791 if opts.get('print0'):
2791 2792 sep = eol = '\0'
2792 2793
2793 2794 getfile = util.lrucachefunc(repo.file)
2794 2795
2795 2796 def matchlines(body):
2796 2797 begin = 0
2797 2798 linenum = 0
2798 2799 while begin < len(body):
2799 2800 match = regexp.search(body, begin)
2800 2801 if not match:
2801 2802 break
2802 2803 mstart, mend = match.span()
2803 2804 linenum += body.count('\n', begin, mstart) + 1
2804 2805 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2805 2806 begin = body.find('\n', mend) + 1 or len(body) + 1
2806 2807 lend = begin - 1
2807 2808 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2808 2809
2809 2810 class linestate(object):
2810 2811 def __init__(self, line, linenum, colstart, colend):
2811 2812 self.line = line
2812 2813 self.linenum = linenum
2813 2814 self.colstart = colstart
2814 2815 self.colend = colend
2815 2816
2816 2817 def __hash__(self):
2817 2818 return hash((self.linenum, self.line))
2818 2819
2819 2820 def __eq__(self, other):
2820 2821 return self.line == other.line
2821 2822
2822 2823 def findpos(self):
2823 2824 """Iterate all (start, end) indices of matches"""
2824 2825 yield self.colstart, self.colend
2825 2826 p = self.colend
2826 2827 while p < len(self.line):
2827 2828 m = regexp.search(self.line, p)
2828 2829 if not m:
2829 2830 break
2830 2831 yield m.span()
2831 2832 p = m.end()
2832 2833
2833 2834 matches = {}
2834 2835 copies = {}
2835 2836 def grepbody(fn, rev, body):
2836 2837 matches[rev].setdefault(fn, [])
2837 2838 m = matches[rev][fn]
2838 2839 for lnum, cstart, cend, line in matchlines(body):
2839 2840 s = linestate(line, lnum, cstart, cend)
2840 2841 m.append(s)
2841 2842
2842 2843 def difflinestates(a, b):
2843 2844 sm = difflib.SequenceMatcher(None, a, b)
2844 2845 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2845 2846 if tag == r'insert':
2846 2847 for i in pycompat.xrange(blo, bhi):
2847 2848 yield ('+', b[i])
2848 2849 elif tag == r'delete':
2849 2850 for i in pycompat.xrange(alo, ahi):
2850 2851 yield ('-', a[i])
2851 2852 elif tag == r'replace':
2852 2853 for i in pycompat.xrange(alo, ahi):
2853 2854 yield ('-', a[i])
2854 2855 for i in pycompat.xrange(blo, bhi):
2855 2856 yield ('+', b[i])
2856 2857
2857 2858 uipathfn = scmutil.getuipathfn(repo)
2858 2859 def display(fm, fn, ctx, pstates, states):
2859 2860 rev = scmutil.intrev(ctx)
2860 2861 if fm.isplain():
2861 2862 formatuser = ui.shortuser
2862 2863 else:
2863 2864 formatuser = pycompat.bytestr
2864 2865 if ui.quiet:
2865 2866 datefmt = '%Y-%m-%d'
2866 2867 else:
2867 2868 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2868 2869 found = False
2869 2870 @util.cachefunc
2870 2871 def binary():
2871 2872 flog = getfile(fn)
2872 2873 try:
2873 2874 return stringutil.binary(flog.read(ctx.filenode(fn)))
2874 2875 except error.WdirUnsupported:
2875 2876 return ctx[fn].isbinary()
2876 2877
2877 2878 fieldnamemap = {'linenumber': 'lineno'}
2878 2879 if diff:
2879 2880 iter = difflinestates(pstates, states)
2880 2881 else:
2881 2882 iter = [('', l) for l in states]
2882 2883 for change, l in iter:
2883 2884 fm.startitem()
2884 2885 fm.context(ctx=ctx)
2885 2886 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
2886 2887 fm.plain(uipathfn(fn), label='grep.filename')
2887 2888
2888 2889 cols = [
2889 2890 ('rev', '%d', rev, not plaingrep, ''),
2890 2891 ('linenumber', '%d', l.linenum, opts.get('line_number'), ''),
2891 2892 ]
2892 2893 if diff:
2893 2894 cols.append(
2894 2895 ('change', '%s', change, True,
2895 2896 'grep.inserted ' if change == '+' else 'grep.deleted ')
2896 2897 )
2897 2898 cols.extend([
2898 2899 ('user', '%s', formatuser(ctx.user()), opts.get('user'), ''),
2899 2900 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2900 2901 opts.get('date'), ''),
2901 2902 ])
2902 2903 for name, fmt, data, cond, extra_label in cols:
2903 2904 if cond:
2904 2905 fm.plain(sep, label='grep.sep')
2905 2906 field = fieldnamemap.get(name, name)
2906 2907 label = extra_label + ('grep.%s' % name)
2907 2908 fm.condwrite(cond, field, fmt, data, label=label)
2908 2909 if not opts.get('files_with_matches'):
2909 2910 fm.plain(sep, label='grep.sep')
2910 2911 if not opts.get('text') and binary():
2911 2912 fm.plain(_(" Binary file matches"))
2912 2913 else:
2913 2914 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2914 2915 fm.plain(eol)
2915 2916 found = True
2916 2917 if opts.get('files_with_matches'):
2917 2918 break
2918 2919 return found
2919 2920
2920 2921 def displaymatches(fm, l):
2921 2922 p = 0
2922 2923 for s, e in l.findpos():
2923 2924 if p < s:
2924 2925 fm.startitem()
2925 2926 fm.write('text', '%s', l.line[p:s])
2926 2927 fm.data(matched=False)
2927 2928 fm.startitem()
2928 2929 fm.write('text', '%s', l.line[s:e], label='grep.match')
2929 2930 fm.data(matched=True)
2930 2931 p = e
2931 2932 if p < len(l.line):
2932 2933 fm.startitem()
2933 2934 fm.write('text', '%s', l.line[p:])
2934 2935 fm.data(matched=False)
2935 2936 fm.end()
2936 2937
2937 2938 skip = set()
2938 2939 revfiles = {}
2939 2940 match = scmutil.match(repo[None], pats, opts)
2940 2941 found = False
2941 2942 follow = opts.get('follow')
2942 2943
2943 2944 getrenamed = scmutil.getrenamedfn(repo)
2944 2945 def prep(ctx, fns):
2945 2946 rev = ctx.rev()
2946 2947 pctx = ctx.p1()
2947 2948 parent = pctx.rev()
2948 2949 matches.setdefault(rev, {})
2949 2950 matches.setdefault(parent, {})
2950 2951 files = revfiles.setdefault(rev, [])
2951 2952 for fn in fns:
2952 2953 flog = getfile(fn)
2953 2954 try:
2954 2955 fnode = ctx.filenode(fn)
2955 2956 except error.LookupError:
2956 2957 continue
2957 2958
2958 2959 copy = None
2959 2960 if follow:
2960 2961 copy = getrenamed(fn, rev)
2961 2962 if copy:
2962 2963 copies.setdefault(rev, {})[fn] = copy
2963 2964 if fn in skip:
2964 2965 skip.add(copy)
2965 2966 if fn in skip:
2966 2967 continue
2967 2968 files.append(fn)
2968 2969
2969 2970 if fn not in matches[rev]:
2970 2971 try:
2971 2972 content = flog.read(fnode)
2972 2973 except error.WdirUnsupported:
2973 2974 content = ctx[fn].data()
2974 2975 grepbody(fn, rev, content)
2975 2976
2976 2977 pfn = copy or fn
2977 2978 if pfn not in matches[parent]:
2978 2979 try:
2979 2980 fnode = pctx.filenode(pfn)
2980 2981 grepbody(pfn, parent, flog.read(fnode))
2981 2982 except error.LookupError:
2982 2983 pass
2983 2984
2984 2985 ui.pager('grep')
2985 2986 fm = ui.formatter('grep', opts)
2986 2987 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2987 2988 rev = ctx.rev()
2988 2989 parent = ctx.p1().rev()
2989 2990 for fn in sorted(revfiles.get(rev, [])):
2990 2991 states = matches[rev][fn]
2991 2992 copy = copies.get(rev, {}).get(fn)
2992 2993 if fn in skip:
2993 2994 if copy:
2994 2995 skip.add(copy)
2995 2996 continue
2996 2997 pstates = matches.get(parent, {}).get(copy or fn, [])
2997 2998 if pstates or states:
2998 2999 r = display(fm, fn, ctx, pstates, states)
2999 3000 found = found or r
3000 3001 if r and not diff and not all_files:
3001 3002 skip.add(fn)
3002 3003 if copy:
3003 3004 skip.add(copy)
3004 3005 del revfiles[rev]
3005 3006 # We will keep the matches dict for the duration of the window
3006 3007 # clear the matches dict once the window is over
3007 3008 if not revfiles:
3008 3009 matches.clear()
3009 3010 fm.end()
3010 3011
3011 3012 return not found
3012 3013
3013 3014 @command('heads',
3014 3015 [('r', 'rev', '',
3015 3016 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3016 3017 ('t', 'topo', False, _('show topological heads only')),
3017 3018 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3018 3019 ('c', 'closed', False, _('show normal and closed branch heads')),
3019 3020 ] + templateopts,
3020 3021 _('[-ct] [-r STARTREV] [REV]...'),
3021 3022 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3022 3023 intents={INTENT_READONLY})
3023 3024 def heads(ui, repo, *branchrevs, **opts):
3024 3025 """show branch heads
3025 3026
3026 3027 With no arguments, show all open branch heads in the repository.
3027 3028 Branch heads are changesets that have no descendants on the
3028 3029 same branch. They are where development generally takes place and
3029 3030 are the usual targets for update and merge operations.
3030 3031
3031 3032 If one or more REVs are given, only open branch heads on the
3032 3033 branches associated with the specified changesets are shown. This
3033 3034 means that you can use :hg:`heads .` to see the heads on the
3034 3035 currently checked-out branch.
3035 3036
3036 3037 If -c/--closed is specified, also show branch heads marked closed
3037 3038 (see :hg:`commit --close-branch`).
3038 3039
3039 3040 If STARTREV is specified, only those heads that are descendants of
3040 3041 STARTREV will be displayed.
3041 3042
3042 3043 If -t/--topo is specified, named branch mechanics will be ignored and only
3043 3044 topological heads (changesets with no children) will be shown.
3044 3045
3045 3046 Returns 0 if matching heads are found, 1 if not.
3046 3047 """
3047 3048
3048 3049 opts = pycompat.byteskwargs(opts)
3049 3050 start = None
3050 3051 rev = opts.get('rev')
3051 3052 if rev:
3052 3053 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3053 3054 start = scmutil.revsingle(repo, rev, None).node()
3054 3055
3055 3056 if opts.get('topo'):
3056 3057 heads = [repo[h] for h in repo.heads(start)]
3057 3058 else:
3058 3059 heads = []
3059 3060 for branch in repo.branchmap():
3060 3061 heads += repo.branchheads(branch, start, opts.get('closed'))
3061 3062 heads = [repo[h] for h in heads]
3062 3063
3063 3064 if branchrevs:
3064 3065 branches = set(repo[r].branch()
3065 3066 for r in scmutil.revrange(repo, branchrevs))
3066 3067 heads = [h for h in heads if h.branch() in branches]
3067 3068
3068 3069 if opts.get('active') and branchrevs:
3069 3070 dagheads = repo.heads(start)
3070 3071 heads = [h for h in heads if h.node() in dagheads]
3071 3072
3072 3073 if branchrevs:
3073 3074 haveheads = set(h.branch() for h in heads)
3074 3075 if branches - haveheads:
3075 3076 headless = ', '.join(b for b in branches - haveheads)
3076 3077 msg = _('no open branch heads found on branches %s')
3077 3078 if opts.get('rev'):
3078 3079 msg += _(' (started at %s)') % opts['rev']
3079 3080 ui.warn((msg + '\n') % headless)
3080 3081
3081 3082 if not heads:
3082 3083 return 1
3083 3084
3084 3085 ui.pager('heads')
3085 3086 heads = sorted(heads, key=lambda x: -x.rev())
3086 3087 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3087 3088 for ctx in heads:
3088 3089 displayer.show(ctx)
3089 3090 displayer.close()
3090 3091
3091 3092 @command('help',
3092 3093 [('e', 'extension', None, _('show only help for extensions')),
3093 3094 ('c', 'command', None, _('show only help for commands')),
3094 3095 ('k', 'keyword', None, _('show topics matching keyword')),
3095 3096 ('s', 'system', [],
3096 3097 _('show help for specific platform(s)'), _('PLATFORM')),
3097 3098 ],
3098 3099 _('[-eck] [-s PLATFORM] [TOPIC]'),
3099 3100 helpcategory=command.CATEGORY_HELP,
3100 3101 norepo=True,
3101 3102 intents={INTENT_READONLY})
3102 3103 def help_(ui, name=None, **opts):
3103 3104 """show help for a given topic or a help overview
3104 3105
3105 3106 With no arguments, print a list of commands with short help messages.
3106 3107
3107 3108 Given a topic, extension, or command name, print help for that
3108 3109 topic.
3109 3110
3110 3111 Returns 0 if successful.
3111 3112 """
3112 3113
3113 3114 keep = opts.get(r'system') or []
3114 3115 if len(keep) == 0:
3115 3116 if pycompat.sysplatform.startswith('win'):
3116 3117 keep.append('windows')
3117 3118 elif pycompat.sysplatform == 'OpenVMS':
3118 3119 keep.append('vms')
3119 3120 elif pycompat.sysplatform == 'plan9':
3120 3121 keep.append('plan9')
3121 3122 else:
3122 3123 keep.append('unix')
3123 3124 keep.append(pycompat.sysplatform.lower())
3124 3125 if ui.verbose:
3125 3126 keep.append('verbose')
3126 3127
3127 3128 commands = sys.modules[__name__]
3128 3129 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3129 3130 ui.pager('help')
3130 3131 ui.write(formatted)
3131 3132
3132 3133
3133 3134 @command('identify|id',
3134 3135 [('r', 'rev', '',
3135 3136 _('identify the specified revision'), _('REV')),
3136 3137 ('n', 'num', None, _('show local revision number')),
3137 3138 ('i', 'id', None, _('show global revision id')),
3138 3139 ('b', 'branch', None, _('show branch')),
3139 3140 ('t', 'tags', None, _('show tags')),
3140 3141 ('B', 'bookmarks', None, _('show bookmarks')),
3141 3142 ] + remoteopts + formatteropts,
3142 3143 _('[-nibtB] [-r REV] [SOURCE]'),
3143 3144 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3144 3145 optionalrepo=True,
3145 3146 intents={INTENT_READONLY})
3146 3147 def identify(ui, repo, source=None, rev=None,
3147 3148 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3148 3149 """identify the working directory or specified revision
3149 3150
3150 3151 Print a summary identifying the repository state at REV using one or
3151 3152 two parent hash identifiers, followed by a "+" if the working
3152 3153 directory has uncommitted changes, the branch name (if not default),
3153 3154 a list of tags, and a list of bookmarks.
3154 3155
3155 3156 When REV is not given, print a summary of the current state of the
3156 3157 repository including the working directory. Specify -r. to get information
3157 3158 of the working directory parent without scanning uncommitted changes.
3158 3159
3159 3160 Specifying a path to a repository root or Mercurial bundle will
3160 3161 cause lookup to operate on that repository/bundle.
3161 3162
3162 3163 .. container:: verbose
3163 3164
3164 3165 Template:
3165 3166
3166 3167 The following keywords are supported in addition to the common template
3167 3168 keywords and functions. See also :hg:`help templates`.
3168 3169
3169 3170 :dirty: String. Character ``+`` denoting if the working directory has
3170 3171 uncommitted changes.
3171 3172 :id: String. One or two nodes, optionally followed by ``+``.
3172 3173 :parents: List of strings. Parent nodes of the changeset.
3173 3174
3174 3175 Examples:
3175 3176
3176 3177 - generate a build identifier for the working directory::
3177 3178
3178 3179 hg id --id > build-id.dat
3179 3180
3180 3181 - find the revision corresponding to a tag::
3181 3182
3182 3183 hg id -n -r 1.3
3183 3184
3184 3185 - check the most recent revision of a remote repository::
3185 3186
3186 3187 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3187 3188
3188 3189 See :hg:`log` for generating more information about specific revisions,
3189 3190 including full hash identifiers.
3190 3191
3191 3192 Returns 0 if successful.
3192 3193 """
3193 3194
3194 3195 opts = pycompat.byteskwargs(opts)
3195 3196 if not repo and not source:
3196 3197 raise error.Abort(_("there is no Mercurial repository here "
3197 3198 "(.hg not found)"))
3198 3199
3199 3200 default = not (num or id or branch or tags or bookmarks)
3200 3201 output = []
3201 3202 revs = []
3202 3203
3203 3204 if source:
3204 3205 source, branches = hg.parseurl(ui.expandpath(source))
3205 3206 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3206 3207 repo = peer.local()
3207 3208 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3208 3209
3209 3210 fm = ui.formatter('identify', opts)
3210 3211 fm.startitem()
3211 3212
3212 3213 if not repo:
3213 3214 if num or branch or tags:
3214 3215 raise error.Abort(
3215 3216 _("can't query remote revision number, branch, or tags"))
3216 3217 if not rev and revs:
3217 3218 rev = revs[0]
3218 3219 if not rev:
3219 3220 rev = "tip"
3220 3221
3221 3222 remoterev = peer.lookup(rev)
3222 3223 hexrev = fm.hexfunc(remoterev)
3223 3224 if default or id:
3224 3225 output = [hexrev]
3225 3226 fm.data(id=hexrev)
3226 3227
3227 3228 @util.cachefunc
3228 3229 def getbms():
3229 3230 bms = []
3230 3231
3231 3232 if 'bookmarks' in peer.listkeys('namespaces'):
3232 3233 hexremoterev = hex(remoterev)
3233 3234 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3234 3235 if bmr == hexremoterev]
3235 3236
3236 3237 return sorted(bms)
3237 3238
3238 3239 if fm.isplain():
3239 3240 if bookmarks:
3240 3241 output.extend(getbms())
3241 3242 elif default and not ui.quiet:
3242 3243 # multiple bookmarks for a single parent separated by '/'
3243 3244 bm = '/'.join(getbms())
3244 3245 if bm:
3245 3246 output.append(bm)
3246 3247 else:
3247 3248 fm.data(node=hex(remoterev))
3248 3249 if bookmarks or 'bookmarks' in fm.datahint():
3249 3250 fm.data(bookmarks=fm.formatlist(getbms(), name='bookmark'))
3250 3251 else:
3251 3252 if rev:
3252 3253 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3253 3254 ctx = scmutil.revsingle(repo, rev, None)
3254 3255
3255 3256 if ctx.rev() is None:
3256 3257 ctx = repo[None]
3257 3258 parents = ctx.parents()
3258 3259 taglist = []
3259 3260 for p in parents:
3260 3261 taglist.extend(p.tags())
3261 3262
3262 3263 dirty = ""
3263 3264 if ctx.dirty(missing=True, merge=False, branch=False):
3264 3265 dirty = '+'
3265 3266 fm.data(dirty=dirty)
3266 3267
3267 3268 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3268 3269 if default or id:
3269 3270 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3270 3271 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3271 3272
3272 3273 if num:
3273 3274 numoutput = ["%d" % p.rev() for p in parents]
3274 3275 output.append("%s%s" % ('+'.join(numoutput), dirty))
3275 3276
3276 3277 fm.data(parents=fm.formatlist([fm.hexfunc(p.node())
3277 3278 for p in parents], name='node'))
3278 3279 else:
3279 3280 hexoutput = fm.hexfunc(ctx.node())
3280 3281 if default or id:
3281 3282 output = [hexoutput]
3282 3283 fm.data(id=hexoutput)
3283 3284
3284 3285 if num:
3285 3286 output.append(pycompat.bytestr(ctx.rev()))
3286 3287 taglist = ctx.tags()
3287 3288
3288 3289 if default and not ui.quiet:
3289 3290 b = ctx.branch()
3290 3291 if b != 'default':
3291 3292 output.append("(%s)" % b)
3292 3293
3293 3294 # multiple tags for a single parent separated by '/'
3294 3295 t = '/'.join(taglist)
3295 3296 if t:
3296 3297 output.append(t)
3297 3298
3298 3299 # multiple bookmarks for a single parent separated by '/'
3299 3300 bm = '/'.join(ctx.bookmarks())
3300 3301 if bm:
3301 3302 output.append(bm)
3302 3303 else:
3303 3304 if branch:
3304 3305 output.append(ctx.branch())
3305 3306
3306 3307 if tags:
3307 3308 output.extend(taglist)
3308 3309
3309 3310 if bookmarks:
3310 3311 output.extend(ctx.bookmarks())
3311 3312
3312 3313 fm.data(node=ctx.hex())
3313 3314 fm.data(branch=ctx.branch())
3314 3315 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3315 3316 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3316 3317 fm.context(ctx=ctx)
3317 3318
3318 3319 fm.plain("%s\n" % ' '.join(output))
3319 3320 fm.end()
3320 3321
3321 3322 @command('import|patch',
3322 3323 [('p', 'strip', 1,
3323 3324 _('directory strip option for patch. This has the same '
3324 3325 'meaning as the corresponding patch option'), _('NUM')),
3325 3326 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3326 3327 ('e', 'edit', False, _('invoke editor on commit messages')),
3327 3328 ('f', 'force', None,
3328 3329 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3329 3330 ('', 'no-commit', None,
3330 3331 _("don't commit, just update the working directory")),
3331 3332 ('', 'bypass', None,
3332 3333 _("apply patch without touching the working directory")),
3333 3334 ('', 'partial', None,
3334 3335 _('commit even if some hunks fail')),
3335 3336 ('', 'exact', None,
3336 3337 _('abort if patch would apply lossily')),
3337 3338 ('', 'prefix', '',
3338 3339 _('apply patch to subdirectory'), _('DIR')),
3339 3340 ('', 'import-branch', None,
3340 3341 _('use any branch information in patch (implied by --exact)'))] +
3341 3342 commitopts + commitopts2 + similarityopts,
3342 3343 _('[OPTION]... PATCH...'),
3343 3344 helpcategory=command.CATEGORY_IMPORT_EXPORT)
3344 3345 def import_(ui, repo, patch1=None, *patches, **opts):
3345 3346 """import an ordered set of patches
3346 3347
3347 3348 Import a list of patches and commit them individually (unless
3348 3349 --no-commit is specified).
3349 3350
3350 3351 To read a patch from standard input (stdin), use "-" as the patch
3351 3352 name. If a URL is specified, the patch will be downloaded from
3352 3353 there.
3353 3354
3354 3355 Import first applies changes to the working directory (unless
3355 3356 --bypass is specified), import will abort if there are outstanding
3356 3357 changes.
3357 3358
3358 3359 Use --bypass to apply and commit patches directly to the
3359 3360 repository, without affecting the working directory. Without
3360 3361 --exact, patches will be applied on top of the working directory
3361 3362 parent revision.
3362 3363
3363 3364 You can import a patch straight from a mail message. Even patches
3364 3365 as attachments work (to use the body part, it must have type
3365 3366 text/plain or text/x-patch). From and Subject headers of email
3366 3367 message are used as default committer and commit message. All
3367 3368 text/plain body parts before first diff are added to the commit
3368 3369 message.
3369 3370
3370 3371 If the imported patch was generated by :hg:`export`, user and
3371 3372 description from patch override values from message headers and
3372 3373 body. Values given on command line with -m/--message and -u/--user
3373 3374 override these.
3374 3375
3375 3376 If --exact is specified, import will set the working directory to
3376 3377 the parent of each patch before applying it, and will abort if the
3377 3378 resulting changeset has a different ID than the one recorded in
3378 3379 the patch. This will guard against various ways that portable
3379 3380 patch formats and mail systems might fail to transfer Mercurial
3380 3381 data or metadata. See :hg:`bundle` for lossless transmission.
3381 3382
3382 3383 Use --partial to ensure a changeset will be created from the patch
3383 3384 even if some hunks fail to apply. Hunks that fail to apply will be
3384 3385 written to a <target-file>.rej file. Conflicts can then be resolved
3385 3386 by hand before :hg:`commit --amend` is run to update the created
3386 3387 changeset. This flag exists to let people import patches that
3387 3388 partially apply without losing the associated metadata (author,
3388 3389 date, description, ...).
3389 3390
3390 3391 .. note::
3391 3392
3392 3393 When no hunks apply cleanly, :hg:`import --partial` will create
3393 3394 an empty changeset, importing only the patch metadata.
3394 3395
3395 3396 With -s/--similarity, hg will attempt to discover renames and
3396 3397 copies in the patch in the same way as :hg:`addremove`.
3397 3398
3398 3399 It is possible to use external patch programs to perform the patch
3399 3400 by setting the ``ui.patch`` configuration option. For the default
3400 3401 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3401 3402 See :hg:`help config` for more information about configuration
3402 3403 files and how to use these options.
3403 3404
3404 3405 See :hg:`help dates` for a list of formats valid for -d/--date.
3405 3406
3406 3407 .. container:: verbose
3407 3408
3408 3409 Examples:
3409 3410
3410 3411 - import a traditional patch from a website and detect renames::
3411 3412
3412 3413 hg import -s 80 http://example.com/bugfix.patch
3413 3414
3414 3415 - import a changeset from an hgweb server::
3415 3416
3416 3417 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3417 3418
3418 3419 - import all the patches in an Unix-style mbox::
3419 3420
3420 3421 hg import incoming-patches.mbox
3421 3422
3422 3423 - import patches from stdin::
3423 3424
3424 3425 hg import -
3425 3426
3426 3427 - attempt to exactly restore an exported changeset (not always
3427 3428 possible)::
3428 3429
3429 3430 hg import --exact proposed-fix.patch
3430 3431
3431 3432 - use an external tool to apply a patch which is too fuzzy for
3432 3433 the default internal tool.
3433 3434
3434 3435 hg import --config ui.patch="patch --merge" fuzzy.patch
3435 3436
3436 3437 - change the default fuzzing from 2 to a less strict 7
3437 3438
3438 3439 hg import --config ui.fuzz=7 fuzz.patch
3439 3440
3440 3441 Returns 0 on success, 1 on partial success (see --partial).
3441 3442 """
3442 3443
3443 3444 opts = pycompat.byteskwargs(opts)
3444 3445 if not patch1:
3445 3446 raise error.Abort(_('need at least one patch to import'))
3446 3447
3447 3448 patches = (patch1,) + patches
3448 3449
3449 3450 date = opts.get('date')
3450 3451 if date:
3451 3452 opts['date'] = dateutil.parsedate(date)
3452 3453
3453 3454 exact = opts.get('exact')
3454 3455 update = not opts.get('bypass')
3455 3456 if not update and opts.get('no_commit'):
3456 3457 raise error.Abort(_('cannot use --no-commit with --bypass'))
3457 3458 try:
3458 3459 sim = float(opts.get('similarity') or 0)
3459 3460 except ValueError:
3460 3461 raise error.Abort(_('similarity must be a number'))
3461 3462 if sim < 0 or sim > 100:
3462 3463 raise error.Abort(_('similarity must be between 0 and 100'))
3463 3464 if sim and not update:
3464 3465 raise error.Abort(_('cannot use --similarity with --bypass'))
3465 3466 if exact:
3466 3467 if opts.get('edit'):
3467 3468 raise error.Abort(_('cannot use --exact with --edit'))
3468 3469 if opts.get('prefix'):
3469 3470 raise error.Abort(_('cannot use --exact with --prefix'))
3470 3471
3471 3472 base = opts["base"]
3472 3473 msgs = []
3473 3474 ret = 0
3474 3475
3475 3476 with repo.wlock():
3476 3477 if update:
3477 3478 cmdutil.checkunfinished(repo)
3478 3479 if (exact or not opts.get('force')):
3479 3480 cmdutil.bailifchanged(repo)
3480 3481
3481 3482 if not opts.get('no_commit'):
3482 3483 lock = repo.lock
3483 3484 tr = lambda: repo.transaction('import')
3484 3485 dsguard = util.nullcontextmanager
3485 3486 else:
3486 3487 lock = util.nullcontextmanager
3487 3488 tr = util.nullcontextmanager
3488 3489 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3489 3490 with lock(), tr(), dsguard():
3490 3491 parents = repo[None].parents()
3491 3492 for patchurl in patches:
3492 3493 if patchurl == '-':
3493 3494 ui.status(_('applying patch from stdin\n'))
3494 3495 patchfile = ui.fin
3495 3496 patchurl = 'stdin' # for error message
3496 3497 else:
3497 3498 patchurl = os.path.join(base, patchurl)
3498 3499 ui.status(_('applying %s\n') % patchurl)
3499 3500 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
3500 3501
3501 3502 haspatch = False
3502 3503 for hunk in patch.split(patchfile):
3503 3504 with patch.extract(ui, hunk) as patchdata:
3504 3505 msg, node, rej = cmdutil.tryimportone(ui, repo,
3505 3506 patchdata,
3506 3507 parents, opts,
3507 3508 msgs, hg.clean)
3508 3509 if msg:
3509 3510 haspatch = True
3510 3511 ui.note(msg + '\n')
3511 3512 if update or exact:
3512 3513 parents = repo[None].parents()
3513 3514 else:
3514 3515 parents = [repo[node]]
3515 3516 if rej:
3516 3517 ui.write_err(_("patch applied partially\n"))
3517 3518 ui.write_err(_("(fix the .rej files and run "
3518 3519 "`hg commit --amend`)\n"))
3519 3520 ret = 1
3520 3521 break
3521 3522
3522 3523 if not haspatch:
3523 3524 raise error.Abort(_('%s: no diffs found') % patchurl)
3524 3525
3525 3526 if msgs:
3526 3527 repo.savecommitmessage('\n* * *\n'.join(msgs))
3527 3528 return ret
3528 3529
3529 3530 @command('incoming|in',
3530 3531 [('f', 'force', None,
3531 3532 _('run even if remote repository is unrelated')),
3532 3533 ('n', 'newest-first', None, _('show newest record first')),
3533 3534 ('', 'bundle', '',
3534 3535 _('file to store the bundles into'), _('FILE')),
3535 3536 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3536 3537 ('B', 'bookmarks', False, _("compare bookmarks")),
3537 3538 ('b', 'branch', [],
3538 3539 _('a specific branch you would like to pull'), _('BRANCH')),
3539 3540 ] + logopts + remoteopts + subrepoopts,
3540 3541 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
3541 3542 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
3542 3543 def incoming(ui, repo, source="default", **opts):
3543 3544 """show new changesets found in source
3544 3545
3545 3546 Show new changesets found in the specified path/URL or the default
3546 3547 pull location. These are the changesets that would have been pulled
3547 3548 by :hg:`pull` at the time you issued this command.
3548 3549
3549 3550 See pull for valid source format details.
3550 3551
3551 3552 .. container:: verbose
3552 3553
3553 3554 With -B/--bookmarks, the result of bookmark comparison between
3554 3555 local and remote repositories is displayed. With -v/--verbose,
3555 3556 status is also displayed for each bookmark like below::
3556 3557
3557 3558 BM1 01234567890a added
3558 3559 BM2 1234567890ab advanced
3559 3560 BM3 234567890abc diverged
3560 3561 BM4 34567890abcd changed
3561 3562
3562 3563 The action taken locally when pulling depends on the
3563 3564 status of each bookmark:
3564 3565
3565 3566 :``added``: pull will create it
3566 3567 :``advanced``: pull will update it
3567 3568 :``diverged``: pull will create a divergent bookmark
3568 3569 :``changed``: result depends on remote changesets
3569 3570
3570 3571 From the point of view of pulling behavior, bookmark
3571 3572 existing only in the remote repository are treated as ``added``,
3572 3573 even if it is in fact locally deleted.
3573 3574
3574 3575 .. container:: verbose
3575 3576
3576 3577 For remote repository, using --bundle avoids downloading the
3577 3578 changesets twice if the incoming is followed by a pull.
3578 3579
3579 3580 Examples:
3580 3581
3581 3582 - show incoming changes with patches and full description::
3582 3583
3583 3584 hg incoming -vp
3584 3585
3585 3586 - show incoming changes excluding merges, store a bundle::
3586 3587
3587 3588 hg in -vpM --bundle incoming.hg
3588 3589 hg pull incoming.hg
3589 3590
3590 3591 - briefly list changes inside a bundle::
3591 3592
3592 3593 hg in changes.hg -T "{desc|firstline}\\n"
3593 3594
3594 3595 Returns 0 if there are incoming changes, 1 otherwise.
3595 3596 """
3596 3597 opts = pycompat.byteskwargs(opts)
3597 3598 if opts.get('graph'):
3598 3599 logcmdutil.checkunsupportedgraphflags([], opts)
3599 3600 def display(other, chlist, displayer):
3600 3601 revdag = logcmdutil.graphrevs(other, chlist, opts)
3601 3602 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3602 3603 graphmod.asciiedges)
3603 3604
3604 3605 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3605 3606 return 0
3606 3607
3607 3608 if opts.get('bundle') and opts.get('subrepos'):
3608 3609 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3609 3610
3610 3611 if opts.get('bookmarks'):
3611 3612 source, branches = hg.parseurl(ui.expandpath(source),
3612 3613 opts.get('branch'))
3613 3614 other = hg.peer(repo, opts, source)
3614 3615 if 'bookmarks' not in other.listkeys('namespaces'):
3615 3616 ui.warn(_("remote doesn't support bookmarks\n"))
3616 3617 return 0
3617 3618 ui.pager('incoming')
3618 3619 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3619 3620 return bookmarks.incoming(ui, repo, other)
3620 3621
3621 3622 repo._subtoppath = ui.expandpath(source)
3622 3623 try:
3623 3624 return hg.incoming(ui, repo, source, opts)
3624 3625 finally:
3625 3626 del repo._subtoppath
3626 3627
3627 3628
3628 3629 @command('init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3629 3630 helpcategory=command.CATEGORY_REPO_CREATION,
3630 3631 helpbasic=True, norepo=True)
3631 3632 def init(ui, dest=".", **opts):
3632 3633 """create a new repository in the given directory
3633 3634
3634 3635 Initialize a new repository in the given directory. If the given
3635 3636 directory does not exist, it will be created.
3636 3637
3637 3638 If no directory is given, the current directory is used.
3638 3639
3639 3640 It is possible to specify an ``ssh://`` URL as the destination.
3640 3641 See :hg:`help urls` for more information.
3641 3642
3642 3643 Returns 0 on success.
3643 3644 """
3644 3645 opts = pycompat.byteskwargs(opts)
3645 3646 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3646 3647
3647 3648 @command('locate',
3648 3649 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3649 3650 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3650 3651 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3651 3652 ] + walkopts,
3652 3653 _('[OPTION]... [PATTERN]...'),
3653 3654 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
3654 3655 def locate(ui, repo, *pats, **opts):
3655 3656 """locate files matching specific patterns (DEPRECATED)
3656 3657
3657 3658 Print files under Mercurial control in the working directory whose
3658 3659 names match the given patterns.
3659 3660
3660 3661 By default, this command searches all directories in the working
3661 3662 directory. To search just the current directory and its
3662 3663 subdirectories, use "--include .".
3663 3664
3664 3665 If no patterns are given to match, this command prints the names
3665 3666 of all files under Mercurial control in the working directory.
3666 3667
3667 3668 If you want to feed the output of this command into the "xargs"
3668 3669 command, use the -0 option to both this command and "xargs". This
3669 3670 will avoid the problem of "xargs" treating single filenames that
3670 3671 contain whitespace as multiple filenames.
3671 3672
3672 3673 See :hg:`help files` for a more versatile command.
3673 3674
3674 3675 Returns 0 if a match is found, 1 otherwise.
3675 3676 """
3676 3677 opts = pycompat.byteskwargs(opts)
3677 3678 if opts.get('print0'):
3678 3679 end = '\0'
3679 3680 else:
3680 3681 end = '\n'
3681 3682 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3682 3683
3683 3684 ret = 1
3684 3685 m = scmutil.match(ctx, pats, opts, default='relglob',
3685 3686 badfn=lambda x, y: False)
3686 3687
3687 3688 ui.pager('locate')
3688 3689 if ctx.rev() is None:
3689 3690 # When run on the working copy, "locate" includes removed files, so
3690 3691 # we get the list of files from the dirstate.
3691 3692 filesgen = sorted(repo.dirstate.matches(m))
3692 3693 else:
3693 3694 filesgen = ctx.matches(m)
3694 3695 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
3695 3696 for abs in filesgen:
3696 3697 if opts.get('fullpath'):
3697 3698 ui.write(repo.wjoin(abs), end)
3698 3699 else:
3699 3700 ui.write(uipathfn(abs), end)
3700 3701 ret = 0
3701 3702
3702 3703 return ret
3703 3704
3704 3705 @command('log|history',
3705 3706 [('f', 'follow', None,
3706 3707 _('follow changeset history, or file history across copies and renames')),
3707 3708 ('', 'follow-first', None,
3708 3709 _('only follow the first parent of merge changesets (DEPRECATED)')),
3709 3710 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3710 3711 ('C', 'copies', None, _('show copied files')),
3711 3712 ('k', 'keyword', [],
3712 3713 _('do case-insensitive search for a given text'), _('TEXT')),
3713 3714 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3714 3715 ('L', 'line-range', [],
3715 3716 _('follow line range of specified file (EXPERIMENTAL)'),
3716 3717 _('FILE,RANGE')),
3717 3718 ('', 'removed', None, _('include revisions where files were removed')),
3718 3719 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3719 3720 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3720 3721 ('', 'only-branch', [],
3721 3722 _('show only changesets within the given named branch (DEPRECATED)'),
3722 3723 _('BRANCH')),
3723 3724 ('b', 'branch', [],
3724 3725 _('show changesets within the given named branch'), _('BRANCH')),
3725 3726 ('P', 'prune', [],
3726 3727 _('do not display revision or any of its ancestors'), _('REV')),
3727 3728 ] + logopts + walkopts,
3728 3729 _('[OPTION]... [FILE]'),
3729 3730 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3730 3731 helpbasic=True, inferrepo=True,
3731 3732 intents={INTENT_READONLY})
3732 3733 def log(ui, repo, *pats, **opts):
3733 3734 """show revision history of entire repository or files
3734 3735
3735 3736 Print the revision history of the specified files or the entire
3736 3737 project.
3737 3738
3738 3739 If no revision range is specified, the default is ``tip:0`` unless
3739 3740 --follow is set, in which case the working directory parent is
3740 3741 used as the starting revision.
3741 3742
3742 3743 File history is shown without following rename or copy history of
3743 3744 files. Use -f/--follow with a filename to follow history across
3744 3745 renames and copies. --follow without a filename will only show
3745 3746 ancestors of the starting revision.
3746 3747
3747 3748 By default this command prints revision number and changeset id,
3748 3749 tags, non-trivial parents, user, date and time, and a summary for
3749 3750 each commit. When the -v/--verbose switch is used, the list of
3750 3751 changed files and full commit message are shown.
3751 3752
3752 3753 With --graph the revisions are shown as an ASCII art DAG with the most
3753 3754 recent changeset at the top.
3754 3755 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3755 3756 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3756 3757 changeset from the lines below is a parent of the 'o' merge on the same
3757 3758 line.
3758 3759 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3759 3760 of a '|' indicates one or more revisions in a path are omitted.
3760 3761
3761 3762 .. container:: verbose
3762 3763
3763 3764 Use -L/--line-range FILE,M:N options to follow the history of lines
3764 3765 from M to N in FILE. With -p/--patch only diff hunks affecting
3765 3766 specified line range will be shown. This option requires --follow;
3766 3767 it can be specified multiple times. Currently, this option is not
3767 3768 compatible with --graph. This option is experimental.
3768 3769
3769 3770 .. note::
3770 3771
3771 3772 :hg:`log --patch` may generate unexpected diff output for merge
3772 3773 changesets, as it will only compare the merge changeset against
3773 3774 its first parent. Also, only files different from BOTH parents
3774 3775 will appear in files:.
3775 3776
3776 3777 .. note::
3777 3778
3778 3779 For performance reasons, :hg:`log FILE` may omit duplicate changes
3779 3780 made on branches and will not show removals or mode changes. To
3780 3781 see all such changes, use the --removed switch.
3781 3782
3782 3783 .. container:: verbose
3783 3784
3784 3785 .. note::
3785 3786
3786 3787 The history resulting from -L/--line-range options depends on diff
3787 3788 options; for instance if white-spaces are ignored, respective changes
3788 3789 with only white-spaces in specified line range will not be listed.
3789 3790
3790 3791 .. container:: verbose
3791 3792
3792 3793 Some examples:
3793 3794
3794 3795 - changesets with full descriptions and file lists::
3795 3796
3796 3797 hg log -v
3797 3798
3798 3799 - changesets ancestral to the working directory::
3799 3800
3800 3801 hg log -f
3801 3802
3802 3803 - last 10 commits on the current branch::
3803 3804
3804 3805 hg log -l 10 -b .
3805 3806
3806 3807 - changesets showing all modifications of a file, including removals::
3807 3808
3808 3809 hg log --removed file.c
3809 3810
3810 3811 - all changesets that touch a directory, with diffs, excluding merges::
3811 3812
3812 3813 hg log -Mp lib/
3813 3814
3814 3815 - all revision numbers that match a keyword::
3815 3816
3816 3817 hg log -k bug --template "{rev}\\n"
3817 3818
3818 3819 - the full hash identifier of the working directory parent::
3819 3820
3820 3821 hg log -r . --template "{node}\\n"
3821 3822
3822 3823 - list available log templates::
3823 3824
3824 3825 hg log -T list
3825 3826
3826 3827 - check if a given changeset is included in a tagged release::
3827 3828
3828 3829 hg log -r "a21ccf and ancestor(1.9)"
3829 3830
3830 3831 - find all changesets by some user in a date range::
3831 3832
3832 3833 hg log -k alice -d "may 2008 to jul 2008"
3833 3834
3834 3835 - summary of all changesets after the last tag::
3835 3836
3836 3837 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3837 3838
3838 3839 - changesets touching lines 13 to 23 for file.c::
3839 3840
3840 3841 hg log -L file.c,13:23
3841 3842
3842 3843 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3843 3844 main.c with patch::
3844 3845
3845 3846 hg log -L file.c,13:23 -L main.c,2:6 -p
3846 3847
3847 3848 See :hg:`help dates` for a list of formats valid for -d/--date.
3848 3849
3849 3850 See :hg:`help revisions` for more about specifying and ordering
3850 3851 revisions.
3851 3852
3852 3853 See :hg:`help templates` for more about pre-packaged styles and
3853 3854 specifying custom templates. The default template used by the log
3854 3855 command can be customized via the ``ui.logtemplate`` configuration
3855 3856 setting.
3856 3857
3857 3858 Returns 0 on success.
3858 3859
3859 3860 """
3860 3861 opts = pycompat.byteskwargs(opts)
3861 3862 linerange = opts.get('line_range')
3862 3863
3863 3864 if linerange and not opts.get('follow'):
3864 3865 raise error.Abort(_('--line-range requires --follow'))
3865 3866
3866 3867 if linerange and pats:
3867 3868 # TODO: take pats as patterns with no line-range filter
3868 3869 raise error.Abort(
3869 3870 _('FILE arguments are not compatible with --line-range option')
3870 3871 )
3871 3872
3872 3873 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3873 3874 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3874 3875 if linerange:
3875 3876 # TODO: should follow file history from logcmdutil._initialrevs(),
3876 3877 # then filter the result by logcmdutil._makerevset() and --limit
3877 3878 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3878 3879
3879 3880 getrenamed = None
3880 3881 if opts.get('copies'):
3881 3882 endrev = None
3882 3883 if revs:
3883 3884 endrev = revs.max() + 1
3884 3885 getrenamed = scmutil.getrenamedfn(repo, endrev=endrev)
3885 3886
3886 3887 ui.pager('log')
3887 3888 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3888 3889 buffered=True)
3889 3890 if opts.get('graph'):
3890 3891 displayfn = logcmdutil.displaygraphrevs
3891 3892 else:
3892 3893 displayfn = logcmdutil.displayrevs
3893 3894 displayfn(ui, repo, revs, displayer, getrenamed)
3894 3895
3895 3896 @command('manifest',
3896 3897 [('r', 'rev', '', _('revision to display'), _('REV')),
3897 3898 ('', 'all', False, _("list files from all revisions"))]
3898 3899 + formatteropts,
3899 3900 _('[-r REV]'),
3900 3901 helpcategory=command.CATEGORY_MAINTENANCE,
3901 3902 intents={INTENT_READONLY})
3902 3903 def manifest(ui, repo, node=None, rev=None, **opts):
3903 3904 """output the current or given revision of the project manifest
3904 3905
3905 3906 Print a list of version controlled files for the given revision.
3906 3907 If no revision is given, the first parent of the working directory
3907 3908 is used, or the null revision if no revision is checked out.
3908 3909
3909 3910 With -v, print file permissions, symlink and executable bits.
3910 3911 With --debug, print file revision hashes.
3911 3912
3912 3913 If option --all is specified, the list of all files from all revisions
3913 3914 is printed. This includes deleted and renamed files.
3914 3915
3915 3916 Returns 0 on success.
3916 3917 """
3917 3918 opts = pycompat.byteskwargs(opts)
3918 3919 fm = ui.formatter('manifest', opts)
3919 3920
3920 3921 if opts.get('all'):
3921 3922 if rev or node:
3922 3923 raise error.Abort(_("can't specify a revision with --all"))
3923 3924
3924 3925 res = set()
3925 3926 for rev in repo:
3926 3927 ctx = repo[rev]
3927 3928 res |= set(ctx.files())
3928 3929
3929 3930 ui.pager('manifest')
3930 3931 for f in sorted(res):
3931 3932 fm.startitem()
3932 3933 fm.write("path", '%s\n', f)
3933 3934 fm.end()
3934 3935 return
3935 3936
3936 3937 if rev and node:
3937 3938 raise error.Abort(_("please specify just one revision"))
3938 3939
3939 3940 if not node:
3940 3941 node = rev
3941 3942
3942 3943 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3943 3944 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3944 3945 if node:
3945 3946 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3946 3947 ctx = scmutil.revsingle(repo, node)
3947 3948 mf = ctx.manifest()
3948 3949 ui.pager('manifest')
3949 3950 for f in ctx:
3950 3951 fm.startitem()
3951 3952 fm.context(ctx=ctx)
3952 3953 fl = ctx[f].flags()
3953 3954 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3954 3955 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3955 3956 fm.write('path', '%s\n', f)
3956 3957 fm.end()
3957 3958
3958 3959 @command('merge',
3959 3960 [('f', 'force', None,
3960 3961 _('force a merge including outstanding changes (DEPRECATED)')),
3961 3962 ('r', 'rev', '', _('revision to merge'), _('REV')),
3962 3963 ('P', 'preview', None,
3963 3964 _('review revisions to merge (no merge is performed)')),
3964 3965 ('', 'abort', None, _('abort the ongoing merge')),
3965 3966 ] + mergetoolopts,
3966 3967 _('[-P] [[-r] REV]'),
3967 3968 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True)
3968 3969 def merge(ui, repo, node=None, **opts):
3969 3970 """merge another revision into working directory
3970 3971
3971 3972 The current working directory is updated with all changes made in
3972 3973 the requested revision since the last common predecessor revision.
3973 3974
3974 3975 Files that changed between either parent are marked as changed for
3975 3976 the next commit and a commit must be performed before any further
3976 3977 updates to the repository are allowed. The next commit will have
3977 3978 two parents.
3978 3979
3979 3980 ``--tool`` can be used to specify the merge tool used for file
3980 3981 merges. It overrides the HGMERGE environment variable and your
3981 3982 configuration files. See :hg:`help merge-tools` for options.
3982 3983
3983 3984 If no revision is specified, the working directory's parent is a
3984 3985 head revision, and the current branch contains exactly one other
3985 3986 head, the other head is merged with by default. Otherwise, an
3986 3987 explicit revision with which to merge with must be provided.
3987 3988
3988 3989 See :hg:`help resolve` for information on handling file conflicts.
3989 3990
3990 3991 To undo an uncommitted merge, use :hg:`merge --abort` which
3991 3992 will check out a clean copy of the original merge parent, losing
3992 3993 all changes.
3993 3994
3994 3995 Returns 0 on success, 1 if there are unresolved files.
3995 3996 """
3996 3997
3997 3998 opts = pycompat.byteskwargs(opts)
3998 3999 abort = opts.get('abort')
3999 4000 if abort and repo.dirstate.p2() == nullid:
4000 4001 cmdutil.wrongtooltocontinue(repo, _('merge'))
4001 4002 if abort:
4002 4003 if node:
4003 4004 raise error.Abort(_("cannot specify a node with --abort"))
4004 4005 if opts.get('rev'):
4005 4006 raise error.Abort(_("cannot specify both --rev and --abort"))
4006 4007 if opts.get('preview'):
4007 4008 raise error.Abort(_("cannot specify --preview with --abort"))
4008 4009 if opts.get('rev') and node:
4009 4010 raise error.Abort(_("please specify just one revision"))
4010 4011 if not node:
4011 4012 node = opts.get('rev')
4012 4013
4013 4014 if node:
4014 4015 node = scmutil.revsingle(repo, node).node()
4015 4016
4016 4017 if not node and not abort:
4017 4018 node = repo[destutil.destmerge(repo)].node()
4018 4019
4019 4020 if opts.get('preview'):
4020 4021 # find nodes that are ancestors of p2 but not of p1
4021 4022 p1 = repo.lookup('.')
4022 4023 p2 = node
4023 4024 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4024 4025
4025 4026 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4026 4027 for node in nodes:
4027 4028 displayer.show(repo[node])
4028 4029 displayer.close()
4029 4030 return 0
4030 4031
4031 4032 # ui.forcemerge is an internal variable, do not document
4032 4033 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4033 4034 with ui.configoverride(overrides, 'merge'):
4034 4035 force = opts.get('force')
4035 4036 labels = ['working copy', 'merge rev']
4036 4037 return hg.merge(repo, node, force=force, mergeforce=force,
4037 4038 labels=labels, abort=abort)
4038 4039
4039 4040 @command('outgoing|out',
4040 4041 [('f', 'force', None, _('run even when the destination is unrelated')),
4041 4042 ('r', 'rev', [],
4042 4043 _('a changeset intended to be included in the destination'), _('REV')),
4043 4044 ('n', 'newest-first', None, _('show newest record first')),
4044 4045 ('B', 'bookmarks', False, _('compare bookmarks')),
4045 4046 ('b', 'branch', [], _('a specific branch you would like to push'),
4046 4047 _('BRANCH')),
4047 4048 ] + logopts + remoteopts + subrepoopts,
4048 4049 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4049 4050 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
4050 4051 def outgoing(ui, repo, dest=None, **opts):
4051 4052 """show changesets not found in the destination
4052 4053
4053 4054 Show changesets not found in the specified destination repository
4054 4055 or the default push location. These are the changesets that would
4055 4056 be pushed if a push was requested.
4056 4057
4057 4058 See pull for details of valid destination formats.
4058 4059
4059 4060 .. container:: verbose
4060 4061
4061 4062 With -B/--bookmarks, the result of bookmark comparison between
4062 4063 local and remote repositories is displayed. With -v/--verbose,
4063 4064 status is also displayed for each bookmark like below::
4064 4065
4065 4066 BM1 01234567890a added
4066 4067 BM2 deleted
4067 4068 BM3 234567890abc advanced
4068 4069 BM4 34567890abcd diverged
4069 4070 BM5 4567890abcde changed
4070 4071
4071 4072 The action taken when pushing depends on the
4072 4073 status of each bookmark:
4073 4074
4074 4075 :``added``: push with ``-B`` will create it
4075 4076 :``deleted``: push with ``-B`` will delete it
4076 4077 :``advanced``: push will update it
4077 4078 :``diverged``: push with ``-B`` will update it
4078 4079 :``changed``: push with ``-B`` will update it
4079 4080
4080 4081 From the point of view of pushing behavior, bookmarks
4081 4082 existing only in the remote repository are treated as
4082 4083 ``deleted``, even if it is in fact added remotely.
4083 4084
4084 4085 Returns 0 if there are outgoing changes, 1 otherwise.
4085 4086 """
4086 4087 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4087 4088 # style URLs, so don't overwrite dest.
4088 4089 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4089 4090 if not path:
4090 4091 raise error.Abort(_('default repository not configured!'),
4091 4092 hint=_("see 'hg help config.paths'"))
4092 4093
4093 4094 opts = pycompat.byteskwargs(opts)
4094 4095 if opts.get('graph'):
4095 4096 logcmdutil.checkunsupportedgraphflags([], opts)
4096 4097 o, other = hg._outgoing(ui, repo, dest, opts)
4097 4098 if not o:
4098 4099 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4099 4100 return
4100 4101
4101 4102 revdag = logcmdutil.graphrevs(repo, o, opts)
4102 4103 ui.pager('outgoing')
4103 4104 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4104 4105 logcmdutil.displaygraph(ui, repo, revdag, displayer,
4105 4106 graphmod.asciiedges)
4106 4107 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4107 4108 return 0
4108 4109
4109 4110 if opts.get('bookmarks'):
4110 4111 dest = path.pushloc or path.loc
4111 4112 other = hg.peer(repo, opts, dest)
4112 4113 if 'bookmarks' not in other.listkeys('namespaces'):
4113 4114 ui.warn(_("remote doesn't support bookmarks\n"))
4114 4115 return 0
4115 4116 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4116 4117 ui.pager('outgoing')
4117 4118 return bookmarks.outgoing(ui, repo, other)
4118 4119
4119 4120 repo._subtoppath = path.pushloc or path.loc
4120 4121 try:
4121 4122 return hg.outgoing(ui, repo, dest, opts)
4122 4123 finally:
4123 4124 del repo._subtoppath
4124 4125
4125 4126 @command('parents',
4126 4127 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4127 4128 ] + templateopts,
4128 4129 _('[-r REV] [FILE]'),
4129 4130 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4130 4131 inferrepo=True)
4131 4132 def parents(ui, repo, file_=None, **opts):
4132 4133 """show the parents of the working directory or revision (DEPRECATED)
4133 4134
4134 4135 Print the working directory's parent revisions. If a revision is
4135 4136 given via -r/--rev, the parent of that revision will be printed.
4136 4137 If a file argument is given, the revision in which the file was
4137 4138 last changed (before the working directory revision or the
4138 4139 argument to --rev if given) is printed.
4139 4140
4140 4141 This command is equivalent to::
4141 4142
4142 4143 hg log -r "p1()+p2()" or
4143 4144 hg log -r "p1(REV)+p2(REV)" or
4144 4145 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4145 4146 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4146 4147
4147 4148 See :hg:`summary` and :hg:`help revsets` for related information.
4148 4149
4149 4150 Returns 0 on success.
4150 4151 """
4151 4152
4152 4153 opts = pycompat.byteskwargs(opts)
4153 4154 rev = opts.get('rev')
4154 4155 if rev:
4155 4156 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4156 4157 ctx = scmutil.revsingle(repo, rev, None)
4157 4158
4158 4159 if file_:
4159 4160 m = scmutil.match(ctx, (file_,), opts)
4160 4161 if m.anypats() or len(m.files()) != 1:
4161 4162 raise error.Abort(_('can only specify an explicit filename'))
4162 4163 file_ = m.files()[0]
4163 4164 filenodes = []
4164 4165 for cp in ctx.parents():
4165 4166 if not cp:
4166 4167 continue
4167 4168 try:
4168 4169 filenodes.append(cp.filenode(file_))
4169 4170 except error.LookupError:
4170 4171 pass
4171 4172 if not filenodes:
4172 4173 raise error.Abort(_("'%s' not found in manifest!") % file_)
4173 4174 p = []
4174 4175 for fn in filenodes:
4175 4176 fctx = repo.filectx(file_, fileid=fn)
4176 4177 p.append(fctx.node())
4177 4178 else:
4178 4179 p = [cp.node() for cp in ctx.parents()]
4179 4180
4180 4181 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4181 4182 for n in p:
4182 4183 if n != nullid:
4183 4184 displayer.show(repo[n])
4184 4185 displayer.close()
4185 4186
4186 4187 @command('paths', formatteropts, _('[NAME]'),
4187 4188 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4188 4189 optionalrepo=True, intents={INTENT_READONLY})
4189 4190 def paths(ui, repo, search=None, **opts):
4190 4191 """show aliases for remote repositories
4191 4192
4192 4193 Show definition of symbolic path name NAME. If no name is given,
4193 4194 show definition of all available names.
4194 4195
4195 4196 Option -q/--quiet suppresses all output when searching for NAME
4196 4197 and shows only the path names when listing all definitions.
4197 4198
4198 4199 Path names are defined in the [paths] section of your
4199 4200 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4200 4201 repository, ``.hg/hgrc`` is used, too.
4201 4202
4202 4203 The path names ``default`` and ``default-push`` have a special
4203 4204 meaning. When performing a push or pull operation, they are used
4204 4205 as fallbacks if no location is specified on the command-line.
4205 4206 When ``default-push`` is set, it will be used for push and
4206 4207 ``default`` will be used for pull; otherwise ``default`` is used
4207 4208 as the fallback for both. When cloning a repository, the clone
4208 4209 source is written as ``default`` in ``.hg/hgrc``.
4209 4210
4210 4211 .. note::
4211 4212
4212 4213 ``default`` and ``default-push`` apply to all inbound (e.g.
4213 4214 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
4214 4215 and :hg:`bundle`) operations.
4215 4216
4216 4217 See :hg:`help urls` for more information.
4217 4218
4218 4219 .. container:: verbose
4219 4220
4220 4221 Template:
4221 4222
4222 4223 The following keywords are supported. See also :hg:`help templates`.
4223 4224
4224 4225 :name: String. Symbolic name of the path alias.
4225 4226 :pushurl: String. URL for push operations.
4226 4227 :url: String. URL or directory path for the other operations.
4227 4228
4228 4229 Returns 0 on success.
4229 4230 """
4230 4231
4231 4232 opts = pycompat.byteskwargs(opts)
4232 4233 ui.pager('paths')
4233 4234 if search:
4234 4235 pathitems = [(name, path) for name, path in ui.paths.iteritems()
4235 4236 if name == search]
4236 4237 else:
4237 4238 pathitems = sorted(ui.paths.iteritems())
4238 4239
4239 4240 fm = ui.formatter('paths', opts)
4240 4241 if fm.isplain():
4241 4242 hidepassword = util.hidepassword
4242 4243 else:
4243 4244 hidepassword = bytes
4244 4245 if ui.quiet:
4245 4246 namefmt = '%s\n'
4246 4247 else:
4247 4248 namefmt = '%s = '
4248 4249 showsubopts = not search and not ui.quiet
4249 4250
4250 4251 for name, path in pathitems:
4251 4252 fm.startitem()
4252 4253 fm.condwrite(not search, 'name', namefmt, name)
4253 4254 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4254 4255 for subopt, value in sorted(path.suboptions.items()):
4255 4256 assert subopt not in ('name', 'url')
4256 4257 if showsubopts:
4257 4258 fm.plain('%s:%s = ' % (name, subopt))
4258 4259 fm.condwrite(showsubopts, subopt, '%s\n', value)
4259 4260
4260 4261 fm.end()
4261 4262
4262 4263 if search and not pathitems:
4263 4264 if not ui.quiet:
4264 4265 ui.warn(_("not found!\n"))
4265 4266 return 1
4266 4267 else:
4267 4268 return 0
4268 4269
4269 4270 @command('phase',
4270 4271 [('p', 'public', False, _('set changeset phase to public')),
4271 4272 ('d', 'draft', False, _('set changeset phase to draft')),
4272 4273 ('s', 'secret', False, _('set changeset phase to secret')),
4273 4274 ('f', 'force', False, _('allow to move boundary backward')),
4274 4275 ('r', 'rev', [], _('target revision'), _('REV')),
4275 4276 ],
4276 4277 _('[-p|-d|-s] [-f] [-r] [REV...]'),
4277 4278 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
4278 4279 def phase(ui, repo, *revs, **opts):
4279 4280 """set or show the current phase name
4280 4281
4281 4282 With no argument, show the phase name of the current revision(s).
4282 4283
4283 4284 With one of -p/--public, -d/--draft or -s/--secret, change the
4284 4285 phase value of the specified revisions.
4285 4286
4286 4287 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4287 4288 lower phase to a higher phase. Phases are ordered as follows::
4288 4289
4289 4290 public < draft < secret
4290 4291
4291 4292 Returns 0 on success, 1 if some phases could not be changed.
4292 4293
4293 4294 (For more information about the phases concept, see :hg:`help phases`.)
4294 4295 """
4295 4296 opts = pycompat.byteskwargs(opts)
4296 4297 # search for a unique phase argument
4297 4298 targetphase = None
4298 4299 for idx, name in enumerate(phases.cmdphasenames):
4299 4300 if opts[name]:
4300 4301 if targetphase is not None:
4301 4302 raise error.Abort(_('only one phase can be specified'))
4302 4303 targetphase = idx
4303 4304
4304 4305 # look for specified revision
4305 4306 revs = list(revs)
4306 4307 revs.extend(opts['rev'])
4307 4308 if not revs:
4308 4309 # display both parents as the second parent phase can influence
4309 4310 # the phase of a merge commit
4310 4311 revs = [c.rev() for c in repo[None].parents()]
4311 4312
4312 4313 revs = scmutil.revrange(repo, revs)
4313 4314
4314 4315 ret = 0
4315 4316 if targetphase is None:
4316 4317 # display
4317 4318 for r in revs:
4318 4319 ctx = repo[r]
4319 4320 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4320 4321 else:
4321 4322 with repo.lock(), repo.transaction("phase") as tr:
4322 4323 # set phase
4323 4324 if not revs:
4324 4325 raise error.Abort(_('empty revision set'))
4325 4326 nodes = [repo[r].node() for r in revs]
4326 4327 # moving revision from public to draft may hide them
4327 4328 # We have to check result on an unfiltered repository
4328 4329 unfi = repo.unfiltered()
4329 4330 getphase = unfi._phasecache.phase
4330 4331 olddata = [getphase(unfi, r) for r in unfi]
4331 4332 phases.advanceboundary(repo, tr, targetphase, nodes)
4332 4333 if opts['force']:
4333 4334 phases.retractboundary(repo, tr, targetphase, nodes)
4334 4335 getphase = unfi._phasecache.phase
4335 4336 newdata = [getphase(unfi, r) for r in unfi]
4336 4337 changes = sum(newdata[r] != olddata[r] for r in unfi)
4337 4338 cl = unfi.changelog
4338 4339 rejected = [n for n in nodes
4339 4340 if newdata[cl.rev(n)] < targetphase]
4340 4341 if rejected:
4341 4342 ui.warn(_('cannot move %i changesets to a higher '
4342 4343 'phase, use --force\n') % len(rejected))
4343 4344 ret = 1
4344 4345 if changes:
4345 4346 msg = _('phase changed for %i changesets\n') % changes
4346 4347 if ret:
4347 4348 ui.status(msg)
4348 4349 else:
4349 4350 ui.note(msg)
4350 4351 else:
4351 4352 ui.warn(_('no phases changed\n'))
4352 4353 return ret
4353 4354
4354 4355 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4355 4356 """Run after a changegroup has been added via pull/unbundle
4356 4357
4357 4358 This takes arguments below:
4358 4359
4359 4360 :modheads: change of heads by pull/unbundle
4360 4361 :optupdate: updating working directory is needed or not
4361 4362 :checkout: update destination revision (or None to default destination)
4362 4363 :brev: a name, which might be a bookmark to be activated after updating
4363 4364 """
4364 4365 if modheads == 0:
4365 4366 return
4366 4367 if optupdate:
4367 4368 try:
4368 4369 return hg.updatetotally(ui, repo, checkout, brev)
4369 4370 except error.UpdateAbort as inst:
4370 4371 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4371 4372 hint = inst.hint
4372 4373 raise error.UpdateAbort(msg, hint=hint)
4373 4374 if modheads is not None and modheads > 1:
4374 4375 currentbranchheads = len(repo.branchheads())
4375 4376 if currentbranchheads == modheads:
4376 4377 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4377 4378 elif currentbranchheads > 1:
4378 4379 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4379 4380 "merge)\n"))
4380 4381 else:
4381 4382 ui.status(_("(run 'hg heads' to see heads)\n"))
4382 4383 elif not ui.configbool('commands', 'update.requiredest'):
4383 4384 ui.status(_("(run 'hg update' to get a working copy)\n"))
4384 4385
4385 4386 @command('pull',
4386 4387 [('u', 'update', None,
4387 4388 _('update to new branch head if new descendants were pulled')),
4388 4389 ('f', 'force', None, _('run even when remote repository is unrelated')),
4389 4390 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4390 4391 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4391 4392 ('b', 'branch', [], _('a specific branch you would like to pull'),
4392 4393 _('BRANCH')),
4393 4394 ] + remoteopts,
4394 4395 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
4395 4396 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4396 4397 helpbasic=True)
4397 4398 def pull(ui, repo, source="default", **opts):
4398 4399 """pull changes from the specified source
4399 4400
4400 4401 Pull changes from a remote repository to a local one.
4401 4402
4402 4403 This finds all changes from the repository at the specified path
4403 4404 or URL and adds them to a local repository (the current one unless
4404 4405 -R is specified). By default, this does not update the copy of the
4405 4406 project in the working directory.
4406 4407
4407 4408 When cloning from servers that support it, Mercurial may fetch
4408 4409 pre-generated data. When this is done, hooks operating on incoming
4409 4410 changesets and changegroups may fire more than once, once for each
4410 4411 pre-generated bundle and as well as for any additional remaining
4411 4412 data. See :hg:`help -e clonebundles` for more.
4412 4413
4413 4414 Use :hg:`incoming` if you want to see what would have been added
4414 4415 by a pull at the time you issued this command. If you then decide
4415 4416 to add those changes to the repository, you should use :hg:`pull
4416 4417 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4417 4418
4418 4419 If SOURCE is omitted, the 'default' path will be used.
4419 4420 See :hg:`help urls` for more information.
4420 4421
4421 4422 Specifying bookmark as ``.`` is equivalent to specifying the active
4422 4423 bookmark's name.
4423 4424
4424 4425 Returns 0 on success, 1 if an update had unresolved files.
4425 4426 """
4426 4427
4427 4428 opts = pycompat.byteskwargs(opts)
4428 4429 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4429 4430 msg = _('update destination required by configuration')
4430 4431 hint = _('use hg pull followed by hg update DEST')
4431 4432 raise error.Abort(msg, hint=hint)
4432 4433
4433 4434 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4434 4435 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4435 4436 other = hg.peer(repo, opts, source)
4436 4437 try:
4437 4438 revs, checkout = hg.addbranchrevs(repo, other, branches,
4438 4439 opts.get('rev'))
4439 4440
4440 4441 pullopargs = {}
4441 4442
4442 4443 nodes = None
4443 4444 if opts.get('bookmark') or revs:
4444 4445 # The list of bookmark used here is the same used to actually update
4445 4446 # the bookmark names, to avoid the race from issue 4689 and we do
4446 4447 # all lookup and bookmark queries in one go so they see the same
4447 4448 # version of the server state (issue 4700).
4448 4449 nodes = []
4449 4450 fnodes = []
4450 4451 revs = revs or []
4451 4452 if revs and not other.capable('lookup'):
4452 4453 err = _("other repository doesn't support revision lookup, "
4453 4454 "so a rev cannot be specified.")
4454 4455 raise error.Abort(err)
4455 4456 with other.commandexecutor() as e:
4456 4457 fremotebookmarks = e.callcommand('listkeys', {
4457 4458 'namespace': 'bookmarks'
4458 4459 })
4459 4460 for r in revs:
4460 4461 fnodes.append(e.callcommand('lookup', {'key': r}))
4461 4462 remotebookmarks = fremotebookmarks.result()
4462 4463 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4463 4464 pullopargs['remotebookmarks'] = remotebookmarks
4464 4465 for b in opts.get('bookmark', []):
4465 4466 b = repo._bookmarks.expandname(b)
4466 4467 if b not in remotebookmarks:
4467 4468 raise error.Abort(_('remote bookmark %s not found!') % b)
4468 4469 nodes.append(remotebookmarks[b])
4469 4470 for i, rev in enumerate(revs):
4470 4471 node = fnodes[i].result()
4471 4472 nodes.append(node)
4472 4473 if rev == checkout:
4473 4474 checkout = node
4474 4475
4475 4476 wlock = util.nullcontextmanager()
4476 4477 if opts.get('update'):
4477 4478 wlock = repo.wlock()
4478 4479 with wlock:
4479 4480 pullopargs.update(opts.get('opargs', {}))
4480 4481 modheads = exchange.pull(repo, other, heads=nodes,
4481 4482 force=opts.get('force'),
4482 4483 bookmarks=opts.get('bookmark', ()),
4483 4484 opargs=pullopargs).cgresult
4484 4485
4485 4486 # brev is a name, which might be a bookmark to be activated at
4486 4487 # the end of the update. In other words, it is an explicit
4487 4488 # destination of the update
4488 4489 brev = None
4489 4490
4490 4491 if checkout:
4491 4492 checkout = repo.unfiltered().changelog.rev(checkout)
4492 4493
4493 4494 # order below depends on implementation of
4494 4495 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4495 4496 # because 'checkout' is determined without it.
4496 4497 if opts.get('rev'):
4497 4498 brev = opts['rev'][0]
4498 4499 elif opts.get('branch'):
4499 4500 brev = opts['branch'][0]
4500 4501 else:
4501 4502 brev = branches[0]
4502 4503 repo._subtoppath = source
4503 4504 try:
4504 4505 ret = postincoming(ui, repo, modheads, opts.get('update'),
4505 4506 checkout, brev)
4506 4507 except error.FilteredRepoLookupError as exc:
4507 4508 msg = _('cannot update to target: %s') % exc.args[0]
4508 4509 exc.args = (msg,) + exc.args[1:]
4509 4510 raise
4510 4511 finally:
4511 4512 del repo._subtoppath
4512 4513
4513 4514 finally:
4514 4515 other.close()
4515 4516 return ret
4516 4517
4517 4518 @command('push',
4518 4519 [('f', 'force', None, _('force push')),
4519 4520 ('r', 'rev', [],
4520 4521 _('a changeset intended to be included in the destination'),
4521 4522 _('REV')),
4522 4523 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4523 4524 ('b', 'branch', [],
4524 4525 _('a specific branch you would like to push'), _('BRANCH')),
4525 4526 ('', 'new-branch', False, _('allow pushing a new branch')),
4526 4527 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4527 4528 ('', 'publish', False, _('push the changeset as public (EXPERIMENTAL)')),
4528 4529 ] + remoteopts,
4529 4530 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
4530 4531 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4531 4532 helpbasic=True)
4532 4533 def push(ui, repo, dest=None, **opts):
4533 4534 """push changes to the specified destination
4534 4535
4535 4536 Push changesets from the local repository to the specified
4536 4537 destination.
4537 4538
4538 4539 This operation is symmetrical to pull: it is identical to a pull
4539 4540 in the destination repository from the current one.
4540 4541
4541 4542 By default, push will not allow creation of new heads at the
4542 4543 destination, since multiple heads would make it unclear which head
4543 4544 to use. In this situation, it is recommended to pull and merge
4544 4545 before pushing.
4545 4546
4546 4547 Use --new-branch if you want to allow push to create a new named
4547 4548 branch that is not present at the destination. This allows you to
4548 4549 only create a new branch without forcing other changes.
4549 4550
4550 4551 .. note::
4551 4552
4552 4553 Extra care should be taken with the -f/--force option,
4553 4554 which will push all new heads on all branches, an action which will
4554 4555 almost always cause confusion for collaborators.
4555 4556
4556 4557 If -r/--rev is used, the specified revision and all its ancestors
4557 4558 will be pushed to the remote repository.
4558 4559
4559 4560 If -B/--bookmark is used, the specified bookmarked revision, its
4560 4561 ancestors, and the bookmark will be pushed to the remote
4561 4562 repository. Specifying ``.`` is equivalent to specifying the active
4562 4563 bookmark's name.
4563 4564
4564 4565 Please see :hg:`help urls` for important details about ``ssh://``
4565 4566 URLs. If DESTINATION is omitted, a default path will be used.
4566 4567
4567 4568 .. container:: verbose
4568 4569
4569 4570 The --pushvars option sends strings to the server that become
4570 4571 environment variables prepended with ``HG_USERVAR_``. For example,
4571 4572 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4572 4573 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4573 4574
4574 4575 pushvars can provide for user-overridable hooks as well as set debug
4575 4576 levels. One example is having a hook that blocks commits containing
4576 4577 conflict markers, but enables the user to override the hook if the file
4577 4578 is using conflict markers for testing purposes or the file format has
4578 4579 strings that look like conflict markers.
4579 4580
4580 4581 By default, servers will ignore `--pushvars`. To enable it add the
4581 4582 following to your configuration file::
4582 4583
4583 4584 [push]
4584 4585 pushvars.server = true
4585 4586
4586 4587 Returns 0 if push was successful, 1 if nothing to push.
4587 4588 """
4588 4589
4589 4590 opts = pycompat.byteskwargs(opts)
4590 4591 if opts.get('bookmark'):
4591 4592 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4592 4593 for b in opts['bookmark']:
4593 4594 # translate -B options to -r so changesets get pushed
4594 4595 b = repo._bookmarks.expandname(b)
4595 4596 if b in repo._bookmarks:
4596 4597 opts.setdefault('rev', []).append(b)
4597 4598 else:
4598 4599 # if we try to push a deleted bookmark, translate it to null
4599 4600 # this lets simultaneous -r, -b options continue working
4600 4601 opts.setdefault('rev', []).append("null")
4601 4602
4602 4603 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4603 4604 if not path:
4604 4605 raise error.Abort(_('default repository not configured!'),
4605 4606 hint=_("see 'hg help config.paths'"))
4606 4607 dest = path.pushloc or path.loc
4607 4608 branches = (path.branch, opts.get('branch') or [])
4608 4609 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4609 4610 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4610 4611 other = hg.peer(repo, opts, dest)
4611 4612
4612 4613 if revs:
4613 4614 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4614 4615 if not revs:
4615 4616 raise error.Abort(_("specified revisions evaluate to an empty set"),
4616 4617 hint=_("use different revision arguments"))
4617 4618 elif path.pushrev:
4618 4619 # It doesn't make any sense to specify ancestor revisions. So limit
4619 4620 # to DAG heads to make discovery simpler.
4620 4621 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4621 4622 revs = scmutil.revrange(repo, [expr])
4622 4623 revs = [repo[rev].node() for rev in revs]
4623 4624 if not revs:
4624 4625 raise error.Abort(_('default push revset for path evaluates to an '
4625 4626 'empty set'))
4626 4627
4627 4628 repo._subtoppath = dest
4628 4629 try:
4629 4630 # push subrepos depth-first for coherent ordering
4630 4631 c = repo['.']
4631 4632 subs = c.substate # only repos that are committed
4632 4633 for s in sorted(subs):
4633 4634 result = c.sub(s).push(opts)
4634 4635 if result == 0:
4635 4636 return not result
4636 4637 finally:
4637 4638 del repo._subtoppath
4638 4639
4639 4640 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4640 4641 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4641 4642
4642 4643 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4643 4644 newbranch=opts.get('new_branch'),
4644 4645 bookmarks=opts.get('bookmark', ()),
4645 4646 publish=opts.get('publish'),
4646 4647 opargs=opargs)
4647 4648
4648 4649 result = not pushop.cgresult
4649 4650
4650 4651 if pushop.bkresult is not None:
4651 4652 if pushop.bkresult == 2:
4652 4653 result = 2
4653 4654 elif not result and pushop.bkresult:
4654 4655 result = 2
4655 4656
4656 4657 return result
4657 4658
4658 4659 @command('recover',
4659 4660 [('','verify', True, "run `hg verify` after succesful recover"),
4660 4661 ],
4661 4662 helpcategory=command.CATEGORY_MAINTENANCE)
4662 4663 def recover(ui, repo, **opts):
4663 4664 """roll back an interrupted transaction
4664 4665
4665 4666 Recover from an interrupted commit or pull.
4666 4667
4667 4668 This command tries to fix the repository status after an
4668 4669 interrupted operation. It should only be necessary when Mercurial
4669 4670 suggests it.
4670 4671
4671 4672 Returns 0 if successful, 1 if nothing to recover or verify fails.
4672 4673 """
4673 4674 ret = repo.recover()
4674 4675 if ret:
4675 4676 if opts['verify']:
4676 4677 return hg.verify(repo)
4677 4678 else:
4678 4679 msg = _("(verify step skipped, run `hg verify` to check your "
4679 4680 "repository content)\n")
4680 4681 ui.warn(msg)
4681 4682 return 0
4682 4683 return 1
4683 4684
4684 4685 @command('remove|rm',
4685 4686 [('A', 'after', None, _('record delete for missing files')),
4686 4687 ('f', 'force', None,
4687 4688 _('forget added files, delete modified files')),
4688 4689 ] + subrepoopts + walkopts + dryrunopts,
4689 4690 _('[OPTION]... FILE...'),
4690 4691 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4691 4692 helpbasic=True, inferrepo=True)
4692 4693 def remove(ui, repo, *pats, **opts):
4693 4694 """remove the specified files on the next commit
4694 4695
4695 4696 Schedule the indicated files for removal from the current branch.
4696 4697
4697 4698 This command schedules the files to be removed at the next commit.
4698 4699 To undo a remove before that, see :hg:`revert`. To undo added
4699 4700 files, see :hg:`forget`.
4700 4701
4701 4702 .. container:: verbose
4702 4703
4703 4704 -A/--after can be used to remove only files that have already
4704 4705 been deleted, -f/--force can be used to force deletion, and -Af
4705 4706 can be used to remove files from the next revision without
4706 4707 deleting them from the working directory.
4707 4708
4708 4709 The following table details the behavior of remove for different
4709 4710 file states (columns) and option combinations (rows). The file
4710 4711 states are Added [A], Clean [C], Modified [M] and Missing [!]
4711 4712 (as reported by :hg:`status`). The actions are Warn, Remove
4712 4713 (from branch) and Delete (from disk):
4713 4714
4714 4715 ========= == == == ==
4715 4716 opt/state A C M !
4716 4717 ========= == == == ==
4717 4718 none W RD W R
4718 4719 -f R RD RD R
4719 4720 -A W W W R
4720 4721 -Af R R R R
4721 4722 ========= == == == ==
4722 4723
4723 4724 .. note::
4724 4725
4725 4726 :hg:`remove` never deletes files in Added [A] state from the
4726 4727 working directory, not even if ``--force`` is specified.
4727 4728
4728 4729 Returns 0 on success, 1 if any warnings encountered.
4729 4730 """
4730 4731
4731 4732 opts = pycompat.byteskwargs(opts)
4732 4733 after, force = opts.get('after'), opts.get('force')
4733 4734 dryrun = opts.get('dry_run')
4734 4735 if not pats and not after:
4735 4736 raise error.Abort(_('no files specified'))
4736 4737
4737 4738 m = scmutil.match(repo[None], pats, opts)
4738 4739 subrepos = opts.get('subrepos')
4739 4740 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
4740 4741 return cmdutil.remove(ui, repo, m, "", uipathfn, after, force, subrepos,
4741 4742 dryrun=dryrun)
4742 4743
4743 4744 @command('rename|move|mv',
4744 4745 [('A', 'after', None, _('record a rename that has already occurred')),
4745 4746 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4746 4747 ] + walkopts + dryrunopts,
4747 4748 _('[OPTION]... SOURCE... DEST'),
4748 4749 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
4749 4750 def rename(ui, repo, *pats, **opts):
4750 4751 """rename files; equivalent of copy + remove
4751 4752
4752 4753 Mark dest as copies of sources; mark sources for deletion. If dest
4753 4754 is a directory, copies are put in that directory. If dest is a
4754 4755 file, there can only be one source.
4755 4756
4756 4757 By default, this command copies the contents of files as they
4757 4758 exist in the working directory. If invoked with -A/--after, the
4758 4759 operation is recorded, but no copying is performed.
4759 4760
4760 4761 This command takes effect at the next commit. To undo a rename
4761 4762 before that, see :hg:`revert`.
4762 4763
4763 4764 Returns 0 on success, 1 if errors are encountered.
4764 4765 """
4765 4766 opts = pycompat.byteskwargs(opts)
4766 4767 with repo.wlock(False):
4767 4768 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4768 4769
4769 4770 @command('resolve',
4770 4771 [('a', 'all', None, _('select all unresolved files')),
4771 4772 ('l', 'list', None, _('list state of files needing merge')),
4772 4773 ('m', 'mark', None, _('mark files as resolved')),
4773 4774 ('u', 'unmark', None, _('mark files as unresolved')),
4774 4775 ('n', 'no-status', None, _('hide status prefix')),
4775 4776 ('', 're-merge', None, _('re-merge files'))]
4776 4777 + mergetoolopts + walkopts + formatteropts,
4777 4778 _('[OPTION]... [FILE]...'),
4778 4779 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4779 4780 inferrepo=True)
4780 4781 def resolve(ui, repo, *pats, **opts):
4781 4782 """redo merges or set/view the merge status of files
4782 4783
4783 4784 Merges with unresolved conflicts are often the result of
4784 4785 non-interactive merging using the ``internal:merge`` configuration
4785 4786 setting, or a command-line merge tool like ``diff3``. The resolve
4786 4787 command is used to manage the files involved in a merge, after
4787 4788 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4788 4789 working directory must have two parents). See :hg:`help
4789 4790 merge-tools` for information on configuring merge tools.
4790 4791
4791 4792 The resolve command can be used in the following ways:
4792 4793
4793 4794 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4794 4795 the specified files, discarding any previous merge attempts. Re-merging
4795 4796 is not performed for files already marked as resolved. Use ``--all/-a``
4796 4797 to select all unresolved files. ``--tool`` can be used to specify
4797 4798 the merge tool used for the given files. It overrides the HGMERGE
4798 4799 environment variable and your configuration files. Previous file
4799 4800 contents are saved with a ``.orig`` suffix.
4800 4801
4801 4802 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4802 4803 (e.g. after having manually fixed-up the files). The default is
4803 4804 to mark all unresolved files.
4804 4805
4805 4806 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4806 4807 default is to mark all resolved files.
4807 4808
4808 4809 - :hg:`resolve -l`: list files which had or still have conflicts.
4809 4810 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4810 4811 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4811 4812 the list. See :hg:`help filesets` for details.
4812 4813
4813 4814 .. note::
4814 4815
4815 4816 Mercurial will not let you commit files with unresolved merge
4816 4817 conflicts. You must use :hg:`resolve -m ...` before you can
4817 4818 commit after a conflicting merge.
4818 4819
4819 4820 .. container:: verbose
4820 4821
4821 4822 Template:
4822 4823
4823 4824 The following keywords are supported in addition to the common template
4824 4825 keywords and functions. See also :hg:`help templates`.
4825 4826
4826 4827 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
4827 4828 :path: String. Repository-absolute path of the file.
4828 4829
4829 4830 Returns 0 on success, 1 if any files fail a resolve attempt.
4830 4831 """
4831 4832
4832 4833 opts = pycompat.byteskwargs(opts)
4833 4834 confirm = ui.configbool('commands', 'resolve.confirm')
4834 4835 flaglist = 'all mark unmark list no_status re_merge'.split()
4835 4836 all, mark, unmark, show, nostatus, remerge = [
4836 4837 opts.get(o) for o in flaglist]
4837 4838
4838 4839 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4839 4840 if actioncount > 1:
4840 4841 raise error.Abort(_("too many actions specified"))
4841 4842 elif (actioncount == 0
4842 4843 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4843 4844 hint = _('use --mark, --unmark, --list or --re-merge')
4844 4845 raise error.Abort(_('no action specified'), hint=hint)
4845 4846 if pats and all:
4846 4847 raise error.Abort(_("can't specify --all and patterns"))
4847 4848 if not (all or pats or show or mark or unmark):
4848 4849 raise error.Abort(_('no files or directories specified'),
4849 4850 hint=('use --all to re-merge all unresolved files'))
4850 4851
4851 4852 if confirm:
4852 4853 if all:
4853 4854 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4854 4855 b'$$ &Yes $$ &No')):
4855 4856 raise error.Abort(_('user quit'))
4856 4857 if mark and not pats:
4857 4858 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4858 4859 b'$$ &Yes $$ &No')):
4859 4860 raise error.Abort(_('user quit'))
4860 4861 if unmark and not pats:
4861 4862 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4862 4863 b'$$ &Yes $$ &No')):
4863 4864 raise error.Abort(_('user quit'))
4864 4865
4865 4866 uipathfn = scmutil.getuipathfn(repo)
4866 4867
4867 4868 if show:
4868 4869 ui.pager('resolve')
4869 4870 fm = ui.formatter('resolve', opts)
4870 4871 ms = mergemod.mergestate.read(repo)
4871 4872 wctx = repo[None]
4872 4873 m = scmutil.match(wctx, pats, opts)
4873 4874
4874 4875 # Labels and keys based on merge state. Unresolved path conflicts show
4875 4876 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4876 4877 # resolved conflicts.
4877 4878 mergestateinfo = {
4878 4879 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4879 4880 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4880 4881 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4881 4882 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4882 4883 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4883 4884 'D'),
4884 4885 }
4885 4886
4886 4887 for f in ms:
4887 4888 if not m(f):
4888 4889 continue
4889 4890
4890 4891 label, key = mergestateinfo[ms[f]]
4891 4892 fm.startitem()
4892 4893 fm.context(ctx=wctx)
4893 4894 fm.condwrite(not nostatus, 'mergestatus', '%s ', key, label=label)
4894 4895 fm.data(path=f)
4895 4896 fm.plain('%s\n' % uipathfn(f), label=label)
4896 4897 fm.end()
4897 4898 return 0
4898 4899
4899 4900 with repo.wlock():
4900 4901 ms = mergemod.mergestate.read(repo)
4901 4902
4902 4903 if not (ms.active() or repo.dirstate.p2() != nullid):
4903 4904 raise error.Abort(
4904 4905 _('resolve command not applicable when not merging'))
4905 4906
4906 4907 wctx = repo[None]
4907 4908
4908 4909 if (ms.mergedriver
4909 4910 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4910 4911 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4911 4912 ms.commit()
4912 4913 # allow mark and unmark to go through
4913 4914 if not mark and not unmark and not proceed:
4914 4915 return 1
4915 4916
4916 4917 m = scmutil.match(wctx, pats, opts)
4917 4918 ret = 0
4918 4919 didwork = False
4919 4920 runconclude = False
4920 4921
4921 4922 tocomplete = []
4922 4923 hasconflictmarkers = []
4923 4924 if mark:
4924 4925 markcheck = ui.config('commands', 'resolve.mark-check')
4925 4926 if markcheck not in ['warn', 'abort']:
4926 4927 # Treat all invalid / unrecognized values as 'none'.
4927 4928 markcheck = False
4928 4929 for f in ms:
4929 4930 if not m(f):
4930 4931 continue
4931 4932
4932 4933 didwork = True
4933 4934
4934 4935 # don't let driver-resolved files be marked, and run the conclude
4935 4936 # step if asked to resolve
4936 4937 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4937 4938 exact = m.exact(f)
4938 4939 if mark:
4939 4940 if exact:
4940 4941 ui.warn(_('not marking %s as it is driver-resolved\n')
4941 4942 % uipathfn(f))
4942 4943 elif unmark:
4943 4944 if exact:
4944 4945 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4945 4946 % uipathfn(f))
4946 4947 else:
4947 4948 runconclude = True
4948 4949 continue
4949 4950
4950 4951 # path conflicts must be resolved manually
4951 4952 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4952 4953 mergemod.MERGE_RECORD_RESOLVED_PATH):
4953 4954 if mark:
4954 4955 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4955 4956 elif unmark:
4956 4957 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4957 4958 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4958 4959 ui.warn(_('%s: path conflict must be resolved manually\n')
4959 4960 % uipathfn(f))
4960 4961 continue
4961 4962
4962 4963 if mark:
4963 4964 if markcheck:
4964 4965 fdata = repo.wvfs.tryread(f)
4965 4966 if (filemerge.hasconflictmarkers(fdata) and
4966 4967 ms[f] != mergemod.MERGE_RECORD_RESOLVED):
4967 4968 hasconflictmarkers.append(f)
4968 4969 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4969 4970 elif unmark:
4970 4971 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4971 4972 else:
4972 4973 # backup pre-resolve (merge uses .orig for its own purposes)
4973 4974 a = repo.wjoin(f)
4974 4975 try:
4975 4976 util.copyfile(a, a + ".resolve")
4976 4977 except (IOError, OSError) as inst:
4977 4978 if inst.errno != errno.ENOENT:
4978 4979 raise
4979 4980
4980 4981 try:
4981 4982 # preresolve file
4982 4983 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4983 4984 with ui.configoverride(overrides, 'resolve'):
4984 4985 complete, r = ms.preresolve(f, wctx)
4985 4986 if not complete:
4986 4987 tocomplete.append(f)
4987 4988 elif r:
4988 4989 ret = 1
4989 4990 finally:
4990 4991 ms.commit()
4991 4992
4992 4993 # replace filemerge's .orig file with our resolve file, but only
4993 4994 # for merges that are complete
4994 4995 if complete:
4995 4996 try:
4996 4997 util.rename(a + ".resolve",
4997 4998 scmutil.backuppath(ui, repo, f))
4998 4999 except OSError as inst:
4999 5000 if inst.errno != errno.ENOENT:
5000 5001 raise
5001 5002
5002 5003 if hasconflictmarkers:
5003 5004 ui.warn(_('warning: the following files still have conflict '
5004 5005 'markers:\n') + ''.join(' ' + uipathfn(f) + '\n'
5005 5006 for f in hasconflictmarkers))
5006 5007 if markcheck == 'abort' and not all and not pats:
5007 5008 raise error.Abort(_('conflict markers detected'),
5008 5009 hint=_('use --all to mark anyway'))
5009 5010
5010 5011 for f in tocomplete:
5011 5012 try:
5012 5013 # resolve file
5013 5014 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
5014 5015 with ui.configoverride(overrides, 'resolve'):
5015 5016 r = ms.resolve(f, wctx)
5016 5017 if r:
5017 5018 ret = 1
5018 5019 finally:
5019 5020 ms.commit()
5020 5021
5021 5022 # replace filemerge's .orig file with our resolve file
5022 5023 a = repo.wjoin(f)
5023 5024 try:
5024 5025 util.rename(a + ".resolve", scmutil.backuppath(ui, repo, f))
5025 5026 except OSError as inst:
5026 5027 if inst.errno != errno.ENOENT:
5027 5028 raise
5028 5029
5029 5030 ms.commit()
5030 5031 ms.recordactions()
5031 5032
5032 5033 if not didwork and pats:
5033 5034 hint = None
5034 5035 if not any([p for p in pats if p.find(':') >= 0]):
5035 5036 pats = ['path:%s' % p for p in pats]
5036 5037 m = scmutil.match(wctx, pats, opts)
5037 5038 for f in ms:
5038 5039 if not m(f):
5039 5040 continue
5040 5041 def flag(o):
5041 5042 if o == 're_merge':
5042 5043 return '--re-merge '
5043 5044 return '-%s ' % o[0:1]
5044 5045 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
5045 5046 hint = _("(try: hg resolve %s%s)\n") % (
5046 5047 flags,
5047 5048 ' '.join(pats))
5048 5049 break
5049 5050 ui.warn(_("arguments do not match paths that need resolving\n"))
5050 5051 if hint:
5051 5052 ui.warn(hint)
5052 5053 elif ms.mergedriver and ms.mdstate() != 's':
5053 5054 # run conclude step when either a driver-resolved file is requested
5054 5055 # or there are no driver-resolved files
5055 5056 # we can't use 'ret' to determine whether any files are unresolved
5056 5057 # because we might not have tried to resolve some
5057 5058 if ((runconclude or not list(ms.driverresolved()))
5058 5059 and not list(ms.unresolved())):
5059 5060 proceed = mergemod.driverconclude(repo, ms, wctx)
5060 5061 ms.commit()
5061 5062 if not proceed:
5062 5063 return 1
5063 5064
5064 5065 # Nudge users into finishing an unfinished operation
5065 5066 unresolvedf = list(ms.unresolved())
5066 5067 driverresolvedf = list(ms.driverresolved())
5067 5068 if not unresolvedf and not driverresolvedf:
5068 5069 ui.status(_('(no more unresolved files)\n'))
5069 5070 cmdutil.checkafterresolved(repo)
5070 5071 elif not unresolvedf:
5071 5072 ui.status(_('(no more unresolved files -- '
5072 5073 'run "hg resolve --all" to conclude)\n'))
5073 5074
5074 5075 return ret
5075 5076
5076 5077 @command('revert',
5077 5078 [('a', 'all', None, _('revert all changes when no arguments given')),
5078 5079 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5079 5080 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5080 5081 ('C', 'no-backup', None, _('do not save backup copies of files')),
5081 5082 ('i', 'interactive', None, _('interactively select the changes')),
5082 5083 ] + walkopts + dryrunopts,
5083 5084 _('[OPTION]... [-r REV] [NAME]...'),
5084 5085 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5085 5086 def revert(ui, repo, *pats, **opts):
5086 5087 """restore files to their checkout state
5087 5088
5088 5089 .. note::
5089 5090
5090 5091 To check out earlier revisions, you should use :hg:`update REV`.
5091 5092 To cancel an uncommitted merge (and lose your changes),
5092 5093 use :hg:`merge --abort`.
5093 5094
5094 5095 With no revision specified, revert the specified files or directories
5095 5096 to the contents they had in the parent of the working directory.
5096 5097 This restores the contents of files to an unmodified
5097 5098 state and unschedules adds, removes, copies, and renames. If the
5098 5099 working directory has two parents, you must explicitly specify a
5099 5100 revision.
5100 5101
5101 5102 Using the -r/--rev or -d/--date options, revert the given files or
5102 5103 directories to their states as of a specific revision. Because
5103 5104 revert does not change the working directory parents, this will
5104 5105 cause these files to appear modified. This can be helpful to "back
5105 5106 out" some or all of an earlier change. See :hg:`backout` for a
5106 5107 related method.
5107 5108
5108 5109 Modified files are saved with a .orig suffix before reverting.
5109 5110 To disable these backups, use --no-backup. It is possible to store
5110 5111 the backup files in a custom directory relative to the root of the
5111 5112 repository by setting the ``ui.origbackuppath`` configuration
5112 5113 option.
5113 5114
5114 5115 See :hg:`help dates` for a list of formats valid for -d/--date.
5115 5116
5116 5117 See :hg:`help backout` for a way to reverse the effect of an
5117 5118 earlier changeset.
5118 5119
5119 5120 Returns 0 on success.
5120 5121 """
5121 5122
5122 5123 opts = pycompat.byteskwargs(opts)
5123 5124 if opts.get("date"):
5124 5125 if opts.get("rev"):
5125 5126 raise error.Abort(_("you can't specify a revision and a date"))
5126 5127 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5127 5128
5128 5129 parent, p2 = repo.dirstate.parents()
5129 5130 if not opts.get('rev') and p2 != nullid:
5130 5131 # revert after merge is a trap for new users (issue2915)
5131 5132 raise error.Abort(_('uncommitted merge with no revision specified'),
5132 5133 hint=_("use 'hg update' or see 'hg help revert'"))
5133 5134
5134 5135 rev = opts.get('rev')
5135 5136 if rev:
5136 5137 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5137 5138 ctx = scmutil.revsingle(repo, rev)
5138 5139
5139 5140 if (not (pats or opts.get('include') or opts.get('exclude') or
5140 5141 opts.get('all') or opts.get('interactive'))):
5141 5142 msg = _("no files or directories specified")
5142 5143 if p2 != nullid:
5143 5144 hint = _("uncommitted merge, use --all to discard all changes,"
5144 5145 " or 'hg update -C .' to abort the merge")
5145 5146 raise error.Abort(msg, hint=hint)
5146 5147 dirty = any(repo.status())
5147 5148 node = ctx.node()
5148 5149 if node != parent:
5149 5150 if dirty:
5150 5151 hint = _("uncommitted changes, use --all to discard all"
5151 5152 " changes, or 'hg update %d' to update") % ctx.rev()
5152 5153 else:
5153 5154 hint = _("use --all to revert all files,"
5154 5155 " or 'hg update %d' to update") % ctx.rev()
5155 5156 elif dirty:
5156 5157 hint = _("uncommitted changes, use --all to discard all changes")
5157 5158 else:
5158 5159 hint = _("use --all to revert all files")
5159 5160 raise error.Abort(msg, hint=hint)
5160 5161
5161 5162 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
5162 5163 **pycompat.strkwargs(opts))
5163 5164
5164 5165 @command(
5165 5166 'rollback',
5166 5167 dryrunopts + [('f', 'force', False, _('ignore safety measures'))],
5167 5168 helpcategory=command.CATEGORY_MAINTENANCE)
5168 5169 def rollback(ui, repo, **opts):
5169 5170 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5170 5171
5171 5172 Please use :hg:`commit --amend` instead of rollback to correct
5172 5173 mistakes in the last commit.
5173 5174
5174 5175 This command should be used with care. There is only one level of
5175 5176 rollback, and there is no way to undo a rollback. It will also
5176 5177 restore the dirstate at the time of the last transaction, losing
5177 5178 any dirstate changes since that time. This command does not alter
5178 5179 the working directory.
5179 5180
5180 5181 Transactions are used to encapsulate the effects of all commands
5181 5182 that create new changesets or propagate existing changesets into a
5182 5183 repository.
5183 5184
5184 5185 .. container:: verbose
5185 5186
5186 5187 For example, the following commands are transactional, and their
5187 5188 effects can be rolled back:
5188 5189
5189 5190 - commit
5190 5191 - import
5191 5192 - pull
5192 5193 - push (with this repository as the destination)
5193 5194 - unbundle
5194 5195
5195 5196 To avoid permanent data loss, rollback will refuse to rollback a
5196 5197 commit transaction if it isn't checked out. Use --force to
5197 5198 override this protection.
5198 5199
5199 5200 The rollback command can be entirely disabled by setting the
5200 5201 ``ui.rollback`` configuration setting to false. If you're here
5201 5202 because you want to use rollback and it's disabled, you can
5202 5203 re-enable the command by setting ``ui.rollback`` to true.
5203 5204
5204 5205 This command is not intended for use on public repositories. Once
5205 5206 changes are visible for pull by other users, rolling a transaction
5206 5207 back locally is ineffective (someone else may already have pulled
5207 5208 the changes). Furthermore, a race is possible with readers of the
5208 5209 repository; for example an in-progress pull from the repository
5209 5210 may fail if a rollback is performed.
5210 5211
5211 5212 Returns 0 on success, 1 if no rollback data is available.
5212 5213 """
5213 5214 if not ui.configbool('ui', 'rollback'):
5214 5215 raise error.Abort(_('rollback is disabled because it is unsafe'),
5215 5216 hint=('see `hg help -v rollback` for information'))
5216 5217 return repo.rollback(dryrun=opts.get(r'dry_run'),
5217 5218 force=opts.get(r'force'))
5218 5219
5219 5220 @command(
5220 5221 'root', [], intents={INTENT_READONLY},
5221 5222 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5222 5223 def root(ui, repo):
5223 5224 """print the root (top) of the current working directory
5224 5225
5225 5226 Print the root directory of the current repository.
5226 5227
5227 5228 Returns 0 on success.
5228 5229 """
5229 5230 ui.write(repo.root + "\n")
5230 5231
5231 5232 @command('serve',
5232 5233 [('A', 'accesslog', '', _('name of access log file to write to'),
5233 5234 _('FILE')),
5234 5235 ('d', 'daemon', None, _('run server in background')),
5235 5236 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
5236 5237 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5237 5238 # use string type, then we can check if something was passed
5238 5239 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5239 5240 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5240 5241 _('ADDR')),
5241 5242 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5242 5243 _('PREFIX')),
5243 5244 ('n', 'name', '',
5244 5245 _('name to show in web pages (default: working directory)'), _('NAME')),
5245 5246 ('', 'web-conf', '',
5246 5247 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
5247 5248 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5248 5249 _('FILE')),
5249 5250 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5250 5251 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
5251 5252 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
5252 5253 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5253 5254 ('', 'style', '', _('template style to use'), _('STYLE')),
5254 5255 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5255 5256 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
5256 5257 ('', 'print-url', None, _('start and print only the URL'))]
5257 5258 + subrepoopts,
5258 5259 _('[OPTION]...'),
5259 5260 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5260 5261 helpbasic=True, optionalrepo=True)
5261 5262 def serve(ui, repo, **opts):
5262 5263 """start stand-alone webserver
5263 5264
5264 5265 Start a local HTTP repository browser and pull server. You can use
5265 5266 this for ad-hoc sharing and browsing of repositories. It is
5266 5267 recommended to use a real web server to serve a repository for
5267 5268 longer periods of time.
5268 5269
5269 5270 Please note that the server does not implement access control.
5270 5271 This means that, by default, anybody can read from the server and
5271 5272 nobody can write to it by default. Set the ``web.allow-push``
5272 5273 option to ``*`` to allow everybody to push to the server. You
5273 5274 should use a real web server if you need to authenticate users.
5274 5275
5275 5276 By default, the server logs accesses to stdout and errors to
5276 5277 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5277 5278 files.
5278 5279
5279 5280 To have the server choose a free port number to listen on, specify
5280 5281 a port number of 0; in this case, the server will print the port
5281 5282 number it uses.
5282 5283
5283 5284 Returns 0 on success.
5284 5285 """
5285 5286
5286 5287 opts = pycompat.byteskwargs(opts)
5287 5288 if opts["stdio"] and opts["cmdserver"]:
5288 5289 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5289 5290 if opts["print_url"] and ui.verbose:
5290 5291 raise error.Abort(_("cannot use --print-url with --verbose"))
5291 5292
5292 5293 if opts["stdio"]:
5293 5294 if repo is None:
5294 5295 raise error.RepoError(_("there is no Mercurial repository here"
5295 5296 " (.hg not found)"))
5296 5297 s = wireprotoserver.sshserver(ui, repo)
5297 5298 s.serve_forever()
5298 5299
5299 5300 service = server.createservice(ui, repo, opts)
5300 5301 return server.runservice(opts, initfn=service.init, runfn=service.run)
5301 5302
5302 5303 _NOTTERSE = 'nothing'
5303 5304
5304 5305 @command('status|st',
5305 5306 [('A', 'all', None, _('show status of all files')),
5306 5307 ('m', 'modified', None, _('show only modified files')),
5307 5308 ('a', 'added', None, _('show only added files')),
5308 5309 ('r', 'removed', None, _('show only removed files')),
5309 5310 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5310 5311 ('c', 'clean', None, _('show only files without changes')),
5311 5312 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5312 5313 ('i', 'ignored', None, _('show only ignored files')),
5313 5314 ('n', 'no-status', None, _('hide status prefix')),
5314 5315 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5315 5316 ('C', 'copies', None, _('show source of copied files')),
5316 5317 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5317 5318 ('', 'rev', [], _('show difference from revision'), _('REV')),
5318 5319 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5319 5320 ] + walkopts + subrepoopts + formatteropts,
5320 5321 _('[OPTION]... [FILE]...'),
5321 5322 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5322 5323 helpbasic=True, inferrepo=True,
5323 5324 intents={INTENT_READONLY})
5324 5325 def status(ui, repo, *pats, **opts):
5325 5326 """show changed files in the working directory
5326 5327
5327 5328 Show status of files in the repository. If names are given, only
5328 5329 files that match are shown. Files that are clean or ignored or
5329 5330 the source of a copy/move operation, are not listed unless
5330 5331 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5331 5332 Unless options described with "show only ..." are given, the
5332 5333 options -mardu are used.
5333 5334
5334 5335 Option -q/--quiet hides untracked (unknown and ignored) files
5335 5336 unless explicitly requested with -u/--unknown or -i/--ignored.
5336 5337
5337 5338 .. note::
5338 5339
5339 5340 :hg:`status` may appear to disagree with diff if permissions have
5340 5341 changed or a merge has occurred. The standard diff format does
5341 5342 not report permission changes and diff only reports changes
5342 5343 relative to one merge parent.
5343 5344
5344 5345 If one revision is given, it is used as the base revision.
5345 5346 If two revisions are given, the differences between them are
5346 5347 shown. The --change option can also be used as a shortcut to list
5347 5348 the changed files of a revision from its first parent.
5348 5349
5349 5350 The codes used to show the status of files are::
5350 5351
5351 5352 M = modified
5352 5353 A = added
5353 5354 R = removed
5354 5355 C = clean
5355 5356 ! = missing (deleted by non-hg command, but still tracked)
5356 5357 ? = not tracked
5357 5358 I = ignored
5358 5359 = origin of the previous file (with --copies)
5359 5360
5360 5361 .. container:: verbose
5361 5362
5362 5363 The -t/--terse option abbreviates the output by showing only the directory
5363 5364 name if all the files in it share the same status. The option takes an
5364 5365 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5365 5366 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5366 5367 for 'ignored' and 'c' for clean.
5367 5368
5368 5369 It abbreviates only those statuses which are passed. Note that clean and
5369 5370 ignored files are not displayed with '--terse ic' unless the -c/--clean
5370 5371 and -i/--ignored options are also used.
5371 5372
5372 5373 The -v/--verbose option shows information when the repository is in an
5373 5374 unfinished merge, shelve, rebase state etc. You can have this behavior
5374 5375 turned on by default by enabling the ``commands.status.verbose`` option.
5375 5376
5376 5377 You can skip displaying some of these states by setting
5377 5378 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5378 5379 'histedit', 'merge', 'rebase', or 'unshelve'.
5379 5380
5380 5381 Template:
5381 5382
5382 5383 The following keywords are supported in addition to the common template
5383 5384 keywords and functions. See also :hg:`help templates`.
5384 5385
5385 5386 :path: String. Repository-absolute path of the file.
5386 5387 :source: String. Repository-absolute path of the file originated from.
5387 5388 Available if ``--copies`` is specified.
5388 5389 :status: String. Character denoting file's status.
5389 5390
5390 5391 Examples:
5391 5392
5392 5393 - show changes in the working directory relative to a
5393 5394 changeset::
5394 5395
5395 5396 hg status --rev 9353
5396 5397
5397 5398 - show changes in the working directory relative to the
5398 5399 current directory (see :hg:`help patterns` for more information)::
5399 5400
5400 5401 hg status re:
5401 5402
5402 5403 - show all changes including copies in an existing changeset::
5403 5404
5404 5405 hg status --copies --change 9353
5405 5406
5406 5407 - get a NUL separated list of added files, suitable for xargs::
5407 5408
5408 5409 hg status -an0
5409 5410
5410 5411 - show more information about the repository status, abbreviating
5411 5412 added, removed, modified, deleted, and untracked paths::
5412 5413
5413 5414 hg status -v -t mardu
5414 5415
5415 5416 Returns 0 on success.
5416 5417
5417 5418 """
5418 5419
5419 5420 opts = pycompat.byteskwargs(opts)
5420 5421 revs = opts.get('rev')
5421 5422 change = opts.get('change')
5422 5423 terse = opts.get('terse')
5423 5424 if terse is _NOTTERSE:
5424 5425 if revs:
5425 5426 terse = ''
5426 5427 else:
5427 5428 terse = ui.config('commands', 'status.terse')
5428 5429
5429 5430 if revs and change:
5430 5431 msg = _('cannot specify --rev and --change at the same time')
5431 5432 raise error.Abort(msg)
5432 5433 elif revs and terse:
5433 5434 msg = _('cannot use --terse with --rev')
5434 5435 raise error.Abort(msg)
5435 5436 elif change:
5436 5437 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5437 5438 ctx2 = scmutil.revsingle(repo, change, None)
5438 5439 ctx1 = ctx2.p1()
5439 5440 else:
5440 5441 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5441 5442 ctx1, ctx2 = scmutil.revpair(repo, revs)
5442 5443
5443 5444 forcerelativevalue = None
5444 5445 if ui.hasconfig('commands', 'status.relative'):
5445 5446 forcerelativevalue = ui.configbool('commands', 'status.relative')
5446 5447 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats),
5447 5448 forcerelativevalue=forcerelativevalue)
5448 5449
5449 5450 if opts.get('print0'):
5450 5451 end = '\0'
5451 5452 else:
5452 5453 end = '\n'
5453 5454 copy = {}
5454 5455 states = 'modified added removed deleted unknown ignored clean'.split()
5455 5456 show = [k for k in states if opts.get(k)]
5456 5457 if opts.get('all'):
5457 5458 show += ui.quiet and (states[:4] + ['clean']) or states
5458 5459
5459 5460 if not show:
5460 5461 if ui.quiet:
5461 5462 show = states[:4]
5462 5463 else:
5463 5464 show = states[:5]
5464 5465
5465 5466 m = scmutil.match(ctx2, pats, opts)
5466 5467 if terse:
5467 5468 # we need to compute clean and unknown to terse
5468 5469 stat = repo.status(ctx1.node(), ctx2.node(), m,
5469 5470 'ignored' in show or 'i' in terse,
5470 5471 clean=True, unknown=True,
5471 5472 listsubrepos=opts.get('subrepos'))
5472 5473
5473 5474 stat = cmdutil.tersedir(stat, terse)
5474 5475 else:
5475 5476 stat = repo.status(ctx1.node(), ctx2.node(), m,
5476 5477 'ignored' in show, 'clean' in show,
5477 5478 'unknown' in show, opts.get('subrepos'))
5478 5479
5479 5480 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5480 5481
5481 5482 if (opts.get('all') or opts.get('copies')
5482 5483 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5483 5484 copy = copies.pathcopies(ctx1, ctx2, m)
5484 5485
5485 5486 ui.pager('status')
5486 5487 fm = ui.formatter('status', opts)
5487 5488 fmt = '%s' + end
5488 5489 showchar = not opts.get('no_status')
5489 5490
5490 5491 for state, char, files in changestates:
5491 5492 if state in show:
5492 5493 label = 'status.' + state
5493 5494 for f in files:
5494 5495 fm.startitem()
5495 5496 fm.context(ctx=ctx2)
5496 5497 fm.data(path=f)
5497 5498 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5498 5499 fm.plain(fmt % uipathfn(f), label=label)
5499 5500 if f in copy:
5500 5501 fm.data(source=copy[f])
5501 5502 fm.plain((' %s' + end) % uipathfn(copy[f]),
5502 5503 label='status.copied')
5503 5504
5504 5505 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5505 5506 and not ui.plain()):
5506 5507 cmdutil.morestatus(repo, fm)
5507 5508 fm.end()
5508 5509
5509 5510 @command('summary|sum',
5510 5511 [('', 'remote', None, _('check for push and pull'))],
5511 5512 '[--remote]',
5512 5513 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5513 5514 helpbasic=True,
5514 5515 intents={INTENT_READONLY})
5515 5516 def summary(ui, repo, **opts):
5516 5517 """summarize working directory state
5517 5518
5518 5519 This generates a brief summary of the working directory state,
5519 5520 including parents, branch, commit status, phase and available updates.
5520 5521
5521 5522 With the --remote option, this will check the default paths for
5522 5523 incoming and outgoing changes. This can be time-consuming.
5523 5524
5524 5525 Returns 0 on success.
5525 5526 """
5526 5527
5527 5528 opts = pycompat.byteskwargs(opts)
5528 5529 ui.pager('summary')
5529 5530 ctx = repo[None]
5530 5531 parents = ctx.parents()
5531 5532 pnode = parents[0].node()
5532 5533 marks = []
5533 5534
5534 5535 try:
5535 5536 ms = mergemod.mergestate.read(repo)
5536 5537 except error.UnsupportedMergeRecords as e:
5537 5538 s = ' '.join(e.recordtypes)
5538 5539 ui.warn(
5539 5540 _('warning: merge state has unsupported record types: %s\n') % s)
5540 5541 unresolved = []
5541 5542 else:
5542 5543 unresolved = list(ms.unresolved())
5543 5544
5544 5545 for p in parents:
5545 5546 # label with log.changeset (instead of log.parent) since this
5546 5547 # shows a working directory parent *changeset*:
5547 5548 # i18n: column positioning for "hg summary"
5548 5549 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5549 5550 label=logcmdutil.changesetlabels(p))
5550 5551 ui.write(' '.join(p.tags()), label='log.tag')
5551 5552 if p.bookmarks():
5552 5553 marks.extend(p.bookmarks())
5553 5554 if p.rev() == -1:
5554 5555 if not len(repo):
5555 5556 ui.write(_(' (empty repository)'))
5556 5557 else:
5557 5558 ui.write(_(' (no revision checked out)'))
5558 5559 if p.obsolete():
5559 5560 ui.write(_(' (obsolete)'))
5560 5561 if p.isunstable():
5561 5562 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5562 5563 for instability in p.instabilities())
5563 5564 ui.write(' ('
5564 5565 + ', '.join(instabilities)
5565 5566 + ')')
5566 5567 ui.write('\n')
5567 5568 if p.description():
5568 5569 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5569 5570 label='log.summary')
5570 5571
5571 5572 branch = ctx.branch()
5572 5573 bheads = repo.branchheads(branch)
5573 5574 # i18n: column positioning for "hg summary"
5574 5575 m = _('branch: %s\n') % branch
5575 5576 if branch != 'default':
5576 5577 ui.write(m, label='log.branch')
5577 5578 else:
5578 5579 ui.status(m, label='log.branch')
5579 5580
5580 5581 if marks:
5581 5582 active = repo._activebookmark
5582 5583 # i18n: column positioning for "hg summary"
5583 5584 ui.write(_('bookmarks:'), label='log.bookmark')
5584 5585 if active is not None:
5585 5586 if active in marks:
5586 5587 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5587 5588 marks.remove(active)
5588 5589 else:
5589 5590 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5590 5591 for m in marks:
5591 5592 ui.write(' ' + m, label='log.bookmark')
5592 5593 ui.write('\n', label='log.bookmark')
5593 5594
5594 5595 status = repo.status(unknown=True)
5595 5596
5596 5597 c = repo.dirstate.copies()
5597 5598 copied, renamed = [], []
5598 5599 for d, s in c.iteritems():
5599 5600 if s in status.removed:
5600 5601 status.removed.remove(s)
5601 5602 renamed.append(d)
5602 5603 else:
5603 5604 copied.append(d)
5604 5605 if d in status.added:
5605 5606 status.added.remove(d)
5606 5607
5607 5608 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5608 5609
5609 5610 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5610 5611 (ui.label(_('%d added'), 'status.added'), status.added),
5611 5612 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5612 5613 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5613 5614 (ui.label(_('%d copied'), 'status.copied'), copied),
5614 5615 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5615 5616 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5616 5617 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5617 5618 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5618 5619 t = []
5619 5620 for l, s in labels:
5620 5621 if s:
5621 5622 t.append(l % len(s))
5622 5623
5623 5624 t = ', '.join(t)
5624 5625 cleanworkdir = False
5625 5626
5626 5627 if repo.vfs.exists('graftstate'):
5627 5628 t += _(' (graft in progress)')
5628 5629 if repo.vfs.exists('updatestate'):
5629 5630 t += _(' (interrupted update)')
5630 5631 elif len(parents) > 1:
5631 5632 t += _(' (merge)')
5632 5633 elif branch != parents[0].branch():
5633 5634 t += _(' (new branch)')
5634 5635 elif (parents[0].closesbranch() and
5635 5636 pnode in repo.branchheads(branch, closed=True)):
5636 5637 t += _(' (head closed)')
5637 5638 elif not (status.modified or status.added or status.removed or renamed or
5638 5639 copied or subs):
5639 5640 t += _(' (clean)')
5640 5641 cleanworkdir = True
5641 5642 elif pnode not in bheads:
5642 5643 t += _(' (new branch head)')
5643 5644
5644 5645 if parents:
5645 5646 pendingphase = max(p.phase() for p in parents)
5646 5647 else:
5647 5648 pendingphase = phases.public
5648 5649
5649 5650 if pendingphase > phases.newcommitphase(ui):
5650 5651 t += ' (%s)' % phases.phasenames[pendingphase]
5651 5652
5652 5653 if cleanworkdir:
5653 5654 # i18n: column positioning for "hg summary"
5654 5655 ui.status(_('commit: %s\n') % t.strip())
5655 5656 else:
5656 5657 # i18n: column positioning for "hg summary"
5657 5658 ui.write(_('commit: %s\n') % t.strip())
5658 5659
5659 5660 # all ancestors of branch heads - all ancestors of parent = new csets
5660 5661 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5661 5662 bheads))
5662 5663
5663 5664 if new == 0:
5664 5665 # i18n: column positioning for "hg summary"
5665 5666 ui.status(_('update: (current)\n'))
5666 5667 elif pnode not in bheads:
5667 5668 # i18n: column positioning for "hg summary"
5668 5669 ui.write(_('update: %d new changesets (update)\n') % new)
5669 5670 else:
5670 5671 # i18n: column positioning for "hg summary"
5671 5672 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5672 5673 (new, len(bheads)))
5673 5674
5674 5675 t = []
5675 5676 draft = len(repo.revs('draft()'))
5676 5677 if draft:
5677 5678 t.append(_('%d draft') % draft)
5678 5679 secret = len(repo.revs('secret()'))
5679 5680 if secret:
5680 5681 t.append(_('%d secret') % secret)
5681 5682
5682 5683 if draft or secret:
5683 5684 ui.status(_('phases: %s\n') % ', '.join(t))
5684 5685
5685 5686 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5686 5687 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5687 5688 numtrouble = len(repo.revs(trouble + "()"))
5688 5689 # We write all the possibilities to ease translation
5689 5690 troublemsg = {
5690 5691 "orphan": _("orphan: %d changesets"),
5691 5692 "contentdivergent": _("content-divergent: %d changesets"),
5692 5693 "phasedivergent": _("phase-divergent: %d changesets"),
5693 5694 }
5694 5695 if numtrouble > 0:
5695 5696 ui.status(troublemsg[trouble] % numtrouble + "\n")
5696 5697
5697 5698 cmdutil.summaryhooks(ui, repo)
5698 5699
5699 5700 if opts.get('remote'):
5700 5701 needsincoming, needsoutgoing = True, True
5701 5702 else:
5702 5703 needsincoming, needsoutgoing = False, False
5703 5704 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5704 5705 if i:
5705 5706 needsincoming = True
5706 5707 if o:
5707 5708 needsoutgoing = True
5708 5709 if not needsincoming and not needsoutgoing:
5709 5710 return
5710 5711
5711 5712 def getincoming():
5712 5713 source, branches = hg.parseurl(ui.expandpath('default'))
5713 5714 sbranch = branches[0]
5714 5715 try:
5715 5716 other = hg.peer(repo, {}, source)
5716 5717 except error.RepoError:
5717 5718 if opts.get('remote'):
5718 5719 raise
5719 5720 return source, sbranch, None, None, None
5720 5721 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5721 5722 if revs:
5722 5723 revs = [other.lookup(rev) for rev in revs]
5723 5724 ui.debug('comparing with %s\n' % util.hidepassword(source))
5724 5725 repo.ui.pushbuffer()
5725 5726 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5726 5727 repo.ui.popbuffer()
5727 5728 return source, sbranch, other, commoninc, commoninc[1]
5728 5729
5729 5730 if needsincoming:
5730 5731 source, sbranch, sother, commoninc, incoming = getincoming()
5731 5732 else:
5732 5733 source = sbranch = sother = commoninc = incoming = None
5733 5734
5734 5735 def getoutgoing():
5735 5736 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5736 5737 dbranch = branches[0]
5737 5738 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5738 5739 if source != dest:
5739 5740 try:
5740 5741 dother = hg.peer(repo, {}, dest)
5741 5742 except error.RepoError:
5742 5743 if opts.get('remote'):
5743 5744 raise
5744 5745 return dest, dbranch, None, None
5745 5746 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5746 5747 elif sother is None:
5747 5748 # there is no explicit destination peer, but source one is invalid
5748 5749 return dest, dbranch, None, None
5749 5750 else:
5750 5751 dother = sother
5751 5752 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5752 5753 common = None
5753 5754 else:
5754 5755 common = commoninc
5755 5756 if revs:
5756 5757 revs = [repo.lookup(rev) for rev in revs]
5757 5758 repo.ui.pushbuffer()
5758 5759 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5759 5760 commoninc=common)
5760 5761 repo.ui.popbuffer()
5761 5762 return dest, dbranch, dother, outgoing
5762 5763
5763 5764 if needsoutgoing:
5764 5765 dest, dbranch, dother, outgoing = getoutgoing()
5765 5766 else:
5766 5767 dest = dbranch = dother = outgoing = None
5767 5768
5768 5769 if opts.get('remote'):
5769 5770 t = []
5770 5771 if incoming:
5771 5772 t.append(_('1 or more incoming'))
5772 5773 o = outgoing.missing
5773 5774 if o:
5774 5775 t.append(_('%d outgoing') % len(o))
5775 5776 other = dother or sother
5776 5777 if 'bookmarks' in other.listkeys('namespaces'):
5777 5778 counts = bookmarks.summary(repo, other)
5778 5779 if counts[0] > 0:
5779 5780 t.append(_('%d incoming bookmarks') % counts[0])
5780 5781 if counts[1] > 0:
5781 5782 t.append(_('%d outgoing bookmarks') % counts[1])
5782 5783
5783 5784 if t:
5784 5785 # i18n: column positioning for "hg summary"
5785 5786 ui.write(_('remote: %s\n') % (', '.join(t)))
5786 5787 else:
5787 5788 # i18n: column positioning for "hg summary"
5788 5789 ui.status(_('remote: (synced)\n'))
5789 5790
5790 5791 cmdutil.summaryremotehooks(ui, repo, opts,
5791 5792 ((source, sbranch, sother, commoninc),
5792 5793 (dest, dbranch, dother, outgoing)))
5793 5794
5794 5795 @command('tag',
5795 5796 [('f', 'force', None, _('force tag')),
5796 5797 ('l', 'local', None, _('make the tag local')),
5797 5798 ('r', 'rev', '', _('revision to tag'), _('REV')),
5798 5799 ('', 'remove', None, _('remove a tag')),
5799 5800 # -l/--local is already there, commitopts cannot be used
5800 5801 ('e', 'edit', None, _('invoke editor on commit messages')),
5801 5802 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5802 5803 ] + commitopts2,
5803 5804 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
5804 5805 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
5805 5806 def tag(ui, repo, name1, *names, **opts):
5806 5807 """add one or more tags for the current or given revision
5807 5808
5808 5809 Name a particular revision using <name>.
5809 5810
5810 5811 Tags are used to name particular revisions of the repository and are
5811 5812 very useful to compare different revisions, to go back to significant
5812 5813 earlier versions or to mark branch points as releases, etc. Changing
5813 5814 an existing tag is normally disallowed; use -f/--force to override.
5814 5815
5815 5816 If no revision is given, the parent of the working directory is
5816 5817 used.
5817 5818
5818 5819 To facilitate version control, distribution, and merging of tags,
5819 5820 they are stored as a file named ".hgtags" which is managed similarly
5820 5821 to other project files and can be hand-edited if necessary. This
5821 5822 also means that tagging creates a new commit. The file
5822 5823 ".hg/localtags" is used for local tags (not shared among
5823 5824 repositories).
5824 5825
5825 5826 Tag commits are usually made at the head of a branch. If the parent
5826 5827 of the working directory is not a branch head, :hg:`tag` aborts; use
5827 5828 -f/--force to force the tag commit to be based on a non-head
5828 5829 changeset.
5829 5830
5830 5831 See :hg:`help dates` for a list of formats valid for -d/--date.
5831 5832
5832 5833 Since tag names have priority over branch names during revision
5833 5834 lookup, using an existing branch name as a tag name is discouraged.
5834 5835
5835 5836 Returns 0 on success.
5836 5837 """
5837 5838 opts = pycompat.byteskwargs(opts)
5838 5839 with repo.wlock(), repo.lock():
5839 5840 rev_ = "."
5840 5841 names = [t.strip() for t in (name1,) + names]
5841 5842 if len(names) != len(set(names)):
5842 5843 raise error.Abort(_('tag names must be unique'))
5843 5844 for n in names:
5844 5845 scmutil.checknewlabel(repo, n, 'tag')
5845 5846 if not n:
5846 5847 raise error.Abort(_('tag names cannot consist entirely of '
5847 5848 'whitespace'))
5848 5849 if opts.get('rev') and opts.get('remove'):
5849 5850 raise error.Abort(_("--rev and --remove are incompatible"))
5850 5851 if opts.get('rev'):
5851 5852 rev_ = opts['rev']
5852 5853 message = opts.get('message')
5853 5854 if opts.get('remove'):
5854 5855 if opts.get('local'):
5855 5856 expectedtype = 'local'
5856 5857 else:
5857 5858 expectedtype = 'global'
5858 5859
5859 5860 for n in names:
5860 5861 if repo.tagtype(n) == 'global':
5861 5862 alltags = tagsmod.findglobaltags(ui, repo)
5862 5863 if alltags[n][0] == nullid:
5863 5864 raise error.Abort(_("tag '%s' is already removed") % n)
5864 5865 if not repo.tagtype(n):
5865 5866 raise error.Abort(_("tag '%s' does not exist") % n)
5866 5867 if repo.tagtype(n) != expectedtype:
5867 5868 if expectedtype == 'global':
5868 5869 raise error.Abort(_("tag '%s' is not a global tag") % n)
5869 5870 else:
5870 5871 raise error.Abort(_("tag '%s' is not a local tag") % n)
5871 5872 rev_ = 'null'
5872 5873 if not message:
5873 5874 # we don't translate commit messages
5874 5875 message = 'Removed tag %s' % ', '.join(names)
5875 5876 elif not opts.get('force'):
5876 5877 for n in names:
5877 5878 if n in repo.tags():
5878 5879 raise error.Abort(_("tag '%s' already exists "
5879 5880 "(use -f to force)") % n)
5880 5881 if not opts.get('local'):
5881 5882 p1, p2 = repo.dirstate.parents()
5882 5883 if p2 != nullid:
5883 5884 raise error.Abort(_('uncommitted merge'))
5884 5885 bheads = repo.branchheads()
5885 5886 if not opts.get('force') and bheads and p1 not in bheads:
5886 5887 raise error.Abort(_('working directory is not at a branch head '
5887 5888 '(use -f to force)'))
5888 5889 node = scmutil.revsingle(repo, rev_).node()
5889 5890
5890 5891 if not message:
5891 5892 # we don't translate commit messages
5892 5893 message = ('Added tag %s for changeset %s' %
5893 5894 (', '.join(names), short(node)))
5894 5895
5895 5896 date = opts.get('date')
5896 5897 if date:
5897 5898 date = dateutil.parsedate(date)
5898 5899
5899 5900 if opts.get('remove'):
5900 5901 editform = 'tag.remove'
5901 5902 else:
5902 5903 editform = 'tag.add'
5903 5904 editor = cmdutil.getcommiteditor(editform=editform,
5904 5905 **pycompat.strkwargs(opts))
5905 5906
5906 5907 # don't allow tagging the null rev
5907 5908 if (not opts.get('remove') and
5908 5909 scmutil.revsingle(repo, rev_).rev() == nullrev):
5909 5910 raise error.Abort(_("cannot tag null revision"))
5910 5911
5911 5912 tagsmod.tag(repo, names, node, message, opts.get('local'),
5912 5913 opts.get('user'), date, editor=editor)
5913 5914
5914 5915 @command(
5915 5916 'tags', formatteropts, '',
5916 5917 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5917 5918 intents={INTENT_READONLY})
5918 5919 def tags(ui, repo, **opts):
5919 5920 """list repository tags
5920 5921
5921 5922 This lists both regular and local tags. When the -v/--verbose
5922 5923 switch is used, a third column "local" is printed for local tags.
5923 5924 When the -q/--quiet switch is used, only the tag name is printed.
5924 5925
5925 5926 .. container:: verbose
5926 5927
5927 5928 Template:
5928 5929
5929 5930 The following keywords are supported in addition to the common template
5930 5931 keywords and functions such as ``{tag}``. See also
5931 5932 :hg:`help templates`.
5932 5933
5933 5934 :type: String. ``local`` for local tags.
5934 5935
5935 5936 Returns 0 on success.
5936 5937 """
5937 5938
5938 5939 opts = pycompat.byteskwargs(opts)
5939 5940 ui.pager('tags')
5940 5941 fm = ui.formatter('tags', opts)
5941 5942 hexfunc = fm.hexfunc
5942 5943
5943 5944 for t, n in reversed(repo.tagslist()):
5944 5945 hn = hexfunc(n)
5945 5946 label = 'tags.normal'
5946 5947 tagtype = ''
5947 5948 if repo.tagtype(t) == 'local':
5948 5949 label = 'tags.local'
5949 5950 tagtype = 'local'
5950 5951
5951 5952 fm.startitem()
5952 5953 fm.context(repo=repo)
5953 5954 fm.write('tag', '%s', t, label=label)
5954 5955 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5955 5956 fm.condwrite(not ui.quiet, 'rev node', fmt,
5956 5957 repo.changelog.rev(n), hn, label=label)
5957 5958 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5958 5959 tagtype, label=label)
5959 5960 fm.plain('\n')
5960 5961 fm.end()
5961 5962
5962 5963 @command('tip',
5963 5964 [('p', 'patch', None, _('show patch')),
5964 5965 ('g', 'git', None, _('use git extended diff format')),
5965 5966 ] + templateopts,
5966 5967 _('[-p] [-g]'),
5967 5968 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
5968 5969 def tip(ui, repo, **opts):
5969 5970 """show the tip revision (DEPRECATED)
5970 5971
5971 5972 The tip revision (usually just called the tip) is the changeset
5972 5973 most recently added to the repository (and therefore the most
5973 5974 recently changed head).
5974 5975
5975 5976 If you have just made a commit, that commit will be the tip. If
5976 5977 you have just pulled changes from another repository, the tip of
5977 5978 that repository becomes the current tip. The "tip" tag is special
5978 5979 and cannot be renamed or assigned to a different changeset.
5979 5980
5980 5981 This command is deprecated, please use :hg:`heads` instead.
5981 5982
5982 5983 Returns 0 on success.
5983 5984 """
5984 5985 opts = pycompat.byteskwargs(opts)
5985 5986 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5986 5987 displayer.show(repo['tip'])
5987 5988 displayer.close()
5988 5989
5989 5990 @command('unbundle',
5990 5991 [('u', 'update', None,
5991 5992 _('update to new branch head if changesets were unbundled'))],
5992 5993 _('[-u] FILE...'),
5993 5994 helpcategory=command.CATEGORY_IMPORT_EXPORT)
5994 5995 def unbundle(ui, repo, fname1, *fnames, **opts):
5995 5996 """apply one or more bundle files
5996 5997
5997 5998 Apply one or more bundle files generated by :hg:`bundle`.
5998 5999
5999 6000 Returns 0 on success, 1 if an update has unresolved files.
6000 6001 """
6001 6002 fnames = (fname1,) + fnames
6002 6003
6003 6004 with repo.lock():
6004 6005 for fname in fnames:
6005 6006 f = hg.openpath(ui, fname)
6006 6007 gen = exchange.readbundle(ui, f, fname)
6007 6008 if isinstance(gen, streamclone.streamcloneapplier):
6008 6009 raise error.Abort(
6009 6010 _('packed bundles cannot be applied with '
6010 6011 '"hg unbundle"'),
6011 6012 hint=_('use "hg debugapplystreamclonebundle"'))
6012 6013 url = 'bundle:' + fname
6013 6014 try:
6014 6015 txnname = 'unbundle'
6015 6016 if not isinstance(gen, bundle2.unbundle20):
6016 6017 txnname = 'unbundle\n%s' % util.hidepassword(url)
6017 6018 with repo.transaction(txnname) as tr:
6018 6019 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6019 6020 url=url)
6020 6021 except error.BundleUnknownFeatureError as exc:
6021 6022 raise error.Abort(
6022 6023 _('%s: unknown bundle feature, %s') % (fname, exc),
6023 6024 hint=_("see https://mercurial-scm.org/"
6024 6025 "wiki/BundleFeature for more "
6025 6026 "information"))
6026 6027 modheads = bundle2.combinechangegroupresults(op)
6027 6028
6028 6029 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
6029 6030
6030 6031 @command('update|up|checkout|co',
6031 6032 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6032 6033 ('c', 'check', None, _('require clean working directory')),
6033 6034 ('m', 'merge', None, _('merge uncommitted changes')),
6034 6035 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6035 6036 ('r', 'rev', '', _('revision'), _('REV'))
6036 6037 ] + mergetoolopts,
6037 6038 _('[-C|-c|-m] [-d DATE] [[-r] REV]'),
6038 6039 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6039 6040 helpbasic=True)
6040 6041 def update(ui, repo, node=None, **opts):
6041 6042 """update working directory (or switch revisions)
6042 6043
6043 6044 Update the repository's working directory to the specified
6044 6045 changeset. If no changeset is specified, update to the tip of the
6045 6046 current named branch and move the active bookmark (see :hg:`help
6046 6047 bookmarks`).
6047 6048
6048 6049 Update sets the working directory's parent revision to the specified
6049 6050 changeset (see :hg:`help parents`).
6050 6051
6051 6052 If the changeset is not a descendant or ancestor of the working
6052 6053 directory's parent and there are uncommitted changes, the update is
6053 6054 aborted. With the -c/--check option, the working directory is checked
6054 6055 for uncommitted changes; if none are found, the working directory is
6055 6056 updated to the specified changeset.
6056 6057
6057 6058 .. container:: verbose
6058 6059
6059 6060 The -C/--clean, -c/--check, and -m/--merge options control what
6060 6061 happens if the working directory contains uncommitted changes.
6061 6062 At most of one of them can be specified.
6062 6063
6063 6064 1. If no option is specified, and if
6064 6065 the requested changeset is an ancestor or descendant of
6065 6066 the working directory's parent, the uncommitted changes
6066 6067 are merged into the requested changeset and the merged
6067 6068 result is left uncommitted. If the requested changeset is
6068 6069 not an ancestor or descendant (that is, it is on another
6069 6070 branch), the update is aborted and the uncommitted changes
6070 6071 are preserved.
6071 6072
6072 6073 2. With the -m/--merge option, the update is allowed even if the
6073 6074 requested changeset is not an ancestor or descendant of
6074 6075 the working directory's parent.
6075 6076
6076 6077 3. With the -c/--check option, the update is aborted and the
6077 6078 uncommitted changes are preserved.
6078 6079
6079 6080 4. With the -C/--clean option, uncommitted changes are discarded and
6080 6081 the working directory is updated to the requested changeset.
6081 6082
6082 6083 To cancel an uncommitted merge (and lose your changes), use
6083 6084 :hg:`merge --abort`.
6084 6085
6085 6086 Use null as the changeset to remove the working directory (like
6086 6087 :hg:`clone -U`).
6087 6088
6088 6089 If you want to revert just one file to an older revision, use
6089 6090 :hg:`revert [-r REV] NAME`.
6090 6091
6091 6092 See :hg:`help dates` for a list of formats valid for -d/--date.
6092 6093
6093 6094 Returns 0 on success, 1 if there are unresolved files.
6094 6095 """
6095 6096 rev = opts.get(r'rev')
6096 6097 date = opts.get(r'date')
6097 6098 clean = opts.get(r'clean')
6098 6099 check = opts.get(r'check')
6099 6100 merge = opts.get(r'merge')
6100 6101 if rev and node:
6101 6102 raise error.Abort(_("please specify just one revision"))
6102 6103
6103 6104 if ui.configbool('commands', 'update.requiredest'):
6104 6105 if not node and not rev and not date:
6105 6106 raise error.Abort(_('you must specify a destination'),
6106 6107 hint=_('for example: hg update ".::"'))
6107 6108
6108 6109 if rev is None or rev == '':
6109 6110 rev = node
6110 6111
6111 6112 if date and rev is not None:
6112 6113 raise error.Abort(_("you can't specify a revision and a date"))
6113 6114
6114 6115 if len([x for x in (clean, check, merge) if x]) > 1:
6115 6116 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
6116 6117 "or -m/--merge"))
6117 6118
6118 6119 updatecheck = None
6119 6120 if check:
6120 6121 updatecheck = 'abort'
6121 6122 elif merge:
6122 6123 updatecheck = 'none'
6123 6124
6124 6125 with repo.wlock():
6125 6126 cmdutil.clearunfinished(repo)
6126 6127
6127 6128 if date:
6128 6129 rev = cmdutil.finddate(ui, repo, date)
6129 6130
6130 6131 # if we defined a bookmark, we have to remember the original name
6131 6132 brev = rev
6132 6133 if rev:
6133 6134 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
6134 6135 ctx = scmutil.revsingle(repo, rev, default=None)
6135 6136 rev = ctx.rev()
6136 6137 hidden = ctx.hidden()
6137 6138 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
6138 6139 with ui.configoverride(overrides, 'update'):
6139 6140 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
6140 6141 updatecheck=updatecheck)
6141 6142 if hidden:
6142 6143 ctxstr = ctx.hex()[:12]
6143 6144 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
6144 6145
6145 6146 if ctx.obsolete():
6146 6147 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
6147 6148 ui.warn("(%s)\n" % obsfatemsg)
6148 6149 return ret
6149 6150
6150 @command('verify', [], helpcategory=command.CATEGORY_MAINTENANCE)
6151 def verify(ui, repo):
6151 @command('verify',
6152 [('', 'full', False, 'perform more checks (EXPERIMENTAL)')],
6153 helpcategory=command.CATEGORY_MAINTENANCE)
6154 def verify(ui, repo, **opts):
6152 6155 """verify the integrity of the repository
6153 6156
6154 6157 Verify the integrity of the current repository.
6155 6158
6156 6159 This will perform an extensive check of the repository's
6157 6160 integrity, validating the hashes and checksums of each entry in
6158 6161 the changelog, manifest, and tracked files, as well as the
6159 6162 integrity of their crosslinks and indices.
6160 6163
6161 6164 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6162 6165 for more information about recovery from corruption of the
6163 6166 repository.
6164 6167
6165 6168 Returns 0 on success, 1 if errors are encountered.
6166 6169 """
6167 return hg.verify(repo)
6170 level = None
6171 if opts['full']:
6172 level = verifymod.VERIFY_FULL
6173 return hg.verify(repo, level)
6168 6174
6169 6175 @command(
6170 6176 'version', [] + formatteropts, helpcategory=command.CATEGORY_HELP,
6171 6177 norepo=True, intents={INTENT_READONLY})
6172 6178 def version_(ui, **opts):
6173 6179 """output version and copyright information
6174 6180
6175 6181 .. container:: verbose
6176 6182
6177 6183 Template:
6178 6184
6179 6185 The following keywords are supported. See also :hg:`help templates`.
6180 6186
6181 6187 :extensions: List of extensions.
6182 6188 :ver: String. Version number.
6183 6189
6184 6190 And each entry of ``{extensions}`` provides the following sub-keywords
6185 6191 in addition to ``{ver}``.
6186 6192
6187 6193 :bundled: Boolean. True if included in the release.
6188 6194 :name: String. Extension name.
6189 6195 """
6190 6196 opts = pycompat.byteskwargs(opts)
6191 6197 if ui.verbose:
6192 6198 ui.pager('version')
6193 6199 fm = ui.formatter("version", opts)
6194 6200 fm.startitem()
6195 6201 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6196 6202 util.version())
6197 6203 license = _(
6198 6204 "(see https://mercurial-scm.org for more information)\n"
6199 6205 "\nCopyright (C) 2005-2019 Matt Mackall and others\n"
6200 6206 "This is free software; see the source for copying conditions. "
6201 6207 "There is NO\nwarranty; "
6202 6208 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6203 6209 )
6204 6210 if not ui.quiet:
6205 6211 fm.plain(license)
6206 6212
6207 6213 if ui.verbose:
6208 6214 fm.plain(_("\nEnabled extensions:\n\n"))
6209 6215 # format names and versions into columns
6210 6216 names = []
6211 6217 vers = []
6212 6218 isinternals = []
6213 6219 for name, module in extensions.extensions():
6214 6220 names.append(name)
6215 6221 vers.append(extensions.moduleversion(module) or None)
6216 6222 isinternals.append(extensions.ismoduleinternal(module))
6217 6223 fn = fm.nested("extensions", tmpl='{name}\n')
6218 6224 if names:
6219 6225 namefmt = " %%-%ds " % max(len(n) for n in names)
6220 6226 places = [_("external"), _("internal")]
6221 6227 for n, v, p in zip(names, vers, isinternals):
6222 6228 fn.startitem()
6223 6229 fn.condwrite(ui.verbose, "name", namefmt, n)
6224 6230 if ui.verbose:
6225 6231 fn.plain("%s " % places[p])
6226 6232 fn.data(bundled=p)
6227 6233 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6228 6234 if ui.verbose:
6229 6235 fn.plain("\n")
6230 6236 fn.end()
6231 6237 fm.end()
6232 6238
6233 6239 def loadcmdtable(ui, name, cmdtable):
6234 6240 """Load command functions from specified cmdtable
6235 6241 """
6236 6242 cmdtable = cmdtable.copy()
6237 6243 for cmd in list(cmdtable):
6238 6244 if not cmd.startswith('^'):
6239 6245 continue
6240 6246 ui.deprecwarn("old-style command registration '%s' in extension '%s'"
6241 6247 % (cmd, name), '4.8')
6242 6248 entry = cmdtable.pop(cmd)
6243 6249 entry[0].helpbasic = True
6244 6250 cmdtable[cmd[1:]] = entry
6245 6251
6246 6252 overrides = [cmd for cmd in cmdtable if cmd in table]
6247 6253 if overrides:
6248 6254 ui.warn(_("extension '%s' overrides commands: %s\n")
6249 6255 % (name, " ".join(overrides)))
6250 6256 table.update(cmdtable)
@@ -1,541 +1,542 b''
1 1 # verify.py - repository integrity checking for Mercurial
2 2 #
3 3 # Copyright 2006, 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 os
11 11
12 12 from .i18n import _
13 13 from .node import (
14 14 nullid,
15 15 short,
16 16 )
17 17
18 18 from . import (
19 19 error,
20 20 pycompat,
21 21 revlog,
22 22 util,
23 23 )
24 24
25 25 VERIFY_DEFAULT = 0
26 VERIFY_FULL = 1
26 27
27 28 def verify(repo, level=None):
28 29 with repo.lock():
29 30 v = verifier(repo, level)
30 31 return v.verify()
31 32
32 33 def _normpath(f):
33 34 # under hg < 2.4, convert didn't sanitize paths properly, so a
34 35 # converted repo may contain repeated slashes
35 36 while '//' in f:
36 37 f = f.replace('//', '/')
37 38 return f
38 39
39 40 class verifier(object):
40 41 def __init__(self, repo, level=None):
41 42 self.repo = repo.unfiltered()
42 43 self.ui = repo.ui
43 44 self.match = repo.narrowmatch()
44 45 if level is None:
45 46 level = VERIFY_DEFAULT
46 47 self._level = level
47 48 self.badrevs = set()
48 49 self.errors = 0
49 50 self.warnings = 0
50 51 self.havecl = len(repo.changelog) > 0
51 52 self.havemf = len(repo.manifestlog.getstorage(b'')) > 0
52 53 self.revlogv1 = repo.changelog.version != revlog.REVLOGV0
53 54 self.lrugetctx = util.lrucachefunc(repo.__getitem__)
54 55 self.refersmf = False
55 56 self.fncachewarned = False
56 57 # developer config: verify.skipflags
57 58 self.skipflags = repo.ui.configint('verify', 'skipflags')
58 59 self.warnorphanstorefiles = True
59 60
60 61 def _warn(self, msg):
61 62 """record a "warning" level issue"""
62 63 self.ui.warn(msg + "\n")
63 64 self.warnings += 1
64 65
65 66 def _err(self, linkrev, msg, filename=None):
66 67 """record a "error" level issue"""
67 68 if linkrev is not None:
68 69 self.badrevs.add(linkrev)
69 70 linkrev = "%d" % linkrev
70 71 else:
71 72 linkrev = '?'
72 73 msg = "%s: %s" % (linkrev, msg)
73 74 if filename:
74 75 msg = "%s@%s" % (filename, msg)
75 76 self.ui.warn(" " + msg + "\n")
76 77 self.errors += 1
77 78
78 79 def _exc(self, linkrev, msg, inst, filename=None):
79 80 """record exception raised during the verify process"""
80 81 fmsg = pycompat.bytestr(inst)
81 82 if not fmsg:
82 83 fmsg = pycompat.byterepr(inst)
83 84 self._err(linkrev, "%s: %s" % (msg, fmsg), filename)
84 85
85 86 def _checkrevlog(self, obj, name, linkrev):
86 87 """verify high level property of a revlog
87 88
88 89 - revlog is present,
89 90 - revlog is non-empty,
90 91 - sizes (index and data) are correct,
91 92 - revlog's format version is correct.
92 93 """
93 94 if not len(obj) and (self.havecl or self.havemf):
94 95 self._err(linkrev, _("empty or missing %s") % name)
95 96 return
96 97
97 98 d = obj.checksize()
98 99 if d[0]:
99 100 self.err(None, _("data length off by %d bytes") % d[0], name)
100 101 if d[1]:
101 102 self.err(None, _("index contains %d extra bytes") % d[1], name)
102 103
103 104 if obj.version != revlog.REVLOGV0:
104 105 if not self.revlogv1:
105 106 self._warn(_("warning: `%s' uses revlog format 1") % name)
106 107 elif self.revlogv1:
107 108 self._warn(_("warning: `%s' uses revlog format 0") % name)
108 109
109 110 def _checkentry(self, obj, i, node, seen, linkrevs, f):
110 111 """verify a single revlog entry
111 112
112 113 arguments are:
113 114 - obj: the source revlog
114 115 - i: the revision number
115 116 - node: the revision node id
116 117 - seen: nodes previously seen for this revlog
117 118 - linkrevs: [changelog-revisions] introducing "node"
118 119 - f: string label ("changelog", "manifest", or filename)
119 120
120 121 Performs the following checks:
121 122 - linkrev points to an existing changelog revision,
122 123 - linkrev points to a changelog revision that introduces this revision,
123 124 - linkrev points to the lowest of these changesets,
124 125 - both parents exist in the revlog,
125 126 - the revision is not duplicated.
126 127
127 128 Return the linkrev of the revision (or None for changelog's revisions).
128 129 """
129 130 lr = obj.linkrev(obj.rev(node))
130 131 if lr < 0 or (self.havecl and lr not in linkrevs):
131 132 if lr < 0 or lr >= len(self.repo.changelog):
132 133 msg = _("rev %d points to nonexistent changeset %d")
133 134 else:
134 135 msg = _("rev %d points to unexpected changeset %d")
135 136 self._err(None, msg % (i, lr), f)
136 137 if linkrevs:
137 138 if f and len(linkrevs) > 1:
138 139 try:
139 140 # attempt to filter down to real linkrevs
140 141 linkrevs = [l for l in linkrevs
141 142 if self.lrugetctx(l)[f].filenode() == node]
142 143 except Exception:
143 144 pass
144 145 self._warn(_(" (expected %s)") % " ".join
145 146 (map(pycompat.bytestr, linkrevs)))
146 147 lr = None # can't be trusted
147 148
148 149 try:
149 150 p1, p2 = obj.parents(node)
150 151 if p1 not in seen and p1 != nullid:
151 152 self._err(lr, _("unknown parent 1 %s of %s") %
152 153 (short(p1), short(node)), f)
153 154 if p2 not in seen and p2 != nullid:
154 155 self._err(lr, _("unknown parent 2 %s of %s") %
155 156 (short(p2), short(node)), f)
156 157 except Exception as inst:
157 158 self._exc(lr, _("checking parents of %s") % short(node), inst, f)
158 159
159 160 if node in seen:
160 161 self._err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f)
161 162 seen[node] = i
162 163 return lr
163 164
164 165 def verify(self):
165 166 """verify the content of the Mercurial repository
166 167
167 168 This method run all verifications, displaying issues as they are found.
168 169
169 170 return 1 if any error have been encountered, 0 otherwise."""
170 171 # initial validation and generic report
171 172 repo = self.repo
172 173 ui = repo.ui
173 174 if not repo.url().startswith('file:'):
174 175 raise error.Abort(_("cannot verify bundle or remote repos"))
175 176
176 177 if os.path.exists(repo.sjoin("journal")):
177 178 ui.warn(_("abandoned transaction found - run hg recover\n"))
178 179
179 180 if ui.verbose or not self.revlogv1:
180 181 ui.status(_("repository uses revlog format %d\n") %
181 182 (self.revlogv1 and 1 or 0))
182 183
183 184 # data verification
184 185 mflinkrevs, filelinkrevs = self._verifychangelog()
185 186 filenodes = self._verifymanifest(mflinkrevs)
186 187 del mflinkrevs
187 188 self._crosscheckfiles(filelinkrevs, filenodes)
188 189 totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs)
189 190
190 191 # final report
191 192 ui.status(_("checked %d changesets with %d changes to %d files\n") %
192 193 (len(repo.changelog), filerevisions, totalfiles))
193 194 if self.warnings:
194 195 ui.warn(_("%d warnings encountered!\n") % self.warnings)
195 196 if self.fncachewarned:
196 197 ui.warn(_('hint: run "hg debugrebuildfncache" to recover from '
197 198 'corrupt fncache\n'))
198 199 if self.errors:
199 200 ui.warn(_("%d integrity errors encountered!\n") % self.errors)
200 201 if self.badrevs:
201 202 ui.warn(_("(first damaged changeset appears to be %d)\n")
202 203 % min(self.badrevs))
203 204 return 1
204 205 return 0
205 206
206 207 def _verifychangelog(self):
207 208 """verify the changelog of a repository
208 209
209 210 The following checks are performed:
210 211 - all of `_checkrevlog` checks,
211 212 - all of `_checkentry` checks (for each revisions),
212 213 - each revision can be read.
213 214
214 215 The function returns some of the data observed in the changesets as a
215 216 (mflinkrevs, filelinkrevs) tuples:
216 217 - mflinkrevs: is a { manifest-node -> [changelog-rev] } mapping
217 218 - filelinkrevs: is a { file-path -> [changelog-rev] } mapping
218 219
219 220 If a matcher was specified, filelinkrevs will only contains matched
220 221 files.
221 222 """
222 223 ui = self.ui
223 224 repo = self.repo
224 225 match = self.match
225 226 cl = repo.changelog
226 227
227 228 ui.status(_("checking changesets\n"))
228 229 mflinkrevs = {}
229 230 filelinkrevs = {}
230 231 seen = {}
231 232 self._checkrevlog(cl, "changelog", 0)
232 233 progress = ui.makeprogress(_('checking'), unit=_('changesets'),
233 234 total=len(repo))
234 235 for i in repo:
235 236 progress.update(i)
236 237 n = cl.node(i)
237 238 self._checkentry(cl, i, n, seen, [i], "changelog")
238 239
239 240 try:
240 241 changes = cl.read(n)
241 242 if changes[0] != nullid:
242 243 mflinkrevs.setdefault(changes[0], []).append(i)
243 244 self.refersmf = True
244 245 for f in changes[3]:
245 246 if match(f):
246 247 filelinkrevs.setdefault(_normpath(f), []).append(i)
247 248 except Exception as inst:
248 249 self.refersmf = True
249 250 self._exc(i, _("unpacking changeset %s") % short(n), inst)
250 251 progress.complete()
251 252 return mflinkrevs, filelinkrevs
252 253
253 254 def _verifymanifest(self, mflinkrevs, dir="", storefiles=None,
254 255 subdirprogress=None):
255 256 """verify the manifestlog content
256 257
257 258 Inputs:
258 259 - mflinkrevs: a {manifest-node -> [changelog-revisions]} mapping
259 260 - dir: a subdirectory to check (for tree manifest repo)
260 261 - storefiles: set of currently "orphan" files.
261 262 - subdirprogress: a progress object
262 263
263 264 This function checks:
264 265 * all of `_checkrevlog` checks (for all manifest related revlogs)
265 266 * all of `_checkentry` checks (for all manifest related revisions)
266 267 * nodes for subdirectory exists in the sub-directory manifest
267 268 * each manifest entries have a file path
268 269 * each manifest node refered in mflinkrevs exist in the manifest log
269 270
270 271 If tree manifest is in use and a matchers is specified, only the
271 272 sub-directories matching it will be verified.
272 273
273 274 return a two level mapping:
274 275 {"path" -> { filenode -> changelog-revision}}
275 276
276 277 This mapping primarily contains entries for every files in the
277 278 repository. In addition, when tree-manifest is used, it also contains
278 279 sub-directory entries.
279 280
280 281 If a matcher is provided, only matching paths will be included.
281 282 """
282 283 repo = self.repo
283 284 ui = self.ui
284 285 match = self.match
285 286 mfl = self.repo.manifestlog
286 287 mf = mfl.getstorage(dir)
287 288
288 289 if not dir:
289 290 self.ui.status(_("checking manifests\n"))
290 291
291 292 filenodes = {}
292 293 subdirnodes = {}
293 294 seen = {}
294 295 label = "manifest"
295 296 if dir:
296 297 label = dir
297 298 revlogfiles = mf.files()
298 299 storefiles.difference_update(revlogfiles)
299 300 if subdirprogress: # should be true since we're in a subdirectory
300 301 subdirprogress.increment()
301 302 if self.refersmf:
302 303 # Do not check manifest if there are only changelog entries with
303 304 # null manifests.
304 305 self._checkrevlog(mf, label, 0)
305 306 progress = ui.makeprogress(_('checking'), unit=_('manifests'),
306 307 total=len(mf))
307 308 for i in mf:
308 309 if not dir:
309 310 progress.update(i)
310 311 n = mf.node(i)
311 312 lr = self._checkentry(mf, i, n, seen, mflinkrevs.get(n, []), label)
312 313 if n in mflinkrevs:
313 314 del mflinkrevs[n]
314 315 elif dir:
315 316 self._err(lr, _("%s not in parent-directory manifest") %
316 317 short(n), label)
317 318 else:
318 319 self._err(lr, _("%s not in changesets") % short(n), label)
319 320
320 321 try:
321 322 mfdelta = mfl.get(dir, n).readdelta(shallow=True)
322 323 for f, fn, fl in mfdelta.iterentries():
323 324 if not f:
324 325 self._err(lr, _("entry without name in manifest"))
325 326 elif f == "/dev/null": # ignore this in very old repos
326 327 continue
327 328 fullpath = dir + _normpath(f)
328 329 if fl == 't':
329 330 if not match.visitdir(fullpath):
330 331 continue
331 332 subdirnodes.setdefault(fullpath + '/', {}).setdefault(
332 333 fn, []).append(lr)
333 334 else:
334 335 if not match(fullpath):
335 336 continue
336 337 filenodes.setdefault(fullpath, {}).setdefault(fn, lr)
337 338 except Exception as inst:
338 339 self._exc(lr, _("reading delta %s") % short(n), inst, label)
339 340 if not dir:
340 341 progress.complete()
341 342
342 343 if self.havemf:
343 344 # since we delete entry in `mflinkrevs` during iteration, any
344 345 # remaining entries are "missing". We need to issue errors for them.
345 346 changesetpairs = [(c, m) for m in mflinkrevs for c in mflinkrevs[m]]
346 347 for c, m in sorted(changesetpairs):
347 348 if dir:
348 349 self._err(c, _("parent-directory manifest refers to unknown"
349 350 " revision %s") % short(m), label)
350 351 else:
351 352 self._err(c, _("changeset refers to unknown revision %s") %
352 353 short(m), label)
353 354
354 355 if not dir and subdirnodes:
355 356 self.ui.status(_("checking directory manifests\n"))
356 357 storefiles = set()
357 358 subdirs = set()
358 359 revlogv1 = self.revlogv1
359 360 for f, f2, size in repo.store.datafiles():
360 361 if not f:
361 362 self._err(None, _("cannot decode filename '%s'") % f2)
362 363 elif (size > 0 or not revlogv1) and f.startswith('meta/'):
363 364 storefiles.add(_normpath(f))
364 365 subdirs.add(os.path.dirname(f))
365 366 subdirprogress = ui.makeprogress(_('checking'), unit=_('manifests'),
366 367 total=len(subdirs))
367 368
368 369 for subdir, linkrevs in subdirnodes.iteritems():
369 370 subdirfilenodes = self._verifymanifest(linkrevs, subdir, storefiles,
370 371 subdirprogress)
371 372 for f, onefilenodes in subdirfilenodes.iteritems():
372 373 filenodes.setdefault(f, {}).update(onefilenodes)
373 374
374 375 if not dir and subdirnodes:
375 376 subdirprogress.complete()
376 377 if self.warnorphanstorefiles:
377 378 for f in sorted(storefiles):
378 379 self._warn(_("warning: orphan data file '%s'") % f)
379 380
380 381 return filenodes
381 382
382 383 def _crosscheckfiles(self, filelinkrevs, filenodes):
383 384 repo = self.repo
384 385 ui = self.ui
385 386 ui.status(_("crosschecking files in changesets and manifests\n"))
386 387
387 388 total = len(filelinkrevs) + len(filenodes)
388 389 progress = ui.makeprogress(_('crosschecking'), unit=_('files'),
389 390 total=total)
390 391 if self.havemf:
391 392 for f in sorted(filelinkrevs):
392 393 progress.increment()
393 394 if f not in filenodes:
394 395 lr = filelinkrevs[f][0]
395 396 self._err(lr, _("in changeset but not in manifest"), f)
396 397
397 398 if self.havecl:
398 399 for f in sorted(filenodes):
399 400 progress.increment()
400 401 if f not in filelinkrevs:
401 402 try:
402 403 fl = repo.file(f)
403 404 lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
404 405 except Exception:
405 406 lr = None
406 407 self._err(lr, _("in manifest but not in changeset"), f)
407 408
408 409 progress.complete()
409 410
410 411 def _verifyfiles(self, filenodes, filelinkrevs):
411 412 repo = self.repo
412 413 ui = self.ui
413 414 lrugetctx = self.lrugetctx
414 415 revlogv1 = self.revlogv1
415 416 havemf = self.havemf
416 417 ui.status(_("checking files\n"))
417 418
418 419 storefiles = set()
419 420 for f, f2, size in repo.store.datafiles():
420 421 if not f:
421 422 self._err(None, _("cannot decode filename '%s'") % f2)
422 423 elif (size > 0 or not revlogv1) and f.startswith('data/'):
423 424 storefiles.add(_normpath(f))
424 425
425 426 state = {
426 427 # TODO this assumes revlog storage for changelog.
427 428 'expectedversion': self.repo.changelog.version & 0xFFFF,
428 429 'skipflags': self.skipflags,
429 430 # experimental config: censor.policy
430 431 'erroroncensored': ui.config('censor', 'policy') == 'abort',
431 432 }
432 433
433 434 files = sorted(set(filenodes) | set(filelinkrevs))
434 435 revisions = 0
435 436 progress = ui.makeprogress(_('checking'), unit=_('files'),
436 437 total=len(files))
437 438 for i, f in enumerate(files):
438 439 progress.update(i, item=f)
439 440 try:
440 441 linkrevs = filelinkrevs[f]
441 442 except KeyError:
442 443 # in manifest but not in changelog
443 444 linkrevs = []
444 445
445 446 if linkrevs:
446 447 lr = linkrevs[0]
447 448 else:
448 449 lr = None
449 450
450 451 try:
451 452 fl = repo.file(f)
452 453 except error.StorageError as e:
453 454 self._err(lr, _("broken revlog! (%s)") % e, f)
454 455 continue
455 456
456 457 for ff in fl.files():
457 458 try:
458 459 storefiles.remove(ff)
459 460 except KeyError:
460 461 if self.warnorphanstorefiles:
461 462 self._warn(_(" warning: revlog '%s' not in fncache!") %
462 463 ff)
463 464 self.fncachewarned = True
464 465
465 466 if not len(fl) and (self.havecl or self.havemf):
466 467 self._err(lr, _("empty or missing %s") % f)
467 468 else:
468 469 # Guard against implementations not setting this.
469 470 state['skipread'] = set()
470 471 for problem in fl.verifyintegrity(state):
471 472 if problem.node is not None:
472 473 linkrev = fl.linkrev(fl.rev(problem.node))
473 474 else:
474 475 linkrev = None
475 476
476 477 if problem.warning:
477 478 self._warn(problem.warning)
478 479 elif problem.error:
479 480 self._err(linkrev if linkrev is not None else lr,
480 481 problem.error, f)
481 482 else:
482 483 raise error.ProgrammingError(
483 484 'problem instance does not set warning or error '
484 485 'attribute: %s' % problem.msg)
485 486
486 487 seen = {}
487 488 for i in fl:
488 489 revisions += 1
489 490 n = fl.node(i)
490 491 lr = self._checkentry(fl, i, n, seen, linkrevs, f)
491 492 if f in filenodes:
492 493 if havemf and n not in filenodes[f]:
493 494 self._err(lr, _("%s not in manifests") % (short(n)), f)
494 495 else:
495 496 del filenodes[f][n]
496 497
497 498 if n in state['skipread']:
498 499 continue
499 500
500 501 # check renames
501 502 try:
502 503 # This requires resolving fulltext (at least on revlogs). We
503 504 # may want ``verifyintegrity()`` to pass a set of nodes with
504 505 # rename metadata as an optimization.
505 506 rp = fl.renamed(n)
506 507 if rp:
507 508 if lr is not None and ui.verbose:
508 509 ctx = lrugetctx(lr)
509 510 if not any(rp[0] in pctx for pctx in ctx.parents()):
510 511 self._warn(_("warning: copy source of '%s' not"
511 512 " in parents of %s") % (f, ctx))
512 513 fl2 = repo.file(rp[0])
513 514 if not len(fl2):
514 515 self._err(lr,
515 516 _("empty or missing copy source revlog "
516 517 "%s:%s") % (rp[0],
517 518 short(rp[1])),
518 519 f)
519 520 elif rp[1] == nullid:
520 521 ui.note(_("warning: %s@%s: copy source"
521 522 " revision is nullid %s:%s\n")
522 523 % (f, lr, rp[0], short(rp[1])))
523 524 else:
524 525 fl2.rev(rp[1])
525 526 except Exception as inst:
526 527 self._exc(lr, _("checking rename of %s") % short(n),
527 528 inst, f)
528 529
529 530 # cross-check
530 531 if f in filenodes:
531 532 fns = [(v, k) for k, v in filenodes[f].iteritems()]
532 533 for lr, node in sorted(fns):
533 534 self._err(lr, _("manifest refers to unknown revision %s") %
534 535 short(node), f)
535 536 progress.complete()
536 537
537 538 if self.warnorphanstorefiles:
538 539 for f in sorted(storefiles):
539 540 self._warn(_("warning: orphan data file '%s'") % f)
540 541
541 542 return len(files), revisions
@@ -1,414 +1,414 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcapabilities
76 76 debugcheckstate
77 77 debugcolor
78 78 debugcommands
79 79 debugcomplete
80 80 debugconfig
81 81 debugcreatestreamclonebundle
82 82 debugdag
83 83 debugdata
84 84 debugdate
85 85 debugdeltachain
86 86 debugdirstate
87 87 debugdiscovery
88 88 debugdownload
89 89 debugextensions
90 90 debugfileset
91 91 debugformat
92 92 debugfsinfo
93 93 debuggetbundle
94 94 debugignore
95 95 debugindex
96 96 debugindexdot
97 97 debugindexstats
98 98 debuginstall
99 99 debugknown
100 100 debuglabelcomplete
101 101 debuglocks
102 102 debugmanifestfulltextcache
103 103 debugmergestate
104 104 debugnamecomplete
105 105 debugobsolete
106 106 debugp1copies
107 107 debugp2copies
108 108 debugpathcomplete
109 109 debugpathcopies
110 110 debugpeer
111 111 debugpickmergetool
112 112 debugpushkey
113 113 debugpvec
114 114 debugrebuilddirstate
115 115 debugrebuildfncache
116 116 debugrename
117 117 debugrevlog
118 118 debugrevlogindex
119 119 debugrevspec
120 120 debugserve
121 121 debugsetparents
122 122 debugssl
123 123 debugsub
124 124 debugsuccessorssets
125 125 debugtemplate
126 126 debuguigetpass
127 127 debuguiprompt
128 128 debugupdatecaches
129 129 debugupgraderepo
130 130 debugwalk
131 131 debugwhyunstable
132 132 debugwireargs
133 133 debugwireproto
134 134
135 135 Do not show the alias of a debug command if there are other candidates
136 136 (this should hide rawcommit)
137 137 $ hg debugcomplete r
138 138 recover
139 139 remove
140 140 rename
141 141 resolve
142 142 revert
143 143 rollback
144 144 root
145 145 Show the alias of a debug command if there are no other candidates
146 146 $ hg debugcomplete rawc
147 147
148 148
149 149 Show the global options
150 150 $ hg debugcomplete --options | sort
151 151 --color
152 152 --config
153 153 --cwd
154 154 --debug
155 155 --debugger
156 156 --encoding
157 157 --encodingmode
158 158 --help
159 159 --hidden
160 160 --noninteractive
161 161 --pager
162 162 --profile
163 163 --quiet
164 164 --repository
165 165 --time
166 166 --traceback
167 167 --verbose
168 168 --version
169 169 -R
170 170 -h
171 171 -q
172 172 -v
173 173 -y
174 174
175 175 Show the options for the "serve" command
176 176 $ hg debugcomplete --options serve | sort
177 177 --accesslog
178 178 --address
179 179 --certificate
180 180 --cmdserver
181 181 --color
182 182 --config
183 183 --cwd
184 184 --daemon
185 185 --daemon-postexec
186 186 --debug
187 187 --debugger
188 188 --encoding
189 189 --encodingmode
190 190 --errorlog
191 191 --help
192 192 --hidden
193 193 --ipv6
194 194 --name
195 195 --noninteractive
196 196 --pager
197 197 --pid-file
198 198 --port
199 199 --prefix
200 200 --print-url
201 201 --profile
202 202 --quiet
203 203 --repository
204 204 --stdio
205 205 --style
206 206 --subrepos
207 207 --templates
208 208 --time
209 209 --traceback
210 210 --verbose
211 211 --version
212 212 --web-conf
213 213 -6
214 214 -A
215 215 -E
216 216 -R
217 217 -S
218 218 -a
219 219 -d
220 220 -h
221 221 -n
222 222 -p
223 223 -q
224 224 -t
225 225 -v
226 226 -y
227 227
228 228 Show an error if we use --options with an ambiguous abbreviation
229 229 $ hg debugcomplete --options s
230 230 hg: command 's' is ambiguous:
231 231 serve showconfig status summary
232 232 [255]
233 233
234 234 Show all commands + options
235 235 $ hg debugcommands
236 236 add: include, exclude, subrepos, dry-run
237 237 addremove: similarity, subrepos, include, exclude, dry-run
238 238 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
239 239 archive: no-decode, prefix, rev, type, subrepos, include, exclude
240 240 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
241 241 bisect: reset, good, bad, skip, extend, command, noupdate
242 242 bookmarks: force, rev, delete, rename, inactive, list, template
243 243 branch: force, clean, rev
244 244 branches: active, closed, rev, template
245 245 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
246 246 cat: output, rev, decode, include, exclude, template
247 247 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
248 248 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
249 249 config: untrusted, edit, local, global, template
250 250 copy: after, force, include, exclude, dry-run
251 251 debugancestor:
252 252 debugapplystreamclonebundle:
253 253 debugbuilddag: mergeable-file, overwritten-file, new-file
254 254 debugbundle: all, part-type, spec
255 255 debugcapabilities:
256 256 debugcheckstate:
257 257 debugcolor: style
258 258 debugcommands:
259 259 debugcomplete: options
260 260 debugcreatestreamclonebundle:
261 261 debugdag: tags, branches, dots, spaces
262 262 debugdata: changelog, manifest, dir
263 263 debugdate: extended
264 264 debugdeltachain: changelog, manifest, dir, template
265 265 debugdirstate: nodates, dates, datesort
266 266 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
267 267 debugdownload: output
268 268 debugextensions: template
269 269 debugfileset: rev, all-files, show-matcher, show-stage
270 270 debugformat: template
271 271 debugfsinfo:
272 272 debuggetbundle: head, common, type
273 273 debugignore:
274 274 debugindex: changelog, manifest, dir, template
275 275 debugindexdot: changelog, manifest, dir
276 276 debugindexstats:
277 277 debuginstall: template
278 278 debugknown:
279 279 debuglabelcomplete:
280 280 debuglocks: force-lock, force-wlock, set-lock, set-wlock
281 281 debugmanifestfulltextcache: clear, add
282 282 debugmergestate:
283 283 debugnamecomplete:
284 284 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
285 285 debugp1copies: rev
286 286 debugp2copies: rev
287 287 debugpathcomplete: full, normal, added, removed
288 288 debugpathcopies: include, exclude
289 289 debugpeer:
290 290 debugpickmergetool: rev, changedelete, include, exclude, tool
291 291 debugpushkey:
292 292 debugpvec:
293 293 debugrebuilddirstate: rev, minimal
294 294 debugrebuildfncache:
295 295 debugrename: rev
296 296 debugrevlog: changelog, manifest, dir, dump
297 297 debugrevlogindex: changelog, manifest, dir, format
298 298 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
299 299 debugserve: sshstdio, logiofd, logiofile
300 300 debugsetparents:
301 301 debugssl:
302 302 debugsub: rev
303 303 debugsuccessorssets: closest
304 304 debugtemplate: rev, define
305 305 debuguigetpass: prompt
306 306 debuguiprompt: prompt
307 307 debugupdatecaches:
308 308 debugupgraderepo: optimize, run, backup
309 309 debugwalk: include, exclude
310 310 debugwhyunstable:
311 311 debugwireargs: three, four, five, ssh, remotecmd, insecure
312 312 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
313 313 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
314 314 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
315 315 files: rev, print0, include, exclude, template, subrepos
316 316 forget: interactive, include, exclude, dry-run
317 317 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
318 318 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
319 319 heads: rev, topo, active, closed, style, template
320 320 help: extension, command, keyword, system
321 321 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
322 322 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
323 323 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
324 324 init: ssh, remotecmd, insecure
325 325 locate: rev, print0, fullpath, include, exclude
326 326 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
327 327 manifest: rev, all, template
328 328 merge: force, rev, preview, abort, tool
329 329 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
330 330 parents: rev, style, template
331 331 paths: template
332 332 phase: public, draft, secret, force, rev
333 333 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
334 334 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
335 335 recover: verify
336 336 remove: after, force, subrepos, include, exclude, dry-run
337 337 rename: after, force, include, exclude, dry-run
338 338 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
339 339 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
340 340 rollback: dry-run, force
341 341 root:
342 342 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
343 343 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
344 344 summary: remote
345 345 tag: force, local, rev, remove, edit, message, date, user
346 346 tags: template
347 347 tip: patch, git, style, template
348 348 unbundle: update
349 349 update: clean, check, merge, date, rev, tool
350 verify:
350 verify: full
351 351 version: template
352 352
353 353 $ hg init a
354 354 $ cd a
355 355 $ echo fee > fee
356 356 $ hg ci -q -Amfee
357 357 $ hg tag fee
358 358 $ mkdir fie
359 359 $ echo dead > fie/dead
360 360 $ echo live > fie/live
361 361 $ hg bookmark fo
362 362 $ hg branch -q fie
363 363 $ hg ci -q -Amfie
364 364 $ echo fo > fo
365 365 $ hg branch -qf default
366 366 $ hg ci -q -Amfo
367 367 $ echo Fum > Fum
368 368 $ hg ci -q -AmFum
369 369 $ hg bookmark Fum
370 370
371 371 Test debugpathcomplete
372 372
373 373 $ hg debugpathcomplete f
374 374 fee
375 375 fie
376 376 fo
377 377 $ hg debugpathcomplete -f f
378 378 fee
379 379 fie/dead
380 380 fie/live
381 381 fo
382 382
383 383 $ hg rm Fum
384 384 $ hg debugpathcomplete -r F
385 385 Fum
386 386
387 387 Test debugnamecomplete
388 388
389 389 $ hg debugnamecomplete
390 390 Fum
391 391 default
392 392 fee
393 393 fie
394 394 fo
395 395 tip
396 396 $ hg debugnamecomplete f
397 397 fee
398 398 fie
399 399 fo
400 400
401 401 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
402 402 used for completions in some shells.
403 403
404 404 $ hg debuglabelcomplete
405 405 Fum
406 406 default
407 407 fee
408 408 fie
409 409 fo
410 410 tip
411 411 $ hg debuglabelcomplete f
412 412 fee
413 413 fie
414 414 fo
@@ -1,3833 +1,3835 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 Extra extensions will be printed in help output in a non-reliable order since
48 48 the extension is unknown.
49 49 #if no-extraextensions
50 50
51 51 $ hg help
52 52 Mercurial Distributed SCM
53 53
54 54 list of commands:
55 55
56 56 Repository creation:
57 57
58 58 clone make a copy of an existing repository
59 59 init create a new repository in the given directory
60 60
61 61 Remote repository management:
62 62
63 63 incoming show new changesets found in source
64 64 outgoing show changesets not found in the destination
65 65 paths show aliases for remote repositories
66 66 pull pull changes from the specified source
67 67 push push changes to the specified destination
68 68 serve start stand-alone webserver
69 69
70 70 Change creation:
71 71
72 72 commit commit the specified files or all outstanding changes
73 73
74 74 Change manipulation:
75 75
76 76 backout reverse effect of earlier changeset
77 77 graft copy changes from other branches onto the current branch
78 78 merge merge another revision into working directory
79 79
80 80 Change organization:
81 81
82 82 bookmarks create a new bookmark or list existing bookmarks
83 83 branch set or show the current branch name
84 84 branches list repository named branches
85 85 phase set or show the current phase name
86 86 tag add one or more tags for the current or given revision
87 87 tags list repository tags
88 88
89 89 File content management:
90 90
91 91 annotate show changeset information by line for each file
92 92 cat output the current or given revision of files
93 93 copy mark files as copied for the next commit
94 94 diff diff repository (or selected files)
95 95 grep search revision history for a pattern in specified files
96 96
97 97 Change navigation:
98 98
99 99 bisect subdivision search of changesets
100 100 heads show branch heads
101 101 identify identify the working directory or specified revision
102 102 log show revision history of entire repository or files
103 103
104 104 Working directory management:
105 105
106 106 add add the specified files on the next commit
107 107 addremove add all new files, delete all missing files
108 108 files list tracked files
109 109 forget forget the specified files on the next commit
110 110 remove remove the specified files on the next commit
111 111 rename rename files; equivalent of copy + remove
112 112 resolve redo merges or set/view the merge status of files
113 113 revert restore files to their checkout state
114 114 root print the root (top) of the current working directory
115 115 status show changed files in the working directory
116 116 summary summarize working directory state
117 117 update update working directory (or switch revisions)
118 118
119 119 Change import/export:
120 120
121 121 archive create an unversioned archive of a repository revision
122 122 bundle create a bundle file
123 123 export dump the header and diffs for one or more changesets
124 124 import import an ordered set of patches
125 125 unbundle apply one or more bundle files
126 126
127 127 Repository maintenance:
128 128
129 129 manifest output the current or given revision of the project manifest
130 130 recover roll back an interrupted transaction
131 131 verify verify the integrity of the repository
132 132
133 133 Help:
134 134
135 135 config show combined config settings from all hgrc files
136 136 help show help for a given topic or a help overview
137 137 version output version and copyright information
138 138
139 139 additional help topics:
140 140
141 141 Mercurial identifiers:
142 142
143 143 filesets Specifying File Sets
144 144 hgignore Syntax for Mercurial Ignore Files
145 145 patterns File Name Patterns
146 146 revisions Specifying Revisions
147 147 urls URL Paths
148 148
149 149 Mercurial output:
150 150
151 151 color Colorizing Outputs
152 152 dates Date Formats
153 153 diffs Diff Formats
154 154 templating Template Usage
155 155
156 156 Mercurial configuration:
157 157
158 158 config Configuration Files
159 159 environment Environment Variables
160 160 extensions Using Additional Features
161 161 flags Command-line flags
162 162 hgweb Configuring hgweb
163 163 merge-tools Merge Tools
164 164 pager Pager Support
165 165
166 166 Concepts:
167 167
168 168 bundlespec Bundle File Formats
169 169 glossary Glossary
170 170 phases Working with Phases
171 171 subrepos Subrepositories
172 172
173 173 Miscellaneous:
174 174
175 175 deprecated Deprecated Features
176 176 internals Technical implementation topics
177 177 scripting Using Mercurial from scripts and automation
178 178
179 179 (use 'hg help -v' to show built-in aliases and global options)
180 180
181 181 $ hg -q help
182 182 Repository creation:
183 183
184 184 clone make a copy of an existing repository
185 185 init create a new repository in the given directory
186 186
187 187 Remote repository management:
188 188
189 189 incoming show new changesets found in source
190 190 outgoing show changesets not found in the destination
191 191 paths show aliases for remote repositories
192 192 pull pull changes from the specified source
193 193 push push changes to the specified destination
194 194 serve start stand-alone webserver
195 195
196 196 Change creation:
197 197
198 198 commit commit the specified files or all outstanding changes
199 199
200 200 Change manipulation:
201 201
202 202 backout reverse effect of earlier changeset
203 203 graft copy changes from other branches onto the current branch
204 204 merge merge another revision into working directory
205 205
206 206 Change organization:
207 207
208 208 bookmarks create a new bookmark or list existing bookmarks
209 209 branch set or show the current branch name
210 210 branches list repository named branches
211 211 phase set or show the current phase name
212 212 tag add one or more tags for the current or given revision
213 213 tags list repository tags
214 214
215 215 File content management:
216 216
217 217 annotate show changeset information by line for each file
218 218 cat output the current or given revision of files
219 219 copy mark files as copied for the next commit
220 220 diff diff repository (or selected files)
221 221 grep search revision history for a pattern in specified files
222 222
223 223 Change navigation:
224 224
225 225 bisect subdivision search of changesets
226 226 heads show branch heads
227 227 identify identify the working directory or specified revision
228 228 log show revision history of entire repository or files
229 229
230 230 Working directory management:
231 231
232 232 add add the specified files on the next commit
233 233 addremove add all new files, delete all missing files
234 234 files list tracked files
235 235 forget forget the specified files on the next commit
236 236 remove remove the specified files on the next commit
237 237 rename rename files; equivalent of copy + remove
238 238 resolve redo merges or set/view the merge status of files
239 239 revert restore files to their checkout state
240 240 root print the root (top) of the current working directory
241 241 status show changed files in the working directory
242 242 summary summarize working directory state
243 243 update update working directory (or switch revisions)
244 244
245 245 Change import/export:
246 246
247 247 archive create an unversioned archive of a repository revision
248 248 bundle create a bundle file
249 249 export dump the header and diffs for one or more changesets
250 250 import import an ordered set of patches
251 251 unbundle apply one or more bundle files
252 252
253 253 Repository maintenance:
254 254
255 255 manifest output the current or given revision of the project manifest
256 256 recover roll back an interrupted transaction
257 257 verify verify the integrity of the repository
258 258
259 259 Help:
260 260
261 261 config show combined config settings from all hgrc files
262 262 help show help for a given topic or a help overview
263 263 version output version and copyright information
264 264
265 265 additional help topics:
266 266
267 267 Mercurial identifiers:
268 268
269 269 filesets Specifying File Sets
270 270 hgignore Syntax for Mercurial Ignore Files
271 271 patterns File Name Patterns
272 272 revisions Specifying Revisions
273 273 urls URL Paths
274 274
275 275 Mercurial output:
276 276
277 277 color Colorizing Outputs
278 278 dates Date Formats
279 279 diffs Diff Formats
280 280 templating Template Usage
281 281
282 282 Mercurial configuration:
283 283
284 284 config Configuration Files
285 285 environment Environment Variables
286 286 extensions Using Additional Features
287 287 flags Command-line flags
288 288 hgweb Configuring hgweb
289 289 merge-tools Merge Tools
290 290 pager Pager Support
291 291
292 292 Concepts:
293 293
294 294 bundlespec Bundle File Formats
295 295 glossary Glossary
296 296 phases Working with Phases
297 297 subrepos Subrepositories
298 298
299 299 Miscellaneous:
300 300
301 301 deprecated Deprecated Features
302 302 internals Technical implementation topics
303 303 scripting Using Mercurial from scripts and automation
304 304
305 305 Test extension help:
306 306 $ hg help extensions --config extensions.rebase= --config extensions.children=
307 307 Using Additional Features
308 308 """""""""""""""""""""""""
309 309
310 310 Mercurial has the ability to add new features through the use of
311 311 extensions. Extensions may add new commands, add options to existing
312 312 commands, change the default behavior of commands, or implement hooks.
313 313
314 314 To enable the "foo" extension, either shipped with Mercurial or in the
315 315 Python search path, create an entry for it in your configuration file,
316 316 like this:
317 317
318 318 [extensions]
319 319 foo =
320 320
321 321 You may also specify the full path to an extension:
322 322
323 323 [extensions]
324 324 myfeature = ~/.hgext/myfeature.py
325 325
326 326 See 'hg help config' for more information on configuration files.
327 327
328 328 Extensions are not loaded by default for a variety of reasons: they can
329 329 increase startup overhead; they may be meant for advanced usage only; they
330 330 may provide potentially dangerous abilities (such as letting you destroy
331 331 or modify history); they might not be ready for prime time; or they may
332 332 alter some usual behaviors of stock Mercurial. It is thus up to the user
333 333 to activate extensions as needed.
334 334
335 335 To explicitly disable an extension enabled in a configuration file of
336 336 broader scope, prepend its path with !:
337 337
338 338 [extensions]
339 339 # disabling extension bar residing in /path/to/extension/bar.py
340 340 bar = !/path/to/extension/bar.py
341 341 # ditto, but no path was supplied for extension baz
342 342 baz = !
343 343
344 344 enabled extensions:
345 345
346 346 children command to display child changesets (DEPRECATED)
347 347 rebase command to move sets of revisions to a different ancestor
348 348
349 349 disabled extensions:
350 350
351 351 acl hooks for controlling repository access
352 352 blackbox log repository events to a blackbox for debugging
353 353 bugzilla hooks for integrating with the Bugzilla bug tracker
354 354 censor erase file content at a given revision
355 355 churn command to display statistics about repository history
356 356 clonebundles advertise pre-generated bundles to seed clones
357 357 closehead close arbitrary heads without checking them out first
358 358 convert import revisions from foreign VCS repositories into
359 359 Mercurial
360 360 eol automatically manage newlines in repository files
361 361 extdiff command to allow external programs to compare revisions
362 362 factotum http authentication with factotum
363 363 githelp try mapping git commands to Mercurial commands
364 364 gpg commands to sign and verify changesets
365 365 hgk browse the repository in a graphical way
366 366 highlight syntax highlighting for hgweb (requires Pygments)
367 367 histedit interactive history editing
368 368 keyword expand keywords in tracked files
369 369 largefiles track large binary files
370 370 mq manage a stack of patches
371 371 notify hooks for sending email push notifications
372 372 patchbomb command to send changesets as (a series of) patch emails
373 373 purge command to delete untracked files from the working
374 374 directory
375 375 relink recreates hardlinks between repository clones
376 376 schemes extend schemes with shortcuts to repository swarms
377 377 share share a common history between several working directories
378 378 shelve save and restore changes to the working directory
379 379 strip strip changesets and their descendants from history
380 380 transplant command to transplant changesets from another branch
381 381 win32mbcs allow the use of MBCS paths with problematic encodings
382 382 zeroconf discover and advertise repositories on the local network
383 383
384 384 #endif
385 385
386 386 Verify that deprecated extensions are included if --verbose:
387 387
388 388 $ hg -v help extensions | grep children
389 389 children command to display child changesets (DEPRECATED)
390 390
391 391 Verify that extension keywords appear in help templates
392 392
393 393 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
394 394
395 395 Test short command list with verbose option
396 396
397 397 $ hg -v help shortlist
398 398 Mercurial Distributed SCM
399 399
400 400 basic commands:
401 401
402 402 add add the specified files on the next commit
403 403 annotate, blame
404 404 show changeset information by line for each file
405 405 clone make a copy of an existing repository
406 406 commit, ci commit the specified files or all outstanding changes
407 407 diff diff repository (or selected files)
408 408 export dump the header and diffs for one or more changesets
409 409 forget forget the specified files on the next commit
410 410 init create a new repository in the given directory
411 411 log, history show revision history of entire repository or files
412 412 merge merge another revision into working directory
413 413 pull pull changes from the specified source
414 414 push push changes to the specified destination
415 415 remove, rm remove the specified files on the next commit
416 416 serve start stand-alone webserver
417 417 status, st show changed files in the working directory
418 418 summary, sum summarize working directory state
419 419 update, up, checkout, co
420 420 update working directory (or switch revisions)
421 421
422 422 global options ([+] can be repeated):
423 423
424 424 -R --repository REPO repository root directory or name of overlay bundle
425 425 file
426 426 --cwd DIR change working directory
427 427 -y --noninteractive do not prompt, automatically pick the first choice for
428 428 all prompts
429 429 -q --quiet suppress output
430 430 -v --verbose enable additional output
431 431 --color TYPE when to colorize (boolean, always, auto, never, or
432 432 debug)
433 433 --config CONFIG [+] set/override config option (use 'section.name=value')
434 434 --debug enable debugging output
435 435 --debugger start debugger
436 436 --encoding ENCODE set the charset encoding (default: ascii)
437 437 --encodingmode MODE set the charset encoding mode (default: strict)
438 438 --traceback always print a traceback on exception
439 439 --time time how long the command takes
440 440 --profile print command execution profile
441 441 --version output version information and exit
442 442 -h --help display help and exit
443 443 --hidden consider hidden changesets
444 444 --pager TYPE when to paginate (boolean, always, auto, or never)
445 445 (default: auto)
446 446
447 447 (use 'hg help' for the full list of commands)
448 448
449 449 $ hg add -h
450 450 hg add [OPTION]... [FILE]...
451 451
452 452 add the specified files on the next commit
453 453
454 454 Schedule files to be version controlled and added to the repository.
455 455
456 456 The files will be added to the repository at the next commit. To undo an
457 457 add before that, see 'hg forget'.
458 458
459 459 If no names are given, add all files to the repository (except files
460 460 matching ".hgignore").
461 461
462 462 Returns 0 if all files are successfully added.
463 463
464 464 options ([+] can be repeated):
465 465
466 466 -I --include PATTERN [+] include names matching the given patterns
467 467 -X --exclude PATTERN [+] exclude names matching the given patterns
468 468 -S --subrepos recurse into subrepositories
469 469 -n --dry-run do not perform actions, just print output
470 470
471 471 (some details hidden, use --verbose to show complete help)
472 472
473 473 Verbose help for add
474 474
475 475 $ hg add -hv
476 476 hg add [OPTION]... [FILE]...
477 477
478 478 add the specified files on the next commit
479 479
480 480 Schedule files to be version controlled and added to the repository.
481 481
482 482 The files will be added to the repository at the next commit. To undo an
483 483 add before that, see 'hg forget'.
484 484
485 485 If no names are given, add all files to the repository (except files
486 486 matching ".hgignore").
487 487
488 488 Examples:
489 489
490 490 - New (unknown) files are added automatically by 'hg add':
491 491
492 492 $ ls
493 493 foo.c
494 494 $ hg status
495 495 ? foo.c
496 496 $ hg add
497 497 adding foo.c
498 498 $ hg status
499 499 A foo.c
500 500
501 501 - Specific files to be added can be specified:
502 502
503 503 $ ls
504 504 bar.c foo.c
505 505 $ hg status
506 506 ? bar.c
507 507 ? foo.c
508 508 $ hg add bar.c
509 509 $ hg status
510 510 A bar.c
511 511 ? foo.c
512 512
513 513 Returns 0 if all files are successfully added.
514 514
515 515 options ([+] can be repeated):
516 516
517 517 -I --include PATTERN [+] include names matching the given patterns
518 518 -X --exclude PATTERN [+] exclude names matching the given patterns
519 519 -S --subrepos recurse into subrepositories
520 520 -n --dry-run do not perform actions, just print output
521 521
522 522 global options ([+] can be repeated):
523 523
524 524 -R --repository REPO repository root directory or name of overlay bundle
525 525 file
526 526 --cwd DIR change working directory
527 527 -y --noninteractive do not prompt, automatically pick the first choice for
528 528 all prompts
529 529 -q --quiet suppress output
530 530 -v --verbose enable additional output
531 531 --color TYPE when to colorize (boolean, always, auto, never, or
532 532 debug)
533 533 --config CONFIG [+] set/override config option (use 'section.name=value')
534 534 --debug enable debugging output
535 535 --debugger start debugger
536 536 --encoding ENCODE set the charset encoding (default: ascii)
537 537 --encodingmode MODE set the charset encoding mode (default: strict)
538 538 --traceback always print a traceback on exception
539 539 --time time how long the command takes
540 540 --profile print command execution profile
541 541 --version output version information and exit
542 542 -h --help display help and exit
543 543 --hidden consider hidden changesets
544 544 --pager TYPE when to paginate (boolean, always, auto, or never)
545 545 (default: auto)
546 546
547 547 Test the textwidth config option
548 548
549 549 $ hg root -h --config ui.textwidth=50
550 550 hg root
551 551
552 552 print the root (top) of the current working
553 553 directory
554 554
555 555 Print the root directory of the current
556 556 repository.
557 557
558 558 Returns 0 on success.
559 559
560 560 (some details hidden, use --verbose to show
561 561 complete help)
562 562
563 563 Test help option with version option
564 564
565 565 $ hg add -h --version
566 566 Mercurial Distributed SCM (version *) (glob)
567 567 (see https://mercurial-scm.org for more information)
568 568
569 569 Copyright (C) 2005-* Matt Mackall and others (glob)
570 570 This is free software; see the source for copying conditions. There is NO
571 571 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
572 572
573 573 $ hg add --skjdfks
574 574 hg add: option --skjdfks not recognized
575 575 hg add [OPTION]... [FILE]...
576 576
577 577 add the specified files on the next commit
578 578
579 579 options ([+] can be repeated):
580 580
581 581 -I --include PATTERN [+] include names matching the given patterns
582 582 -X --exclude PATTERN [+] exclude names matching the given patterns
583 583 -S --subrepos recurse into subrepositories
584 584 -n --dry-run do not perform actions, just print output
585 585
586 586 (use 'hg add -h' to show more help)
587 587 [255]
588 588
589 589 Test ambiguous command help
590 590
591 591 $ hg help ad
592 592 list of commands:
593 593
594 594 add add the specified files on the next commit
595 595 addremove add all new files, delete all missing files
596 596
597 597 (use 'hg help -v ad' to show built-in aliases and global options)
598 598
599 599 Test command without options
600 600
601 601 $ hg help verify
602 602 hg verify
603 603
604 604 verify the integrity of the repository
605 605
606 606 Verify the integrity of the current repository.
607 607
608 608 This will perform an extensive check of the repository's integrity,
609 609 validating the hashes and checksums of each entry in the changelog,
610 610 manifest, and tracked files, as well as the integrity of their crosslinks
611 611 and indices.
612 612
613 613 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
614 614 information about recovery from corruption of the repository.
615 615
616 616 Returns 0 on success, 1 if errors are encountered.
617 617
618 options:
619
618 620 (some details hidden, use --verbose to show complete help)
619 621
620 622 $ hg help diff
621 623 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
622 624
623 625 diff repository (or selected files)
624 626
625 627 Show differences between revisions for the specified files.
626 628
627 629 Differences between files are shown using the unified diff format.
628 630
629 631 Note:
630 632 'hg diff' may generate unexpected results for merges, as it will
631 633 default to comparing against the working directory's first parent
632 634 changeset if no revisions are specified.
633 635
634 636 When two revision arguments are given, then changes are shown between
635 637 those revisions. If only one revision is specified then that revision is
636 638 compared to the working directory, and, when no revisions are specified,
637 639 the working directory files are compared to its first parent.
638 640
639 641 Alternatively you can specify -c/--change with a revision to see the
640 642 changes in that changeset relative to its first parent.
641 643
642 644 Without the -a/--text option, diff will avoid generating diffs of files it
643 645 detects as binary. With -a, diff will generate a diff anyway, probably
644 646 with undesirable results.
645 647
646 648 Use the -g/--git option to generate diffs in the git extended diff format.
647 649 For more information, read 'hg help diffs'.
648 650
649 651 Returns 0 on success.
650 652
651 653 options ([+] can be repeated):
652 654
653 655 -r --rev REV [+] revision
654 656 -c --change REV change made by revision
655 657 -a --text treat all files as text
656 658 -g --git use git extended diff format
657 659 --binary generate binary diffs in git mode (default)
658 660 --nodates omit dates from diff headers
659 661 --noprefix omit a/ and b/ prefixes from filenames
660 662 -p --show-function show which function each change is in
661 663 --reverse produce a diff that undoes the changes
662 664 -w --ignore-all-space ignore white space when comparing lines
663 665 -b --ignore-space-change ignore changes in the amount of white space
664 666 -B --ignore-blank-lines ignore changes whose lines are all blank
665 667 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
666 668 -U --unified NUM number of lines of context to show
667 669 --stat output diffstat-style summary of changes
668 670 --root DIR produce diffs relative to subdirectory
669 671 -I --include PATTERN [+] include names matching the given patterns
670 672 -X --exclude PATTERN [+] exclude names matching the given patterns
671 673 -S --subrepos recurse into subrepositories
672 674
673 675 (some details hidden, use --verbose to show complete help)
674 676
675 677 $ hg help status
676 678 hg status [OPTION]... [FILE]...
677 679
678 680 aliases: st
679 681
680 682 show changed files in the working directory
681 683
682 684 Show status of files in the repository. If names are given, only files
683 685 that match are shown. Files that are clean or ignored or the source of a
684 686 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
685 687 -C/--copies or -A/--all are given. Unless options described with "show
686 688 only ..." are given, the options -mardu are used.
687 689
688 690 Option -q/--quiet hides untracked (unknown and ignored) files unless
689 691 explicitly requested with -u/--unknown or -i/--ignored.
690 692
691 693 Note:
692 694 'hg status' may appear to disagree with diff if permissions have
693 695 changed or a merge has occurred. The standard diff format does not
694 696 report permission changes and diff only reports changes relative to one
695 697 merge parent.
696 698
697 699 If one revision is given, it is used as the base revision. If two
698 700 revisions are given, the differences between them are shown. The --change
699 701 option can also be used as a shortcut to list the changed files of a
700 702 revision from its first parent.
701 703
702 704 The codes used to show the status of files are:
703 705
704 706 M = modified
705 707 A = added
706 708 R = removed
707 709 C = clean
708 710 ! = missing (deleted by non-hg command, but still tracked)
709 711 ? = not tracked
710 712 I = ignored
711 713 = origin of the previous file (with --copies)
712 714
713 715 Returns 0 on success.
714 716
715 717 options ([+] can be repeated):
716 718
717 719 -A --all show status of all files
718 720 -m --modified show only modified files
719 721 -a --added show only added files
720 722 -r --removed show only removed files
721 723 -d --deleted show only deleted (but tracked) files
722 724 -c --clean show only files without changes
723 725 -u --unknown show only unknown (not tracked) files
724 726 -i --ignored show only ignored files
725 727 -n --no-status hide status prefix
726 728 -C --copies show source of copied files
727 729 -0 --print0 end filenames with NUL, for use with xargs
728 730 --rev REV [+] show difference from revision
729 731 --change REV list the changed files of a revision
730 732 -I --include PATTERN [+] include names matching the given patterns
731 733 -X --exclude PATTERN [+] exclude names matching the given patterns
732 734 -S --subrepos recurse into subrepositories
733 735 -T --template TEMPLATE display with template
734 736
735 737 (some details hidden, use --verbose to show complete help)
736 738
737 739 $ hg -q help status
738 740 hg status [OPTION]... [FILE]...
739 741
740 742 show changed files in the working directory
741 743
742 744 $ hg help foo
743 745 abort: no such help topic: foo
744 746 (try 'hg help --keyword foo')
745 747 [255]
746 748
747 749 $ hg skjdfks
748 750 hg: unknown command 'skjdfks'
749 751 (use 'hg help' for a list of commands)
750 752 [255]
751 753
752 754 Typoed command gives suggestion
753 755 $ hg puls
754 756 hg: unknown command 'puls'
755 757 (did you mean one of pull, push?)
756 758 [255]
757 759
758 760 Not enabled extension gets suggested
759 761
760 762 $ hg rebase
761 763 hg: unknown command 'rebase'
762 764 'rebase' is provided by the following extension:
763 765
764 766 rebase command to move sets of revisions to a different ancestor
765 767
766 768 (use 'hg help extensions' for information on enabling extensions)
767 769 [255]
768 770
769 771 Disabled extension gets suggested
770 772 $ hg --config extensions.rebase=! rebase
771 773 hg: unknown command 'rebase'
772 774 'rebase' is provided by the following extension:
773 775
774 776 rebase command to move sets of revisions to a different ancestor
775 777
776 778 (use 'hg help extensions' for information on enabling extensions)
777 779 [255]
778 780
779 781 Make sure that we don't run afoul of the help system thinking that
780 782 this is a section and erroring out weirdly.
781 783
782 784 $ hg .log
783 785 hg: unknown command '.log'
784 786 (did you mean log?)
785 787 [255]
786 788
787 789 $ hg log.
788 790 hg: unknown command 'log.'
789 791 (did you mean log?)
790 792 [255]
791 793 $ hg pu.lh
792 794 hg: unknown command 'pu.lh'
793 795 (did you mean one of pull, push?)
794 796 [255]
795 797
796 798 $ cat > helpext.py <<EOF
797 799 > import os
798 800 > from mercurial import commands, fancyopts, registrar
799 801 >
800 802 > def func(arg):
801 803 > return '%sfoo' % arg
802 804 > class customopt(fancyopts.customopt):
803 805 > def newstate(self, oldstate, newparam, abort):
804 806 > return '%sbar' % oldstate
805 807 > cmdtable = {}
806 808 > command = registrar.command(cmdtable)
807 809 >
808 810 > @command(b'nohelp',
809 811 > [(b'', b'longdesc', 3, b'x'*67),
810 812 > (b'n', b'', None, b'normal desc'),
811 813 > (b'', b'newline', b'', b'line1\nline2'),
812 814 > (b'', b'default-off', False, b'enable X'),
813 815 > (b'', b'default-on', True, b'enable Y'),
814 816 > (b'', b'callableopt', func, b'adds foo'),
815 817 > (b'', b'customopt', customopt(''), b'adds bar'),
816 818 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
817 819 > b'hg nohelp',
818 820 > norepo=True)
819 821 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
820 822 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
821 823 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
822 824 > def nohelp(ui, *args, **kwargs):
823 825 > pass
824 826 >
825 827 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
826 828 > def hashelp(ui, *args, **kwargs):
827 829 > """Extension command's help"""
828 830 >
829 831 > def uisetup(ui):
830 832 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
831 833 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
832 834 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
833 835 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
834 836 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
835 837 >
836 838 > EOF
837 839 $ echo '[extensions]' >> $HGRCPATH
838 840 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
839 841
840 842 Test for aliases
841 843
842 844 $ hg help | grep hgalias
843 845 hgalias My doc
844 846
845 847 $ hg help hgalias
846 848 hg hgalias [--remote]
847 849
848 850 alias for: hg summary
849 851
850 852 My doc
851 853
852 854 defined by: helpext
853 855
854 856 options:
855 857
856 858 --remote check for push and pull
857 859
858 860 (some details hidden, use --verbose to show complete help)
859 861 $ hg help hgaliasnodoc
860 862 hg hgaliasnodoc [--remote]
861 863
862 864 alias for: hg summary
863 865
864 866 summarize working directory state
865 867
866 868 This generates a brief summary of the working directory state, including
867 869 parents, branch, commit status, phase and available updates.
868 870
869 871 With the --remote option, this will check the default paths for incoming
870 872 and outgoing changes. This can be time-consuming.
871 873
872 874 Returns 0 on success.
873 875
874 876 defined by: helpext
875 877
876 878 options:
877 879
878 880 --remote check for push and pull
879 881
880 882 (some details hidden, use --verbose to show complete help)
881 883
882 884 $ hg help shellalias
883 885 hg shellalias
884 886
885 887 shell alias for: echo hi
886 888
887 889 (no help text available)
888 890
889 891 defined by: helpext
890 892
891 893 (some details hidden, use --verbose to show complete help)
892 894
893 895 Test command with no help text
894 896
895 897 $ hg help nohelp
896 898 hg nohelp
897 899
898 900 (no help text available)
899 901
900 902 options:
901 903
902 904 --longdesc VALUE
903 905 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
904 906 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
905 907 -n -- normal desc
906 908 --newline VALUE line1 line2
907 909 --default-off enable X
908 910 --[no-]default-on enable Y (default: on)
909 911 --callableopt VALUE adds foo
910 912 --customopt VALUE adds bar
911 913 --customopt-withdefault VALUE adds bar (default: foo)
912 914
913 915 (some details hidden, use --verbose to show complete help)
914 916
915 917 Test that default list of commands includes extension commands that have help,
916 918 but not those that don't, except in verbose mode, when a keyword is passed, or
917 919 when help about the extension is requested.
918 920
919 921 #if no-extraextensions
920 922
921 923 $ hg help | grep hashelp
922 924 hashelp Extension command's help
923 925 $ hg help | grep nohelp
924 926 [1]
925 927 $ hg help -v | grep nohelp
926 928 nohelp (no help text available)
927 929
928 930 $ hg help -k nohelp
929 931 Commands:
930 932
931 933 nohelp hg nohelp
932 934
933 935 Extension Commands:
934 936
935 937 nohelp (no help text available)
936 938
937 939 $ hg help helpext
938 940 helpext extension - no help text available
939 941
940 942 list of commands:
941 943
942 944 hashelp Extension command's help
943 945 nohelp (no help text available)
944 946
945 947 (use 'hg help -v helpext' to show built-in aliases and global options)
946 948
947 949 #endif
948 950
949 951 Test list of internal help commands
950 952
951 953 $ hg help debug
952 954 debug commands (internal and unsupported):
953 955
954 956 debugancestor
955 957 find the ancestor revision of two revisions in a given index
956 958 debugapplystreamclonebundle
957 959 apply a stream clone bundle file
958 960 debugbuilddag
959 961 builds a repo with a given DAG from scratch in the current
960 962 empty repo
961 963 debugbundle lists the contents of a bundle
962 964 debugcapabilities
963 965 lists the capabilities of a remote peer
964 966 debugcheckstate
965 967 validate the correctness of the current dirstate
966 968 debugcolor show available color, effects or style
967 969 debugcommands
968 970 list all available commands and options
969 971 debugcomplete
970 972 returns the completion list associated with the given command
971 973 debugcreatestreamclonebundle
972 974 create a stream clone bundle file
973 975 debugdag format the changelog or an index DAG as a concise textual
974 976 description
975 977 debugdata dump the contents of a data file revision
976 978 debugdate parse and display a date
977 979 debugdeltachain
978 980 dump information about delta chains in a revlog
979 981 debugdirstate
980 982 show the contents of the current dirstate
981 983 debugdiscovery
982 984 runs the changeset discovery protocol in isolation
983 985 debugdownload
984 986 download a resource using Mercurial logic and config
985 987 debugextensions
986 988 show information about active extensions
987 989 debugfileset parse and apply a fileset specification
988 990 debugformat display format information about the current repository
989 991 debugfsinfo show information detected about current filesystem
990 992 debuggetbundle
991 993 retrieves a bundle from a repo
992 994 debugignore display the combined ignore pattern and information about
993 995 ignored files
994 996 debugindex dump index data for a storage primitive
995 997 debugindexdot
996 998 dump an index DAG as a graphviz dot file
997 999 debugindexstats
998 1000 show stats related to the changelog index
999 1001 debuginstall test Mercurial installation
1000 1002 debugknown test whether node ids are known to a repo
1001 1003 debuglocks show or modify state of locks
1002 1004 debugmanifestfulltextcache
1003 1005 show, clear or amend the contents of the manifest fulltext
1004 1006 cache
1005 1007 debugmergestate
1006 1008 print merge state
1007 1009 debugnamecomplete
1008 1010 complete "names" - tags, open branch names, bookmark names
1009 1011 debugobsolete
1010 1012 create arbitrary obsolete marker
1011 1013 debugoptADV (no help text available)
1012 1014 debugoptDEP (no help text available)
1013 1015 debugoptEXP (no help text available)
1014 1016 debugp1copies
1015 1017 dump copy information compared to p1
1016 1018 debugp2copies
1017 1019 dump copy information compared to p2
1018 1020 debugpathcomplete
1019 1021 complete part or all of a tracked path
1020 1022 debugpathcopies
1021 1023 show copies between two revisions
1022 1024 debugpeer establish a connection to a peer repository
1023 1025 debugpickmergetool
1024 1026 examine which merge tool is chosen for specified file
1025 1027 debugpushkey access the pushkey key/value protocol
1026 1028 debugpvec (no help text available)
1027 1029 debugrebuilddirstate
1028 1030 rebuild the dirstate as it would look like for the given
1029 1031 revision
1030 1032 debugrebuildfncache
1031 1033 rebuild the fncache file
1032 1034 debugrename dump rename information
1033 1035 debugrevlog show data and statistics about a revlog
1034 1036 debugrevlogindex
1035 1037 dump the contents of a revlog index
1036 1038 debugrevspec parse and apply a revision specification
1037 1039 debugserve run a server with advanced settings
1038 1040 debugsetparents
1039 1041 manually set the parents of the current working directory
1040 1042 debugssl test a secure connection to a server
1041 1043 debugsub (no help text available)
1042 1044 debugsuccessorssets
1043 1045 show set of successors for revision
1044 1046 debugtemplate
1045 1047 parse and apply a template
1046 1048 debuguigetpass
1047 1049 show prompt to type password
1048 1050 debuguiprompt
1049 1051 show plain prompt
1050 1052 debugupdatecaches
1051 1053 warm all known caches in the repository
1052 1054 debugupgraderepo
1053 1055 upgrade a repository to use different features
1054 1056 debugwalk show how files match on given patterns
1055 1057 debugwhyunstable
1056 1058 explain instabilities of a changeset
1057 1059 debugwireargs
1058 1060 (no help text available)
1059 1061 debugwireproto
1060 1062 send wire protocol commands to a server
1061 1063
1062 1064 (use 'hg help -v debug' to show built-in aliases and global options)
1063 1065
1064 1066 internals topic renders index of available sub-topics
1065 1067
1066 1068 $ hg help internals
1067 1069 Technical implementation topics
1068 1070 """""""""""""""""""""""""""""""
1069 1071
1070 1072 To access a subtopic, use "hg help internals.{subtopic-name}"
1071 1073
1072 1074 bundle2 Bundle2
1073 1075 bundles Bundles
1074 1076 cbor CBOR
1075 1077 censor Censor
1076 1078 changegroups Changegroups
1077 1079 config Config Registrar
1078 1080 extensions Extension API
1079 1081 requirements Repository Requirements
1080 1082 revlogs Revision Logs
1081 1083 wireprotocol Wire Protocol
1082 1084 wireprotocolrpc
1083 1085 Wire Protocol RPC
1084 1086 wireprotocolv2
1085 1087 Wire Protocol Version 2
1086 1088
1087 1089 sub-topics can be accessed
1088 1090
1089 1091 $ hg help internals.changegroups
1090 1092 Changegroups
1091 1093 """"""""""""
1092 1094
1093 1095 Changegroups are representations of repository revlog data, specifically
1094 1096 the changelog data, root/flat manifest data, treemanifest data, and
1095 1097 filelogs.
1096 1098
1097 1099 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1098 1100 level, versions "1" and "2" are almost exactly the same, with the only
1099 1101 difference being an additional item in the *delta header*. Version "3"
1100 1102 adds support for storage flags in the *delta header* and optionally
1101 1103 exchanging treemanifests (enabled by setting an option on the
1102 1104 "changegroup" part in the bundle2).
1103 1105
1104 1106 Changegroups when not exchanging treemanifests consist of 3 logical
1105 1107 segments:
1106 1108
1107 1109 +---------------------------------+
1108 1110 | | | |
1109 1111 | changeset | manifest | filelogs |
1110 1112 | | | |
1111 1113 | | | |
1112 1114 +---------------------------------+
1113 1115
1114 1116 When exchanging treemanifests, there are 4 logical segments:
1115 1117
1116 1118 +-------------------------------------------------+
1117 1119 | | | | |
1118 1120 | changeset | root | treemanifests | filelogs |
1119 1121 | | manifest | | |
1120 1122 | | | | |
1121 1123 +-------------------------------------------------+
1122 1124
1123 1125 The principle building block of each segment is a *chunk*. A *chunk* is a
1124 1126 framed piece of data:
1125 1127
1126 1128 +---------------------------------------+
1127 1129 | | |
1128 1130 | length | data |
1129 1131 | (4 bytes) | (<length - 4> bytes) |
1130 1132 | | |
1131 1133 +---------------------------------------+
1132 1134
1133 1135 All integers are big-endian signed integers. Each chunk starts with a
1134 1136 32-bit integer indicating the length of the entire chunk (including the
1135 1137 length field itself).
1136 1138
1137 1139 There is a special case chunk that has a value of 0 for the length
1138 1140 ("0x00000000"). We call this an *empty chunk*.
1139 1141
1140 1142 Delta Groups
1141 1143 ============
1142 1144
1143 1145 A *delta group* expresses the content of a revlog as a series of deltas,
1144 1146 or patches against previous revisions.
1145 1147
1146 1148 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1147 1149 to signal the end of the delta group:
1148 1150
1149 1151 +------------------------------------------------------------------------+
1150 1152 | | | | | |
1151 1153 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1152 1154 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1153 1155 | | | | | |
1154 1156 +------------------------------------------------------------------------+
1155 1157
1156 1158 Each *chunk*'s data consists of the following:
1157 1159
1158 1160 +---------------------------------------+
1159 1161 | | |
1160 1162 | delta header | delta data |
1161 1163 | (various by version) | (various) |
1162 1164 | | |
1163 1165 +---------------------------------------+
1164 1166
1165 1167 The *delta data* is a series of *delta*s that describe a diff from an
1166 1168 existing entry (either that the recipient already has, or previously
1167 1169 specified in the bundle/changegroup).
1168 1170
1169 1171 The *delta header* is different between versions "1", "2", and "3" of the
1170 1172 changegroup format.
1171 1173
1172 1174 Version 1 (headerlen=80):
1173 1175
1174 1176 +------------------------------------------------------+
1175 1177 | | | | |
1176 1178 | node | p1 node | p2 node | link node |
1177 1179 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1178 1180 | | | | |
1179 1181 +------------------------------------------------------+
1180 1182
1181 1183 Version 2 (headerlen=100):
1182 1184
1183 1185 +------------------------------------------------------------------+
1184 1186 | | | | | |
1185 1187 | node | p1 node | p2 node | base node | link node |
1186 1188 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1187 1189 | | | | | |
1188 1190 +------------------------------------------------------------------+
1189 1191
1190 1192 Version 3 (headerlen=102):
1191 1193
1192 1194 +------------------------------------------------------------------------------+
1193 1195 | | | | | | |
1194 1196 | node | p1 node | p2 node | base node | link node | flags |
1195 1197 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1196 1198 | | | | | | |
1197 1199 +------------------------------------------------------------------------------+
1198 1200
1199 1201 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1200 1202 contain a series of *delta*s, densely packed (no separators). These deltas
1201 1203 describe a diff from an existing entry (either that the recipient already
1202 1204 has, or previously specified in the bundle/changegroup). The format is
1203 1205 described more fully in "hg help internals.bdiff", but briefly:
1204 1206
1205 1207 +---------------------------------------------------------------+
1206 1208 | | | | |
1207 1209 | start offset | end offset | new length | content |
1208 1210 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1209 1211 | | | | |
1210 1212 +---------------------------------------------------------------+
1211 1213
1212 1214 Please note that the length field in the delta data does *not* include
1213 1215 itself.
1214 1216
1215 1217 In version 1, the delta is always applied against the previous node from
1216 1218 the changegroup or the first parent if this is the first entry in the
1217 1219 changegroup.
1218 1220
1219 1221 In version 2 and up, the delta base node is encoded in the entry in the
1220 1222 changegroup. This allows the delta to be expressed against any parent,
1221 1223 which can result in smaller deltas and more efficient encoding of data.
1222 1224
1223 1225 The *flags* field holds bitwise flags affecting the processing of revision
1224 1226 data. The following flags are defined:
1225 1227
1226 1228 32768
1227 1229 Censored revision. The revision's fulltext has been replaced by censor
1228 1230 metadata. May only occur on file revisions.
1229 1231
1230 1232 16384
1231 1233 Ellipsis revision. Revision hash does not match data (likely due to
1232 1234 rewritten parents).
1233 1235
1234 1236 8192
1235 1237 Externally stored. The revision fulltext contains "key:value" "\n"
1236 1238 delimited metadata defining an object stored elsewhere. Used by the LFS
1237 1239 extension.
1238 1240
1239 1241 For historical reasons, the integer values are identical to revlog version
1240 1242 1 per-revision storage flags and correspond to bits being set in this
1241 1243 2-byte field. Bits were allocated starting from the most-significant bit,
1242 1244 hence the reverse ordering and allocation of these flags.
1243 1245
1244 1246 Changeset Segment
1245 1247 =================
1246 1248
1247 1249 The *changeset segment* consists of a single *delta group* holding
1248 1250 changelog data. The *empty chunk* at the end of the *delta group* denotes
1249 1251 the boundary to the *manifest segment*.
1250 1252
1251 1253 Manifest Segment
1252 1254 ================
1253 1255
1254 1256 The *manifest segment* consists of a single *delta group* holding manifest
1255 1257 data. If treemanifests are in use, it contains only the manifest for the
1256 1258 root directory of the repository. Otherwise, it contains the entire
1257 1259 manifest data. The *empty chunk* at the end of the *delta group* denotes
1258 1260 the boundary to the next segment (either the *treemanifests segment* or
1259 1261 the *filelogs segment*, depending on version and the request options).
1260 1262
1261 1263 Treemanifests Segment
1262 1264 ---------------------
1263 1265
1264 1266 The *treemanifests segment* only exists in changegroup version "3", and
1265 1267 only if the 'treemanifest' param is part of the bundle2 changegroup part
1266 1268 (it is not possible to use changegroup version 3 outside of bundle2).
1267 1269 Aside from the filenames in the *treemanifests segment* containing a
1268 1270 trailing "/" character, it behaves identically to the *filelogs segment*
1269 1271 (see below). The final sub-segment is followed by an *empty chunk*
1270 1272 (logically, a sub-segment with filename size 0). This denotes the boundary
1271 1273 to the *filelogs segment*.
1272 1274
1273 1275 Filelogs Segment
1274 1276 ================
1275 1277
1276 1278 The *filelogs segment* consists of multiple sub-segments, each
1277 1279 corresponding to an individual file whose data is being described:
1278 1280
1279 1281 +--------------------------------------------------+
1280 1282 | | | | | |
1281 1283 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1282 1284 | | | | | (4 bytes) |
1283 1285 | | | | | |
1284 1286 +--------------------------------------------------+
1285 1287
1286 1288 The final filelog sub-segment is followed by an *empty chunk* (logically,
1287 1289 a sub-segment with filename size 0). This denotes the end of the segment
1288 1290 and of the overall changegroup.
1289 1291
1290 1292 Each filelog sub-segment consists of the following:
1291 1293
1292 1294 +------------------------------------------------------+
1293 1295 | | | |
1294 1296 | filename length | filename | delta group |
1295 1297 | (4 bytes) | (<length - 4> bytes) | (various) |
1296 1298 | | | |
1297 1299 +------------------------------------------------------+
1298 1300
1299 1301 That is, a *chunk* consisting of the filename (not terminated or padded)
1300 1302 followed by N chunks constituting the *delta group* for this file. The
1301 1303 *empty chunk* at the end of each *delta group* denotes the boundary to the
1302 1304 next filelog sub-segment.
1303 1305
1304 1306 test advanced, deprecated and experimental options are hidden in command help
1305 1307 $ hg help debugoptADV
1306 1308 hg debugoptADV
1307 1309
1308 1310 (no help text available)
1309 1311
1310 1312 options:
1311 1313
1312 1314 (some details hidden, use --verbose to show complete help)
1313 1315 $ hg help debugoptDEP
1314 1316 hg debugoptDEP
1315 1317
1316 1318 (no help text available)
1317 1319
1318 1320 options:
1319 1321
1320 1322 (some details hidden, use --verbose to show complete help)
1321 1323
1322 1324 $ hg help debugoptEXP
1323 1325 hg debugoptEXP
1324 1326
1325 1327 (no help text available)
1326 1328
1327 1329 options:
1328 1330
1329 1331 (some details hidden, use --verbose to show complete help)
1330 1332
1331 1333 test advanced, deprecated and experimental options are shown with -v
1332 1334 $ hg help -v debugoptADV | grep aopt
1333 1335 --aopt option is (ADVANCED)
1334 1336 $ hg help -v debugoptDEP | grep dopt
1335 1337 --dopt option is (DEPRECATED)
1336 1338 $ hg help -v debugoptEXP | grep eopt
1337 1339 --eopt option is (EXPERIMENTAL)
1338 1340
1339 1341 #if gettext
1340 1342 test deprecated option is hidden with translation with untranslated description
1341 1343 (use many globy for not failing on changed transaction)
1342 1344 $ LANGUAGE=sv hg help debugoptDEP
1343 1345 hg debugoptDEP
1344 1346
1345 1347 (*) (glob)
1346 1348
1347 1349 options:
1348 1350
1349 1351 (some details hidden, use --verbose to show complete help)
1350 1352 #endif
1351 1353
1352 1354 Test commands that collide with topics (issue4240)
1353 1355
1354 1356 $ hg config -hq
1355 1357 hg config [-u] [NAME]...
1356 1358
1357 1359 show combined config settings from all hgrc files
1358 1360 $ hg showconfig -hq
1359 1361 hg config [-u] [NAME]...
1360 1362
1361 1363 show combined config settings from all hgrc files
1362 1364
1363 1365 Test a help topic
1364 1366
1365 1367 $ hg help dates
1366 1368 Date Formats
1367 1369 """"""""""""
1368 1370
1369 1371 Some commands allow the user to specify a date, e.g.:
1370 1372
1371 1373 - backout, commit, import, tag: Specify the commit date.
1372 1374 - log, revert, update: Select revision(s) by date.
1373 1375
1374 1376 Many date formats are valid. Here are some examples:
1375 1377
1376 1378 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1377 1379 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1378 1380 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1379 1381 - "Dec 6" (midnight)
1380 1382 - "13:18" (today assumed)
1381 1383 - "3:39" (3:39AM assumed)
1382 1384 - "3:39pm" (15:39)
1383 1385 - "2006-12-06 13:18:29" (ISO 8601 format)
1384 1386 - "2006-12-6 13:18"
1385 1387 - "2006-12-6"
1386 1388 - "12-6"
1387 1389 - "12/6"
1388 1390 - "12/6/6" (Dec 6 2006)
1389 1391 - "today" (midnight)
1390 1392 - "yesterday" (midnight)
1391 1393 - "now" - right now
1392 1394
1393 1395 Lastly, there is Mercurial's internal format:
1394 1396
1395 1397 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1396 1398
1397 1399 This is the internal representation format for dates. The first number is
1398 1400 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1399 1401 is the offset of the local timezone, in seconds west of UTC (negative if
1400 1402 the timezone is east of UTC).
1401 1403
1402 1404 The log command also accepts date ranges:
1403 1405
1404 1406 - "<DATE" - at or before a given date/time
1405 1407 - ">DATE" - on or after a given date/time
1406 1408 - "DATE to DATE" - a date range, inclusive
1407 1409 - "-DAYS" - within a given number of days of today
1408 1410
1409 1411 Test repeated config section name
1410 1412
1411 1413 $ hg help config.host
1412 1414 "http_proxy.host"
1413 1415 Host name and (optional) port of the proxy server, for example
1414 1416 "myproxy:8000".
1415 1417
1416 1418 "smtp.host"
1417 1419 Host name of mail server, e.g. "mail.example.com".
1418 1420
1419 1421
1420 1422 Test section name with dot
1421 1423
1422 1424 $ hg help config.ui.username
1423 1425 "ui.username"
1424 1426 The committer of a changeset created when running "commit". Typically
1425 1427 a person's name and email address, e.g. "Fred Widget
1426 1428 <fred@example.com>". Environment variables in the username are
1427 1429 expanded.
1428 1430
1429 1431 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1430 1432 empty, e.g. if the system admin set "username =" in the system hgrc,
1431 1433 it has to be specified manually or in a different hgrc file)
1432 1434
1433 1435
1434 1436 $ hg help config.annotate.git
1435 1437 abort: help section not found: config.annotate.git
1436 1438 [255]
1437 1439
1438 1440 $ hg help config.update.check
1439 1441 "commands.update.check"
1440 1442 Determines what level of checking 'hg update' will perform before
1441 1443 moving to a destination revision. Valid values are "abort", "none",
1442 1444 "linear", and "noconflict". "abort" always fails if the working
1443 1445 directory has uncommitted changes. "none" performs no checking, and
1444 1446 may result in a merge with uncommitted changes. "linear" allows any
1445 1447 update as long as it follows a straight line in the revision history,
1446 1448 and may trigger a merge with uncommitted changes. "noconflict" will
1447 1449 allow any update which would not trigger a merge with uncommitted
1448 1450 changes, if any are present. (default: "linear")
1449 1451
1450 1452
1451 1453 $ hg help config.commands.update.check
1452 1454 "commands.update.check"
1453 1455 Determines what level of checking 'hg update' will perform before
1454 1456 moving to a destination revision. Valid values are "abort", "none",
1455 1457 "linear", and "noconflict". "abort" always fails if the working
1456 1458 directory has uncommitted changes. "none" performs no checking, and
1457 1459 may result in a merge with uncommitted changes. "linear" allows any
1458 1460 update as long as it follows a straight line in the revision history,
1459 1461 and may trigger a merge with uncommitted changes. "noconflict" will
1460 1462 allow any update which would not trigger a merge with uncommitted
1461 1463 changes, if any are present. (default: "linear")
1462 1464
1463 1465
1464 1466 $ hg help config.ommands.update.check
1465 1467 abort: help section not found: config.ommands.update.check
1466 1468 [255]
1467 1469
1468 1470 Unrelated trailing paragraphs shouldn't be included
1469 1471
1470 1472 $ hg help config.extramsg | grep '^$'
1471 1473
1472 1474
1473 1475 Test capitalized section name
1474 1476
1475 1477 $ hg help scripting.HGPLAIN > /dev/null
1476 1478
1477 1479 Help subsection:
1478 1480
1479 1481 $ hg help config.charsets |grep "Email example:" > /dev/null
1480 1482 [1]
1481 1483
1482 1484 Show nested definitions
1483 1485 ("profiling.type"[break]"ls"[break]"stat"[break])
1484 1486
1485 1487 $ hg help config.type | egrep '^$'|wc -l
1486 1488 \s*3 (re)
1487 1489
1488 1490 $ hg help config.profiling.type.ls
1489 1491 "profiling.type.ls"
1490 1492 Use Python's built-in instrumenting profiler. This profiler works on
1491 1493 all platforms, but each line number it reports is the first line of
1492 1494 a function. This restriction makes it difficult to identify the
1493 1495 expensive parts of a non-trivial function.
1494 1496
1495 1497
1496 1498 Separate sections from subsections
1497 1499
1498 1500 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1499 1501 "format"
1500 1502 --------
1501 1503
1502 1504 "usegeneraldelta"
1503 1505
1504 1506 "dotencode"
1505 1507
1506 1508 "usefncache"
1507 1509
1508 1510 "usestore"
1509 1511
1510 1512 "sparse-revlog"
1511 1513
1512 1514 "profiling"
1513 1515 -----------
1514 1516
1515 1517 "format"
1516 1518
1517 1519 "progress"
1518 1520 ----------
1519 1521
1520 1522 "format"
1521 1523
1522 1524
1523 1525 Last item in help config.*:
1524 1526
1525 1527 $ hg help config.`hg help config|grep '^ "'| \
1526 1528 > tail -1|sed 's![ "]*!!g'`| \
1527 1529 > grep 'hg help -c config' > /dev/null
1528 1530 [1]
1529 1531
1530 1532 note to use help -c for general hg help config:
1531 1533
1532 1534 $ hg help config |grep 'hg help -c config' > /dev/null
1533 1535
1534 1536 Test templating help
1535 1537
1536 1538 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1537 1539 desc String. The text of the changeset description.
1538 1540 diffstat String. Statistics of changes with the following format:
1539 1541 firstline Any text. Returns the first line of text.
1540 1542 nonempty Any text. Returns '(none)' if the string is empty.
1541 1543
1542 1544 Test deprecated items
1543 1545
1544 1546 $ hg help -v templating | grep currentbookmark
1545 1547 currentbookmark
1546 1548 $ hg help templating | (grep currentbookmark || true)
1547 1549
1548 1550 Test help hooks
1549 1551
1550 1552 $ cat > helphook1.py <<EOF
1551 1553 > from mercurial import help
1552 1554 >
1553 1555 > def rewrite(ui, topic, doc):
1554 1556 > return doc + b'\nhelphook1\n'
1555 1557 >
1556 1558 > def extsetup(ui):
1557 1559 > help.addtopichook(b'revisions', rewrite)
1558 1560 > EOF
1559 1561 $ cat > helphook2.py <<EOF
1560 1562 > from mercurial import help
1561 1563 >
1562 1564 > def rewrite(ui, topic, doc):
1563 1565 > return doc + b'\nhelphook2\n'
1564 1566 >
1565 1567 > def extsetup(ui):
1566 1568 > help.addtopichook(b'revisions', rewrite)
1567 1569 > EOF
1568 1570 $ echo '[extensions]' >> $HGRCPATH
1569 1571 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1570 1572 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1571 1573 $ hg help revsets | grep helphook
1572 1574 helphook1
1573 1575 helphook2
1574 1576
1575 1577 help -c should only show debug --debug
1576 1578
1577 1579 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1578 1580 [1]
1579 1581
1580 1582 help -c should only show deprecated for -v
1581 1583
1582 1584 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1583 1585 [1]
1584 1586
1585 1587 Test -s / --system
1586 1588
1587 1589 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1588 1590 > wc -l | sed -e 's/ //g'
1589 1591 0
1590 1592 $ hg help config.files --system unix | grep 'USER' | \
1591 1593 > wc -l | sed -e 's/ //g'
1592 1594 0
1593 1595
1594 1596 Test -e / -c / -k combinations
1595 1597
1596 1598 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1597 1599 Commands:
1598 1600 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1599 1601 Extensions:
1600 1602 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1601 1603 Topics:
1602 1604 Commands:
1603 1605 Extensions:
1604 1606 Extension Commands:
1605 1607 $ hg help -c schemes
1606 1608 abort: no such help topic: schemes
1607 1609 (try 'hg help --keyword schemes')
1608 1610 [255]
1609 1611 $ hg help -e schemes |head -1
1610 1612 schemes extension - extend schemes with shortcuts to repository swarms
1611 1613 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1612 1614 Commands:
1613 1615 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1614 1616 Extensions:
1615 1617 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1616 1618 Extensions:
1617 1619 Commands:
1618 1620 $ hg help -c commit > /dev/null
1619 1621 $ hg help -e -c commit > /dev/null
1620 1622 $ hg help -e commit
1621 1623 abort: no such help topic: commit
1622 1624 (try 'hg help --keyword commit')
1623 1625 [255]
1624 1626
1625 1627 Test keyword search help
1626 1628
1627 1629 $ cat > prefixedname.py <<EOF
1628 1630 > '''matched against word "clone"
1629 1631 > '''
1630 1632 > EOF
1631 1633 $ echo '[extensions]' >> $HGRCPATH
1632 1634 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1633 1635 $ hg help -k clone
1634 1636 Topics:
1635 1637
1636 1638 config Configuration Files
1637 1639 extensions Using Additional Features
1638 1640 glossary Glossary
1639 1641 phases Working with Phases
1640 1642 subrepos Subrepositories
1641 1643 urls URL Paths
1642 1644
1643 1645 Commands:
1644 1646
1645 1647 bookmarks create a new bookmark or list existing bookmarks
1646 1648 clone make a copy of an existing repository
1647 1649 paths show aliases for remote repositories
1648 1650 pull pull changes from the specified source
1649 1651 update update working directory (or switch revisions)
1650 1652
1651 1653 Extensions:
1652 1654
1653 1655 clonebundles advertise pre-generated bundles to seed clones
1654 1656 narrow create clones which fetch history data for subset of files
1655 1657 (EXPERIMENTAL)
1656 1658 prefixedname matched against word "clone"
1657 1659 relink recreates hardlinks between repository clones
1658 1660
1659 1661 Extension Commands:
1660 1662
1661 1663 qclone clone main and patch repository at same time
1662 1664
1663 1665 Test unfound topic
1664 1666
1665 1667 $ hg help nonexistingtopicthatwillneverexisteverever
1666 1668 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1667 1669 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1668 1670 [255]
1669 1671
1670 1672 Test unfound keyword
1671 1673
1672 1674 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1673 1675 abort: no matches
1674 1676 (try 'hg help' for a list of topics)
1675 1677 [255]
1676 1678
1677 1679 Test omit indicating for help
1678 1680
1679 1681 $ cat > addverboseitems.py <<EOF
1680 1682 > r'''extension to test omit indicating.
1681 1683 >
1682 1684 > This paragraph is never omitted (for extension)
1683 1685 >
1684 1686 > .. container:: verbose
1685 1687 >
1686 1688 > This paragraph is omitted,
1687 1689 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1688 1690 >
1689 1691 > This paragraph is never omitted, too (for extension)
1690 1692 > '''
1691 1693 > from __future__ import absolute_import
1692 1694 > from mercurial import commands, help
1693 1695 > testtopic = br"""This paragraph is never omitted (for topic).
1694 1696 >
1695 1697 > .. container:: verbose
1696 1698 >
1697 1699 > This paragraph is omitted,
1698 1700 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1699 1701 >
1700 1702 > This paragraph is never omitted, too (for topic)
1701 1703 > """
1702 1704 > def extsetup(ui):
1703 1705 > help.helptable.append(([b"topic-containing-verbose"],
1704 1706 > b"This is the topic to test omit indicating.",
1705 1707 > lambda ui: testtopic))
1706 1708 > EOF
1707 1709 $ echo '[extensions]' >> $HGRCPATH
1708 1710 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1709 1711 $ hg help addverboseitems
1710 1712 addverboseitems extension - extension to test omit indicating.
1711 1713
1712 1714 This paragraph is never omitted (for extension)
1713 1715
1714 1716 This paragraph is never omitted, too (for extension)
1715 1717
1716 1718 (some details hidden, use --verbose to show complete help)
1717 1719
1718 1720 no commands defined
1719 1721 $ hg help -v addverboseitems
1720 1722 addverboseitems extension - extension to test omit indicating.
1721 1723
1722 1724 This paragraph is never omitted (for extension)
1723 1725
1724 1726 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1725 1727 extension)
1726 1728
1727 1729 This paragraph is never omitted, too (for extension)
1728 1730
1729 1731 no commands defined
1730 1732 $ hg help topic-containing-verbose
1731 1733 This is the topic to test omit indicating.
1732 1734 """"""""""""""""""""""""""""""""""""""""""
1733 1735
1734 1736 This paragraph is never omitted (for topic).
1735 1737
1736 1738 This paragraph is never omitted, too (for topic)
1737 1739
1738 1740 (some details hidden, use --verbose to show complete help)
1739 1741 $ hg help -v topic-containing-verbose
1740 1742 This is the topic to test omit indicating.
1741 1743 """"""""""""""""""""""""""""""""""""""""""
1742 1744
1743 1745 This paragraph is never omitted (for topic).
1744 1746
1745 1747 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1746 1748 topic)
1747 1749
1748 1750 This paragraph is never omitted, too (for topic)
1749 1751
1750 1752 Test section lookup
1751 1753
1752 1754 $ hg help revset.merge
1753 1755 "merge()"
1754 1756 Changeset is a merge changeset.
1755 1757
1756 1758 $ hg help glossary.dag
1757 1759 DAG
1758 1760 The repository of changesets of a distributed version control system
1759 1761 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1760 1762 of nodes and edges, where nodes correspond to changesets and edges
1761 1763 imply a parent -> child relation. This graph can be visualized by
1762 1764 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1763 1765 limited by the requirement for children to have at most two parents.
1764 1766
1765 1767
1766 1768 $ hg help hgrc.paths
1767 1769 "paths"
1768 1770 -------
1769 1771
1770 1772 Assigns symbolic names and behavior to repositories.
1771 1773
1772 1774 Options are symbolic names defining the URL or directory that is the
1773 1775 location of the repository. Example:
1774 1776
1775 1777 [paths]
1776 1778 my_server = https://example.com/my_repo
1777 1779 local_path = /home/me/repo
1778 1780
1779 1781 These symbolic names can be used from the command line. To pull from
1780 1782 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1781 1783 local_path'.
1782 1784
1783 1785 Options containing colons (":") denote sub-options that can influence
1784 1786 behavior for that specific path. Example:
1785 1787
1786 1788 [paths]
1787 1789 my_server = https://example.com/my_path
1788 1790 my_server:pushurl = ssh://example.com/my_path
1789 1791
1790 1792 The following sub-options can be defined:
1791 1793
1792 1794 "pushurl"
1793 1795 The URL to use for push operations. If not defined, the location
1794 1796 defined by the path's main entry is used.
1795 1797
1796 1798 "pushrev"
1797 1799 A revset defining which revisions to push by default.
1798 1800
1799 1801 When 'hg push' is executed without a "-r" argument, the revset defined
1800 1802 by this sub-option is evaluated to determine what to push.
1801 1803
1802 1804 For example, a value of "." will push the working directory's revision
1803 1805 by default.
1804 1806
1805 1807 Revsets specifying bookmarks will not result in the bookmark being
1806 1808 pushed.
1807 1809
1808 1810 The following special named paths exist:
1809 1811
1810 1812 "default"
1811 1813 The URL or directory to use when no source or remote is specified.
1812 1814
1813 1815 'hg clone' will automatically define this path to the location the
1814 1816 repository was cloned from.
1815 1817
1816 1818 "default-push"
1817 1819 (deprecated) The URL or directory for the default 'hg push' location.
1818 1820 "default:pushurl" should be used instead.
1819 1821
1820 1822 $ hg help glossary.mcguffin
1821 1823 abort: help section not found: glossary.mcguffin
1822 1824 [255]
1823 1825
1824 1826 $ hg help glossary.mc.guffin
1825 1827 abort: help section not found: glossary.mc.guffin
1826 1828 [255]
1827 1829
1828 1830 $ hg help template.files
1829 1831 files List of strings. All files modified, added, or removed by
1830 1832 this changeset.
1831 1833 files(pattern)
1832 1834 All files of the current changeset matching the pattern. See
1833 1835 'hg help patterns'.
1834 1836
1835 1837 Test section lookup by translated message
1836 1838
1837 1839 str.lower() instead of encoding.lower(str) on translated message might
1838 1840 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1839 1841 as the second or later byte of multi-byte character.
1840 1842
1841 1843 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1842 1844 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1843 1845 replacement makes message meaningless.
1844 1846
1845 1847 This tests that section lookup by translated string isn't broken by
1846 1848 such str.lower().
1847 1849
1848 1850 $ "$PYTHON" <<EOF
1849 1851 > def escape(s):
1850 1852 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1851 1853 > # translation of "record" in ja_JP.cp932
1852 1854 > upper = b"\x8bL\x98^"
1853 1855 > # str.lower()-ed section name should be treated as different one
1854 1856 > lower = b"\x8bl\x98^"
1855 1857 > with open('ambiguous.py', 'wb') as fp:
1856 1858 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1857 1859 > u'''summary of extension
1858 1860 >
1859 1861 > %s
1860 1862 > ----
1861 1863 >
1862 1864 > Upper name should show only this message
1863 1865 >
1864 1866 > %s
1865 1867 > ----
1866 1868 >
1867 1869 > Lower name should show only this message
1868 1870 >
1869 1871 > subsequent section
1870 1872 > ------------------
1871 1873 >
1872 1874 > This should be hidden at 'hg help ambiguous' with section name.
1873 1875 > '''
1874 1876 > """ % (escape(upper), escape(lower)))
1875 1877 > EOF
1876 1878
1877 1879 $ cat >> $HGRCPATH <<EOF
1878 1880 > [extensions]
1879 1881 > ambiguous = ./ambiguous.py
1880 1882 > EOF
1881 1883
1882 1884 $ "$PYTHON" <<EOF | sh
1883 1885 > from mercurial import pycompat
1884 1886 > upper = b"\x8bL\x98^"
1885 1887 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1886 1888 > EOF
1887 1889 \x8bL\x98^ (esc)
1888 1890 ----
1889 1891
1890 1892 Upper name should show only this message
1891 1893
1892 1894
1893 1895 $ "$PYTHON" <<EOF | sh
1894 1896 > from mercurial import pycompat
1895 1897 > lower = b"\x8bl\x98^"
1896 1898 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1897 1899 > EOF
1898 1900 \x8bl\x98^ (esc)
1899 1901 ----
1900 1902
1901 1903 Lower name should show only this message
1902 1904
1903 1905
1904 1906 $ cat >> $HGRCPATH <<EOF
1905 1907 > [extensions]
1906 1908 > ambiguous = !
1907 1909 > EOF
1908 1910
1909 1911 Show help content of disabled extensions
1910 1912
1911 1913 $ cat >> $HGRCPATH <<EOF
1912 1914 > [extensions]
1913 1915 > ambiguous = !./ambiguous.py
1914 1916 > EOF
1915 1917 $ hg help -e ambiguous
1916 1918 ambiguous extension - (no help text available)
1917 1919
1918 1920 (use 'hg help extensions' for information on enabling extensions)
1919 1921
1920 1922 Test dynamic list of merge tools only shows up once
1921 1923 $ hg help merge-tools
1922 1924 Merge Tools
1923 1925 """""""""""
1924 1926
1925 1927 To merge files Mercurial uses merge tools.
1926 1928
1927 1929 A merge tool combines two different versions of a file into a merged file.
1928 1930 Merge tools are given the two files and the greatest common ancestor of
1929 1931 the two file versions, so they can determine the changes made on both
1930 1932 branches.
1931 1933
1932 1934 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1933 1935 backout' and in several extensions.
1934 1936
1935 1937 Usually, the merge tool tries to automatically reconcile the files by
1936 1938 combining all non-overlapping changes that occurred separately in the two
1937 1939 different evolutions of the same initial base file. Furthermore, some
1938 1940 interactive merge programs make it easier to manually resolve conflicting
1939 1941 merges, either in a graphical way, or by inserting some conflict markers.
1940 1942 Mercurial does not include any interactive merge programs but relies on
1941 1943 external tools for that.
1942 1944
1943 1945 Available merge tools
1944 1946 =====================
1945 1947
1946 1948 External merge tools and their properties are configured in the merge-
1947 1949 tools configuration section - see hgrc(5) - but they can often just be
1948 1950 named by their executable.
1949 1951
1950 1952 A merge tool is generally usable if its executable can be found on the
1951 1953 system and if it can handle the merge. The executable is found if it is an
1952 1954 absolute or relative executable path or the name of an application in the
1953 1955 executable search path. The tool is assumed to be able to handle the merge
1954 1956 if it can handle symlinks if the file is a symlink, if it can handle
1955 1957 binary files if the file is binary, and if a GUI is available if the tool
1956 1958 requires a GUI.
1957 1959
1958 1960 There are some internal merge tools which can be used. The internal merge
1959 1961 tools are:
1960 1962
1961 1963 ":dump"
1962 1964 Creates three versions of the files to merge, containing the contents of
1963 1965 local, other and base. These files can then be used to perform a merge
1964 1966 manually. If the file to be merged is named "a.txt", these files will
1965 1967 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1966 1968 they will be placed in the same directory as "a.txt".
1967 1969
1968 1970 This implies premerge. Therefore, files aren't dumped, if premerge runs
1969 1971 successfully. Use :forcedump to forcibly write files out.
1970 1972
1971 1973 (actual capabilities: binary, symlink)
1972 1974
1973 1975 ":fail"
1974 1976 Rather than attempting to merge files that were modified on both
1975 1977 branches, it marks them as unresolved. The resolve command must be used
1976 1978 to resolve these conflicts.
1977 1979
1978 1980 (actual capabilities: binary, symlink)
1979 1981
1980 1982 ":forcedump"
1981 1983 Creates three versions of the files as same as :dump, but omits
1982 1984 premerge.
1983 1985
1984 1986 (actual capabilities: binary, symlink)
1985 1987
1986 1988 ":local"
1987 1989 Uses the local 'p1()' version of files as the merged version.
1988 1990
1989 1991 (actual capabilities: binary, symlink)
1990 1992
1991 1993 ":merge"
1992 1994 Uses the internal non-interactive simple merge algorithm for merging
1993 1995 files. It will fail if there are any conflicts and leave markers in the
1994 1996 partially merged file. Markers will have two sections, one for each side
1995 1997 of merge.
1996 1998
1997 1999 ":merge-local"
1998 2000 Like :merge, but resolve all conflicts non-interactively in favor of the
1999 2001 local 'p1()' changes.
2000 2002
2001 2003 ":merge-other"
2002 2004 Like :merge, but resolve all conflicts non-interactively in favor of the
2003 2005 other 'p2()' changes.
2004 2006
2005 2007 ":merge3"
2006 2008 Uses the internal non-interactive simple merge algorithm for merging
2007 2009 files. It will fail if there are any conflicts and leave markers in the
2008 2010 partially merged file. Marker will have three sections, one from each
2009 2011 side of the merge and one for the base content.
2010 2012
2011 2013 ":other"
2012 2014 Uses the other 'p2()' version of files as the merged version.
2013 2015
2014 2016 (actual capabilities: binary, symlink)
2015 2017
2016 2018 ":prompt"
2017 2019 Asks the user which of the local 'p1()' or the other 'p2()' version to
2018 2020 keep as the merged version.
2019 2021
2020 2022 (actual capabilities: binary, symlink)
2021 2023
2022 2024 ":tagmerge"
2023 2025 Uses the internal tag merge algorithm (experimental).
2024 2026
2025 2027 ":union"
2026 2028 Uses the internal non-interactive simple merge algorithm for merging
2027 2029 files. It will use both left and right sides for conflict regions. No
2028 2030 markers are inserted.
2029 2031
2030 2032 Internal tools are always available and do not require a GUI but will by
2031 2033 default not handle symlinks or binary files. See next section for detail
2032 2034 about "actual capabilities" described above.
2033 2035
2034 2036 Choosing a merge tool
2035 2037 =====================
2036 2038
2037 2039 Mercurial uses these rules when deciding which merge tool to use:
2038 2040
2039 2041 1. If a tool has been specified with the --tool option to merge or
2040 2042 resolve, it is used. If it is the name of a tool in the merge-tools
2041 2043 configuration, its configuration is used. Otherwise the specified tool
2042 2044 must be executable by the shell.
2043 2045 2. If the "HGMERGE" environment variable is present, its value is used and
2044 2046 must be executable by the shell.
2045 2047 3. If the filename of the file to be merged matches any of the patterns in
2046 2048 the merge-patterns configuration section, the first usable merge tool
2047 2049 corresponding to a matching pattern is used.
2048 2050 4. If ui.merge is set it will be considered next. If the value is not the
2049 2051 name of a configured tool, the specified value is used and must be
2050 2052 executable by the shell. Otherwise the named tool is used if it is
2051 2053 usable.
2052 2054 5. If any usable merge tools are present in the merge-tools configuration
2053 2055 section, the one with the highest priority is used.
2054 2056 6. If a program named "hgmerge" can be found on the system, it is used -
2055 2057 but it will by default not be used for symlinks and binary files.
2056 2058 7. If the file to be merged is not binary and is not a symlink, then
2057 2059 internal ":merge" is used.
2058 2060 8. Otherwise, ":prompt" is used.
2059 2061
2060 2062 For historical reason, Mercurial treats merge tools as below while
2061 2063 examining rules above.
2062 2064
2063 2065 step specified via binary symlink
2064 2066 ----------------------------------
2065 2067 1. --tool o/o o/o
2066 2068 2. HGMERGE o/o o/o
2067 2069 3. merge-patterns o/o(*) x/?(*)
2068 2070 4. ui.merge x/?(*) x/?(*)
2069 2071
2070 2072 Each capability column indicates Mercurial behavior for internal/external
2071 2073 merge tools at examining each rule.
2072 2074
2073 2075 - "o": "assume that a tool has capability"
2074 2076 - "x": "assume that a tool does not have capability"
2075 2077 - "?": "check actual capability of a tool"
2076 2078
2077 2079 If "merge.strict-capability-check" configuration is true, Mercurial checks
2078 2080 capabilities of merge tools strictly in (*) cases above (= each capability
2079 2081 column becomes "?/?"). It is false by default for backward compatibility.
2080 2082
2081 2083 Note:
2082 2084 After selecting a merge program, Mercurial will by default attempt to
2083 2085 merge the files using a simple merge algorithm first. Only if it
2084 2086 doesn't succeed because of conflicting changes will Mercurial actually
2085 2087 execute the merge program. Whether to use the simple merge algorithm
2086 2088 first can be controlled by the premerge setting of the merge tool.
2087 2089 Premerge is enabled by default unless the file is binary or a symlink.
2088 2090
2089 2091 See the merge-tools and ui sections of hgrc(5) for details on the
2090 2092 configuration of merge tools.
2091 2093
2092 2094 Compression engines listed in `hg help bundlespec`
2093 2095
2094 2096 $ hg help bundlespec | grep gzip
2095 2097 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2096 2098 An algorithm that produces smaller bundles than "gzip".
2097 2099 This engine will likely produce smaller bundles than "gzip" but will be
2098 2100 "gzip"
2099 2101 better compression than "gzip". It also frequently yields better (?)
2100 2102
2101 2103 Test usage of section marks in help documents
2102 2104
2103 2105 $ cd "$TESTDIR"/../doc
2104 2106 $ "$PYTHON" check-seclevel.py
2105 2107 $ cd $TESTTMP
2106 2108
2107 2109 #if serve
2108 2110
2109 2111 Test the help pages in hgweb.
2110 2112
2111 2113 Dish up an empty repo; serve it cold.
2112 2114
2113 2115 $ hg init "$TESTTMP/test"
2114 2116 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2115 2117 $ cat hg.pid >> $DAEMON_PIDS
2116 2118
2117 2119 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2118 2120 200 Script output follows
2119 2121
2120 2122 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2121 2123 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2122 2124 <head>
2123 2125 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2124 2126 <meta name="robots" content="index, nofollow" />
2125 2127 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2126 2128 <script type="text/javascript" src="/static/mercurial.js"></script>
2127 2129
2128 2130 <title>Help: Index</title>
2129 2131 </head>
2130 2132 <body>
2131 2133
2132 2134 <div class="container">
2133 2135 <div class="menu">
2134 2136 <div class="logo">
2135 2137 <a href="https://mercurial-scm.org/">
2136 2138 <img src="/static/hglogo.png" alt="mercurial" /></a>
2137 2139 </div>
2138 2140 <ul>
2139 2141 <li><a href="/shortlog">log</a></li>
2140 2142 <li><a href="/graph">graph</a></li>
2141 2143 <li><a href="/tags">tags</a></li>
2142 2144 <li><a href="/bookmarks">bookmarks</a></li>
2143 2145 <li><a href="/branches">branches</a></li>
2144 2146 </ul>
2145 2147 <ul>
2146 2148 <li class="active">help</li>
2147 2149 </ul>
2148 2150 </div>
2149 2151
2150 2152 <div class="main">
2151 2153 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2152 2154
2153 2155 <form class="search" action="/log">
2154 2156
2155 2157 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2156 2158 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2157 2159 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2158 2160 </form>
2159 2161 <table class="bigtable">
2160 2162 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2161 2163
2162 2164 <tr><td>
2163 2165 <a href="/help/bundlespec">
2164 2166 bundlespec
2165 2167 </a>
2166 2168 </td><td>
2167 2169 Bundle File Formats
2168 2170 </td></tr>
2169 2171 <tr><td>
2170 2172 <a href="/help/color">
2171 2173 color
2172 2174 </a>
2173 2175 </td><td>
2174 2176 Colorizing Outputs
2175 2177 </td></tr>
2176 2178 <tr><td>
2177 2179 <a href="/help/config">
2178 2180 config
2179 2181 </a>
2180 2182 </td><td>
2181 2183 Configuration Files
2182 2184 </td></tr>
2183 2185 <tr><td>
2184 2186 <a href="/help/dates">
2185 2187 dates
2186 2188 </a>
2187 2189 </td><td>
2188 2190 Date Formats
2189 2191 </td></tr>
2190 2192 <tr><td>
2191 2193 <a href="/help/deprecated">
2192 2194 deprecated
2193 2195 </a>
2194 2196 </td><td>
2195 2197 Deprecated Features
2196 2198 </td></tr>
2197 2199 <tr><td>
2198 2200 <a href="/help/diffs">
2199 2201 diffs
2200 2202 </a>
2201 2203 </td><td>
2202 2204 Diff Formats
2203 2205 </td></tr>
2204 2206 <tr><td>
2205 2207 <a href="/help/environment">
2206 2208 environment
2207 2209 </a>
2208 2210 </td><td>
2209 2211 Environment Variables
2210 2212 </td></tr>
2211 2213 <tr><td>
2212 2214 <a href="/help/extensions">
2213 2215 extensions
2214 2216 </a>
2215 2217 </td><td>
2216 2218 Using Additional Features
2217 2219 </td></tr>
2218 2220 <tr><td>
2219 2221 <a href="/help/filesets">
2220 2222 filesets
2221 2223 </a>
2222 2224 </td><td>
2223 2225 Specifying File Sets
2224 2226 </td></tr>
2225 2227 <tr><td>
2226 2228 <a href="/help/flags">
2227 2229 flags
2228 2230 </a>
2229 2231 </td><td>
2230 2232 Command-line flags
2231 2233 </td></tr>
2232 2234 <tr><td>
2233 2235 <a href="/help/glossary">
2234 2236 glossary
2235 2237 </a>
2236 2238 </td><td>
2237 2239 Glossary
2238 2240 </td></tr>
2239 2241 <tr><td>
2240 2242 <a href="/help/hgignore">
2241 2243 hgignore
2242 2244 </a>
2243 2245 </td><td>
2244 2246 Syntax for Mercurial Ignore Files
2245 2247 </td></tr>
2246 2248 <tr><td>
2247 2249 <a href="/help/hgweb">
2248 2250 hgweb
2249 2251 </a>
2250 2252 </td><td>
2251 2253 Configuring hgweb
2252 2254 </td></tr>
2253 2255 <tr><td>
2254 2256 <a href="/help/internals">
2255 2257 internals
2256 2258 </a>
2257 2259 </td><td>
2258 2260 Technical implementation topics
2259 2261 </td></tr>
2260 2262 <tr><td>
2261 2263 <a href="/help/merge-tools">
2262 2264 merge-tools
2263 2265 </a>
2264 2266 </td><td>
2265 2267 Merge Tools
2266 2268 </td></tr>
2267 2269 <tr><td>
2268 2270 <a href="/help/pager">
2269 2271 pager
2270 2272 </a>
2271 2273 </td><td>
2272 2274 Pager Support
2273 2275 </td></tr>
2274 2276 <tr><td>
2275 2277 <a href="/help/patterns">
2276 2278 patterns
2277 2279 </a>
2278 2280 </td><td>
2279 2281 File Name Patterns
2280 2282 </td></tr>
2281 2283 <tr><td>
2282 2284 <a href="/help/phases">
2283 2285 phases
2284 2286 </a>
2285 2287 </td><td>
2286 2288 Working with Phases
2287 2289 </td></tr>
2288 2290 <tr><td>
2289 2291 <a href="/help/revisions">
2290 2292 revisions
2291 2293 </a>
2292 2294 </td><td>
2293 2295 Specifying Revisions
2294 2296 </td></tr>
2295 2297 <tr><td>
2296 2298 <a href="/help/scripting">
2297 2299 scripting
2298 2300 </a>
2299 2301 </td><td>
2300 2302 Using Mercurial from scripts and automation
2301 2303 </td></tr>
2302 2304 <tr><td>
2303 2305 <a href="/help/subrepos">
2304 2306 subrepos
2305 2307 </a>
2306 2308 </td><td>
2307 2309 Subrepositories
2308 2310 </td></tr>
2309 2311 <tr><td>
2310 2312 <a href="/help/templating">
2311 2313 templating
2312 2314 </a>
2313 2315 </td><td>
2314 2316 Template Usage
2315 2317 </td></tr>
2316 2318 <tr><td>
2317 2319 <a href="/help/urls">
2318 2320 urls
2319 2321 </a>
2320 2322 </td><td>
2321 2323 URL Paths
2322 2324 </td></tr>
2323 2325 <tr><td>
2324 2326 <a href="/help/topic-containing-verbose">
2325 2327 topic-containing-verbose
2326 2328 </a>
2327 2329 </td><td>
2328 2330 This is the topic to test omit indicating.
2329 2331 </td></tr>
2330 2332
2331 2333
2332 2334 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2333 2335
2334 2336 <tr><td>
2335 2337 <a href="/help/add">
2336 2338 add
2337 2339 </a>
2338 2340 </td><td>
2339 2341 add the specified files on the next commit
2340 2342 </td></tr>
2341 2343 <tr><td>
2342 2344 <a href="/help/annotate">
2343 2345 annotate
2344 2346 </a>
2345 2347 </td><td>
2346 2348 show changeset information by line for each file
2347 2349 </td></tr>
2348 2350 <tr><td>
2349 2351 <a href="/help/clone">
2350 2352 clone
2351 2353 </a>
2352 2354 </td><td>
2353 2355 make a copy of an existing repository
2354 2356 </td></tr>
2355 2357 <tr><td>
2356 2358 <a href="/help/commit">
2357 2359 commit
2358 2360 </a>
2359 2361 </td><td>
2360 2362 commit the specified files or all outstanding changes
2361 2363 </td></tr>
2362 2364 <tr><td>
2363 2365 <a href="/help/diff">
2364 2366 diff
2365 2367 </a>
2366 2368 </td><td>
2367 2369 diff repository (or selected files)
2368 2370 </td></tr>
2369 2371 <tr><td>
2370 2372 <a href="/help/export">
2371 2373 export
2372 2374 </a>
2373 2375 </td><td>
2374 2376 dump the header and diffs for one or more changesets
2375 2377 </td></tr>
2376 2378 <tr><td>
2377 2379 <a href="/help/forget">
2378 2380 forget
2379 2381 </a>
2380 2382 </td><td>
2381 2383 forget the specified files on the next commit
2382 2384 </td></tr>
2383 2385 <tr><td>
2384 2386 <a href="/help/init">
2385 2387 init
2386 2388 </a>
2387 2389 </td><td>
2388 2390 create a new repository in the given directory
2389 2391 </td></tr>
2390 2392 <tr><td>
2391 2393 <a href="/help/log">
2392 2394 log
2393 2395 </a>
2394 2396 </td><td>
2395 2397 show revision history of entire repository or files
2396 2398 </td></tr>
2397 2399 <tr><td>
2398 2400 <a href="/help/merge">
2399 2401 merge
2400 2402 </a>
2401 2403 </td><td>
2402 2404 merge another revision into working directory
2403 2405 </td></tr>
2404 2406 <tr><td>
2405 2407 <a href="/help/pull">
2406 2408 pull
2407 2409 </a>
2408 2410 </td><td>
2409 2411 pull changes from the specified source
2410 2412 </td></tr>
2411 2413 <tr><td>
2412 2414 <a href="/help/push">
2413 2415 push
2414 2416 </a>
2415 2417 </td><td>
2416 2418 push changes to the specified destination
2417 2419 </td></tr>
2418 2420 <tr><td>
2419 2421 <a href="/help/remove">
2420 2422 remove
2421 2423 </a>
2422 2424 </td><td>
2423 2425 remove the specified files on the next commit
2424 2426 </td></tr>
2425 2427 <tr><td>
2426 2428 <a href="/help/serve">
2427 2429 serve
2428 2430 </a>
2429 2431 </td><td>
2430 2432 start stand-alone webserver
2431 2433 </td></tr>
2432 2434 <tr><td>
2433 2435 <a href="/help/status">
2434 2436 status
2435 2437 </a>
2436 2438 </td><td>
2437 2439 show changed files in the working directory
2438 2440 </td></tr>
2439 2441 <tr><td>
2440 2442 <a href="/help/summary">
2441 2443 summary
2442 2444 </a>
2443 2445 </td><td>
2444 2446 summarize working directory state
2445 2447 </td></tr>
2446 2448 <tr><td>
2447 2449 <a href="/help/update">
2448 2450 update
2449 2451 </a>
2450 2452 </td><td>
2451 2453 update working directory (or switch revisions)
2452 2454 </td></tr>
2453 2455
2454 2456
2455 2457
2456 2458 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2457 2459
2458 2460 <tr><td>
2459 2461 <a href="/help/addremove">
2460 2462 addremove
2461 2463 </a>
2462 2464 </td><td>
2463 2465 add all new files, delete all missing files
2464 2466 </td></tr>
2465 2467 <tr><td>
2466 2468 <a href="/help/archive">
2467 2469 archive
2468 2470 </a>
2469 2471 </td><td>
2470 2472 create an unversioned archive of a repository revision
2471 2473 </td></tr>
2472 2474 <tr><td>
2473 2475 <a href="/help/backout">
2474 2476 backout
2475 2477 </a>
2476 2478 </td><td>
2477 2479 reverse effect of earlier changeset
2478 2480 </td></tr>
2479 2481 <tr><td>
2480 2482 <a href="/help/bisect">
2481 2483 bisect
2482 2484 </a>
2483 2485 </td><td>
2484 2486 subdivision search of changesets
2485 2487 </td></tr>
2486 2488 <tr><td>
2487 2489 <a href="/help/bookmarks">
2488 2490 bookmarks
2489 2491 </a>
2490 2492 </td><td>
2491 2493 create a new bookmark or list existing bookmarks
2492 2494 </td></tr>
2493 2495 <tr><td>
2494 2496 <a href="/help/branch">
2495 2497 branch
2496 2498 </a>
2497 2499 </td><td>
2498 2500 set or show the current branch name
2499 2501 </td></tr>
2500 2502 <tr><td>
2501 2503 <a href="/help/branches">
2502 2504 branches
2503 2505 </a>
2504 2506 </td><td>
2505 2507 list repository named branches
2506 2508 </td></tr>
2507 2509 <tr><td>
2508 2510 <a href="/help/bundle">
2509 2511 bundle
2510 2512 </a>
2511 2513 </td><td>
2512 2514 create a bundle file
2513 2515 </td></tr>
2514 2516 <tr><td>
2515 2517 <a href="/help/cat">
2516 2518 cat
2517 2519 </a>
2518 2520 </td><td>
2519 2521 output the current or given revision of files
2520 2522 </td></tr>
2521 2523 <tr><td>
2522 2524 <a href="/help/config">
2523 2525 config
2524 2526 </a>
2525 2527 </td><td>
2526 2528 show combined config settings from all hgrc files
2527 2529 </td></tr>
2528 2530 <tr><td>
2529 2531 <a href="/help/copy">
2530 2532 copy
2531 2533 </a>
2532 2534 </td><td>
2533 2535 mark files as copied for the next commit
2534 2536 </td></tr>
2535 2537 <tr><td>
2536 2538 <a href="/help/files">
2537 2539 files
2538 2540 </a>
2539 2541 </td><td>
2540 2542 list tracked files
2541 2543 </td></tr>
2542 2544 <tr><td>
2543 2545 <a href="/help/graft">
2544 2546 graft
2545 2547 </a>
2546 2548 </td><td>
2547 2549 copy changes from other branches onto the current branch
2548 2550 </td></tr>
2549 2551 <tr><td>
2550 2552 <a href="/help/grep">
2551 2553 grep
2552 2554 </a>
2553 2555 </td><td>
2554 2556 search revision history for a pattern in specified files
2555 2557 </td></tr>
2556 2558 <tr><td>
2557 2559 <a href="/help/hashelp">
2558 2560 hashelp
2559 2561 </a>
2560 2562 </td><td>
2561 2563 Extension command's help
2562 2564 </td></tr>
2563 2565 <tr><td>
2564 2566 <a href="/help/heads">
2565 2567 heads
2566 2568 </a>
2567 2569 </td><td>
2568 2570 show branch heads
2569 2571 </td></tr>
2570 2572 <tr><td>
2571 2573 <a href="/help/help">
2572 2574 help
2573 2575 </a>
2574 2576 </td><td>
2575 2577 show help for a given topic or a help overview
2576 2578 </td></tr>
2577 2579 <tr><td>
2578 2580 <a href="/help/hgalias">
2579 2581 hgalias
2580 2582 </a>
2581 2583 </td><td>
2582 2584 My doc
2583 2585 </td></tr>
2584 2586 <tr><td>
2585 2587 <a href="/help/hgaliasnodoc">
2586 2588 hgaliasnodoc
2587 2589 </a>
2588 2590 </td><td>
2589 2591 summarize working directory state
2590 2592 </td></tr>
2591 2593 <tr><td>
2592 2594 <a href="/help/identify">
2593 2595 identify
2594 2596 </a>
2595 2597 </td><td>
2596 2598 identify the working directory or specified revision
2597 2599 </td></tr>
2598 2600 <tr><td>
2599 2601 <a href="/help/import">
2600 2602 import
2601 2603 </a>
2602 2604 </td><td>
2603 2605 import an ordered set of patches
2604 2606 </td></tr>
2605 2607 <tr><td>
2606 2608 <a href="/help/incoming">
2607 2609 incoming
2608 2610 </a>
2609 2611 </td><td>
2610 2612 show new changesets found in source
2611 2613 </td></tr>
2612 2614 <tr><td>
2613 2615 <a href="/help/manifest">
2614 2616 manifest
2615 2617 </a>
2616 2618 </td><td>
2617 2619 output the current or given revision of the project manifest
2618 2620 </td></tr>
2619 2621 <tr><td>
2620 2622 <a href="/help/nohelp">
2621 2623 nohelp
2622 2624 </a>
2623 2625 </td><td>
2624 2626 (no help text available)
2625 2627 </td></tr>
2626 2628 <tr><td>
2627 2629 <a href="/help/outgoing">
2628 2630 outgoing
2629 2631 </a>
2630 2632 </td><td>
2631 2633 show changesets not found in the destination
2632 2634 </td></tr>
2633 2635 <tr><td>
2634 2636 <a href="/help/paths">
2635 2637 paths
2636 2638 </a>
2637 2639 </td><td>
2638 2640 show aliases for remote repositories
2639 2641 </td></tr>
2640 2642 <tr><td>
2641 2643 <a href="/help/phase">
2642 2644 phase
2643 2645 </a>
2644 2646 </td><td>
2645 2647 set or show the current phase name
2646 2648 </td></tr>
2647 2649 <tr><td>
2648 2650 <a href="/help/recover">
2649 2651 recover
2650 2652 </a>
2651 2653 </td><td>
2652 2654 roll back an interrupted transaction
2653 2655 </td></tr>
2654 2656 <tr><td>
2655 2657 <a href="/help/rename">
2656 2658 rename
2657 2659 </a>
2658 2660 </td><td>
2659 2661 rename files; equivalent of copy + remove
2660 2662 </td></tr>
2661 2663 <tr><td>
2662 2664 <a href="/help/resolve">
2663 2665 resolve
2664 2666 </a>
2665 2667 </td><td>
2666 2668 redo merges or set/view the merge status of files
2667 2669 </td></tr>
2668 2670 <tr><td>
2669 2671 <a href="/help/revert">
2670 2672 revert
2671 2673 </a>
2672 2674 </td><td>
2673 2675 restore files to their checkout state
2674 2676 </td></tr>
2675 2677 <tr><td>
2676 2678 <a href="/help/root">
2677 2679 root
2678 2680 </a>
2679 2681 </td><td>
2680 2682 print the root (top) of the current working directory
2681 2683 </td></tr>
2682 2684 <tr><td>
2683 2685 <a href="/help/shellalias">
2684 2686 shellalias
2685 2687 </a>
2686 2688 </td><td>
2687 2689 (no help text available)
2688 2690 </td></tr>
2689 2691 <tr><td>
2690 2692 <a href="/help/tag">
2691 2693 tag
2692 2694 </a>
2693 2695 </td><td>
2694 2696 add one or more tags for the current or given revision
2695 2697 </td></tr>
2696 2698 <tr><td>
2697 2699 <a href="/help/tags">
2698 2700 tags
2699 2701 </a>
2700 2702 </td><td>
2701 2703 list repository tags
2702 2704 </td></tr>
2703 2705 <tr><td>
2704 2706 <a href="/help/unbundle">
2705 2707 unbundle
2706 2708 </a>
2707 2709 </td><td>
2708 2710 apply one or more bundle files
2709 2711 </td></tr>
2710 2712 <tr><td>
2711 2713 <a href="/help/verify">
2712 2714 verify
2713 2715 </a>
2714 2716 </td><td>
2715 2717 verify the integrity of the repository
2716 2718 </td></tr>
2717 2719 <tr><td>
2718 2720 <a href="/help/version">
2719 2721 version
2720 2722 </a>
2721 2723 </td><td>
2722 2724 output version and copyright information
2723 2725 </td></tr>
2724 2726
2725 2727
2726 2728 </table>
2727 2729 </div>
2728 2730 </div>
2729 2731
2730 2732
2731 2733
2732 2734 </body>
2733 2735 </html>
2734 2736
2735 2737
2736 2738 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2737 2739 200 Script output follows
2738 2740
2739 2741 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2740 2742 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2741 2743 <head>
2742 2744 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2743 2745 <meta name="robots" content="index, nofollow" />
2744 2746 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2745 2747 <script type="text/javascript" src="/static/mercurial.js"></script>
2746 2748
2747 2749 <title>Help: add</title>
2748 2750 </head>
2749 2751 <body>
2750 2752
2751 2753 <div class="container">
2752 2754 <div class="menu">
2753 2755 <div class="logo">
2754 2756 <a href="https://mercurial-scm.org/">
2755 2757 <img src="/static/hglogo.png" alt="mercurial" /></a>
2756 2758 </div>
2757 2759 <ul>
2758 2760 <li><a href="/shortlog">log</a></li>
2759 2761 <li><a href="/graph">graph</a></li>
2760 2762 <li><a href="/tags">tags</a></li>
2761 2763 <li><a href="/bookmarks">bookmarks</a></li>
2762 2764 <li><a href="/branches">branches</a></li>
2763 2765 </ul>
2764 2766 <ul>
2765 2767 <li class="active"><a href="/help">help</a></li>
2766 2768 </ul>
2767 2769 </div>
2768 2770
2769 2771 <div class="main">
2770 2772 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2771 2773 <h3>Help: add</h3>
2772 2774
2773 2775 <form class="search" action="/log">
2774 2776
2775 2777 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2776 2778 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2777 2779 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2778 2780 </form>
2779 2781 <div id="doc">
2780 2782 <p>
2781 2783 hg add [OPTION]... [FILE]...
2782 2784 </p>
2783 2785 <p>
2784 2786 add the specified files on the next commit
2785 2787 </p>
2786 2788 <p>
2787 2789 Schedule files to be version controlled and added to the
2788 2790 repository.
2789 2791 </p>
2790 2792 <p>
2791 2793 The files will be added to the repository at the next commit. To
2792 2794 undo an add before that, see 'hg forget'.
2793 2795 </p>
2794 2796 <p>
2795 2797 If no names are given, add all files to the repository (except
2796 2798 files matching &quot;.hgignore&quot;).
2797 2799 </p>
2798 2800 <p>
2799 2801 Examples:
2800 2802 </p>
2801 2803 <ul>
2802 2804 <li> New (unknown) files are added automatically by 'hg add':
2803 2805 <pre>
2804 2806 \$ ls (re)
2805 2807 foo.c
2806 2808 \$ hg status (re)
2807 2809 ? foo.c
2808 2810 \$ hg add (re)
2809 2811 adding foo.c
2810 2812 \$ hg status (re)
2811 2813 A foo.c
2812 2814 </pre>
2813 2815 <li> Specific files to be added can be specified:
2814 2816 <pre>
2815 2817 \$ ls (re)
2816 2818 bar.c foo.c
2817 2819 \$ hg status (re)
2818 2820 ? bar.c
2819 2821 ? foo.c
2820 2822 \$ hg add bar.c (re)
2821 2823 \$ hg status (re)
2822 2824 A bar.c
2823 2825 ? foo.c
2824 2826 </pre>
2825 2827 </ul>
2826 2828 <p>
2827 2829 Returns 0 if all files are successfully added.
2828 2830 </p>
2829 2831 <p>
2830 2832 options ([+] can be repeated):
2831 2833 </p>
2832 2834 <table>
2833 2835 <tr><td>-I</td>
2834 2836 <td>--include PATTERN [+]</td>
2835 2837 <td>include names matching the given patterns</td></tr>
2836 2838 <tr><td>-X</td>
2837 2839 <td>--exclude PATTERN [+]</td>
2838 2840 <td>exclude names matching the given patterns</td></tr>
2839 2841 <tr><td>-S</td>
2840 2842 <td>--subrepos</td>
2841 2843 <td>recurse into subrepositories</td></tr>
2842 2844 <tr><td>-n</td>
2843 2845 <td>--dry-run</td>
2844 2846 <td>do not perform actions, just print output</td></tr>
2845 2847 </table>
2846 2848 <p>
2847 2849 global options ([+] can be repeated):
2848 2850 </p>
2849 2851 <table>
2850 2852 <tr><td>-R</td>
2851 2853 <td>--repository REPO</td>
2852 2854 <td>repository root directory or name of overlay bundle file</td></tr>
2853 2855 <tr><td></td>
2854 2856 <td>--cwd DIR</td>
2855 2857 <td>change working directory</td></tr>
2856 2858 <tr><td>-y</td>
2857 2859 <td>--noninteractive</td>
2858 2860 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2859 2861 <tr><td>-q</td>
2860 2862 <td>--quiet</td>
2861 2863 <td>suppress output</td></tr>
2862 2864 <tr><td>-v</td>
2863 2865 <td>--verbose</td>
2864 2866 <td>enable additional output</td></tr>
2865 2867 <tr><td></td>
2866 2868 <td>--color TYPE</td>
2867 2869 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2868 2870 <tr><td></td>
2869 2871 <td>--config CONFIG [+]</td>
2870 2872 <td>set/override config option (use 'section.name=value')</td></tr>
2871 2873 <tr><td></td>
2872 2874 <td>--debug</td>
2873 2875 <td>enable debugging output</td></tr>
2874 2876 <tr><td></td>
2875 2877 <td>--debugger</td>
2876 2878 <td>start debugger</td></tr>
2877 2879 <tr><td></td>
2878 2880 <td>--encoding ENCODE</td>
2879 2881 <td>set the charset encoding (default: ascii)</td></tr>
2880 2882 <tr><td></td>
2881 2883 <td>--encodingmode MODE</td>
2882 2884 <td>set the charset encoding mode (default: strict)</td></tr>
2883 2885 <tr><td></td>
2884 2886 <td>--traceback</td>
2885 2887 <td>always print a traceback on exception</td></tr>
2886 2888 <tr><td></td>
2887 2889 <td>--time</td>
2888 2890 <td>time how long the command takes</td></tr>
2889 2891 <tr><td></td>
2890 2892 <td>--profile</td>
2891 2893 <td>print command execution profile</td></tr>
2892 2894 <tr><td></td>
2893 2895 <td>--version</td>
2894 2896 <td>output version information and exit</td></tr>
2895 2897 <tr><td>-h</td>
2896 2898 <td>--help</td>
2897 2899 <td>display help and exit</td></tr>
2898 2900 <tr><td></td>
2899 2901 <td>--hidden</td>
2900 2902 <td>consider hidden changesets</td></tr>
2901 2903 <tr><td></td>
2902 2904 <td>--pager TYPE</td>
2903 2905 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2904 2906 </table>
2905 2907
2906 2908 </div>
2907 2909 </div>
2908 2910 </div>
2909 2911
2910 2912
2911 2913
2912 2914 </body>
2913 2915 </html>
2914 2916
2915 2917
2916 2918 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2917 2919 200 Script output follows
2918 2920
2919 2921 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2920 2922 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2921 2923 <head>
2922 2924 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2923 2925 <meta name="robots" content="index, nofollow" />
2924 2926 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2925 2927 <script type="text/javascript" src="/static/mercurial.js"></script>
2926 2928
2927 2929 <title>Help: remove</title>
2928 2930 </head>
2929 2931 <body>
2930 2932
2931 2933 <div class="container">
2932 2934 <div class="menu">
2933 2935 <div class="logo">
2934 2936 <a href="https://mercurial-scm.org/">
2935 2937 <img src="/static/hglogo.png" alt="mercurial" /></a>
2936 2938 </div>
2937 2939 <ul>
2938 2940 <li><a href="/shortlog">log</a></li>
2939 2941 <li><a href="/graph">graph</a></li>
2940 2942 <li><a href="/tags">tags</a></li>
2941 2943 <li><a href="/bookmarks">bookmarks</a></li>
2942 2944 <li><a href="/branches">branches</a></li>
2943 2945 </ul>
2944 2946 <ul>
2945 2947 <li class="active"><a href="/help">help</a></li>
2946 2948 </ul>
2947 2949 </div>
2948 2950
2949 2951 <div class="main">
2950 2952 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2951 2953 <h3>Help: remove</h3>
2952 2954
2953 2955 <form class="search" action="/log">
2954 2956
2955 2957 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2956 2958 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2957 2959 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2958 2960 </form>
2959 2961 <div id="doc">
2960 2962 <p>
2961 2963 hg remove [OPTION]... FILE...
2962 2964 </p>
2963 2965 <p>
2964 2966 aliases: rm
2965 2967 </p>
2966 2968 <p>
2967 2969 remove the specified files on the next commit
2968 2970 </p>
2969 2971 <p>
2970 2972 Schedule the indicated files for removal from the current branch.
2971 2973 </p>
2972 2974 <p>
2973 2975 This command schedules the files to be removed at the next commit.
2974 2976 To undo a remove before that, see 'hg revert'. To undo added
2975 2977 files, see 'hg forget'.
2976 2978 </p>
2977 2979 <p>
2978 2980 -A/--after can be used to remove only files that have already
2979 2981 been deleted, -f/--force can be used to force deletion, and -Af
2980 2982 can be used to remove files from the next revision without
2981 2983 deleting them from the working directory.
2982 2984 </p>
2983 2985 <p>
2984 2986 The following table details the behavior of remove for different
2985 2987 file states (columns) and option combinations (rows). The file
2986 2988 states are Added [A], Clean [C], Modified [M] and Missing [!]
2987 2989 (as reported by 'hg status'). The actions are Warn, Remove
2988 2990 (from branch) and Delete (from disk):
2989 2991 </p>
2990 2992 <table>
2991 2993 <tr><td>opt/state</td>
2992 2994 <td>A</td>
2993 2995 <td>C</td>
2994 2996 <td>M</td>
2995 2997 <td>!</td></tr>
2996 2998 <tr><td>none</td>
2997 2999 <td>W</td>
2998 3000 <td>RD</td>
2999 3001 <td>W</td>
3000 3002 <td>R</td></tr>
3001 3003 <tr><td>-f</td>
3002 3004 <td>R</td>
3003 3005 <td>RD</td>
3004 3006 <td>RD</td>
3005 3007 <td>R</td></tr>
3006 3008 <tr><td>-A</td>
3007 3009 <td>W</td>
3008 3010 <td>W</td>
3009 3011 <td>W</td>
3010 3012 <td>R</td></tr>
3011 3013 <tr><td>-Af</td>
3012 3014 <td>R</td>
3013 3015 <td>R</td>
3014 3016 <td>R</td>
3015 3017 <td>R</td></tr>
3016 3018 </table>
3017 3019 <p>
3018 3020 <b>Note:</b>
3019 3021 </p>
3020 3022 <p>
3021 3023 'hg remove' never deletes files in Added [A] state from the
3022 3024 working directory, not even if &quot;--force&quot; is specified.
3023 3025 </p>
3024 3026 <p>
3025 3027 Returns 0 on success, 1 if any warnings encountered.
3026 3028 </p>
3027 3029 <p>
3028 3030 options ([+] can be repeated):
3029 3031 </p>
3030 3032 <table>
3031 3033 <tr><td>-A</td>
3032 3034 <td>--after</td>
3033 3035 <td>record delete for missing files</td></tr>
3034 3036 <tr><td>-f</td>
3035 3037 <td>--force</td>
3036 3038 <td>forget added files, delete modified files</td></tr>
3037 3039 <tr><td>-S</td>
3038 3040 <td>--subrepos</td>
3039 3041 <td>recurse into subrepositories</td></tr>
3040 3042 <tr><td>-I</td>
3041 3043 <td>--include PATTERN [+]</td>
3042 3044 <td>include names matching the given patterns</td></tr>
3043 3045 <tr><td>-X</td>
3044 3046 <td>--exclude PATTERN [+]</td>
3045 3047 <td>exclude names matching the given patterns</td></tr>
3046 3048 <tr><td>-n</td>
3047 3049 <td>--dry-run</td>
3048 3050 <td>do not perform actions, just print output</td></tr>
3049 3051 </table>
3050 3052 <p>
3051 3053 global options ([+] can be repeated):
3052 3054 </p>
3053 3055 <table>
3054 3056 <tr><td>-R</td>
3055 3057 <td>--repository REPO</td>
3056 3058 <td>repository root directory or name of overlay bundle file</td></tr>
3057 3059 <tr><td></td>
3058 3060 <td>--cwd DIR</td>
3059 3061 <td>change working directory</td></tr>
3060 3062 <tr><td>-y</td>
3061 3063 <td>--noninteractive</td>
3062 3064 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3063 3065 <tr><td>-q</td>
3064 3066 <td>--quiet</td>
3065 3067 <td>suppress output</td></tr>
3066 3068 <tr><td>-v</td>
3067 3069 <td>--verbose</td>
3068 3070 <td>enable additional output</td></tr>
3069 3071 <tr><td></td>
3070 3072 <td>--color TYPE</td>
3071 3073 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3072 3074 <tr><td></td>
3073 3075 <td>--config CONFIG [+]</td>
3074 3076 <td>set/override config option (use 'section.name=value')</td></tr>
3075 3077 <tr><td></td>
3076 3078 <td>--debug</td>
3077 3079 <td>enable debugging output</td></tr>
3078 3080 <tr><td></td>
3079 3081 <td>--debugger</td>
3080 3082 <td>start debugger</td></tr>
3081 3083 <tr><td></td>
3082 3084 <td>--encoding ENCODE</td>
3083 3085 <td>set the charset encoding (default: ascii)</td></tr>
3084 3086 <tr><td></td>
3085 3087 <td>--encodingmode MODE</td>
3086 3088 <td>set the charset encoding mode (default: strict)</td></tr>
3087 3089 <tr><td></td>
3088 3090 <td>--traceback</td>
3089 3091 <td>always print a traceback on exception</td></tr>
3090 3092 <tr><td></td>
3091 3093 <td>--time</td>
3092 3094 <td>time how long the command takes</td></tr>
3093 3095 <tr><td></td>
3094 3096 <td>--profile</td>
3095 3097 <td>print command execution profile</td></tr>
3096 3098 <tr><td></td>
3097 3099 <td>--version</td>
3098 3100 <td>output version information and exit</td></tr>
3099 3101 <tr><td>-h</td>
3100 3102 <td>--help</td>
3101 3103 <td>display help and exit</td></tr>
3102 3104 <tr><td></td>
3103 3105 <td>--hidden</td>
3104 3106 <td>consider hidden changesets</td></tr>
3105 3107 <tr><td></td>
3106 3108 <td>--pager TYPE</td>
3107 3109 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3108 3110 </table>
3109 3111
3110 3112 </div>
3111 3113 </div>
3112 3114 </div>
3113 3115
3114 3116
3115 3117
3116 3118 </body>
3117 3119 </html>
3118 3120
3119 3121
3120 3122 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3121 3123 200 Script output follows
3122 3124
3123 3125 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3124 3126 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3125 3127 <head>
3126 3128 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3127 3129 <meta name="robots" content="index, nofollow" />
3128 3130 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3129 3131 <script type="text/javascript" src="/static/mercurial.js"></script>
3130 3132
3131 3133 <title>Help: dates</title>
3132 3134 </head>
3133 3135 <body>
3134 3136
3135 3137 <div class="container">
3136 3138 <div class="menu">
3137 3139 <div class="logo">
3138 3140 <a href="https://mercurial-scm.org/">
3139 3141 <img src="/static/hglogo.png" alt="mercurial" /></a>
3140 3142 </div>
3141 3143 <ul>
3142 3144 <li><a href="/shortlog">log</a></li>
3143 3145 <li><a href="/graph">graph</a></li>
3144 3146 <li><a href="/tags">tags</a></li>
3145 3147 <li><a href="/bookmarks">bookmarks</a></li>
3146 3148 <li><a href="/branches">branches</a></li>
3147 3149 </ul>
3148 3150 <ul>
3149 3151 <li class="active"><a href="/help">help</a></li>
3150 3152 </ul>
3151 3153 </div>
3152 3154
3153 3155 <div class="main">
3154 3156 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3155 3157 <h3>Help: dates</h3>
3156 3158
3157 3159 <form class="search" action="/log">
3158 3160
3159 3161 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3160 3162 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3161 3163 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3162 3164 </form>
3163 3165 <div id="doc">
3164 3166 <h1>Date Formats</h1>
3165 3167 <p>
3166 3168 Some commands allow the user to specify a date, e.g.:
3167 3169 </p>
3168 3170 <ul>
3169 3171 <li> backout, commit, import, tag: Specify the commit date.
3170 3172 <li> log, revert, update: Select revision(s) by date.
3171 3173 </ul>
3172 3174 <p>
3173 3175 Many date formats are valid. Here are some examples:
3174 3176 </p>
3175 3177 <ul>
3176 3178 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3177 3179 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3178 3180 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3179 3181 <li> &quot;Dec 6&quot; (midnight)
3180 3182 <li> &quot;13:18&quot; (today assumed)
3181 3183 <li> &quot;3:39&quot; (3:39AM assumed)
3182 3184 <li> &quot;3:39pm&quot; (15:39)
3183 3185 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3184 3186 <li> &quot;2006-12-6 13:18&quot;
3185 3187 <li> &quot;2006-12-6&quot;
3186 3188 <li> &quot;12-6&quot;
3187 3189 <li> &quot;12/6&quot;
3188 3190 <li> &quot;12/6/6&quot; (Dec 6 2006)
3189 3191 <li> &quot;today&quot; (midnight)
3190 3192 <li> &quot;yesterday&quot; (midnight)
3191 3193 <li> &quot;now&quot; - right now
3192 3194 </ul>
3193 3195 <p>
3194 3196 Lastly, there is Mercurial's internal format:
3195 3197 </p>
3196 3198 <ul>
3197 3199 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3198 3200 </ul>
3199 3201 <p>
3200 3202 This is the internal representation format for dates. The first number
3201 3203 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3202 3204 second is the offset of the local timezone, in seconds west of UTC
3203 3205 (negative if the timezone is east of UTC).
3204 3206 </p>
3205 3207 <p>
3206 3208 The log command also accepts date ranges:
3207 3209 </p>
3208 3210 <ul>
3209 3211 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3210 3212 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3211 3213 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3212 3214 <li> &quot;-DAYS&quot; - within a given number of days of today
3213 3215 </ul>
3214 3216
3215 3217 </div>
3216 3218 </div>
3217 3219 </div>
3218 3220
3219 3221
3220 3222
3221 3223 </body>
3222 3224 </html>
3223 3225
3224 3226
3225 3227 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3226 3228 200 Script output follows
3227 3229
3228 3230 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3229 3231 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3230 3232 <head>
3231 3233 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3232 3234 <meta name="robots" content="index, nofollow" />
3233 3235 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3234 3236 <script type="text/javascript" src="/static/mercurial.js"></script>
3235 3237
3236 3238 <title>Help: pager</title>
3237 3239 </head>
3238 3240 <body>
3239 3241
3240 3242 <div class="container">
3241 3243 <div class="menu">
3242 3244 <div class="logo">
3243 3245 <a href="https://mercurial-scm.org/">
3244 3246 <img src="/static/hglogo.png" alt="mercurial" /></a>
3245 3247 </div>
3246 3248 <ul>
3247 3249 <li><a href="/shortlog">log</a></li>
3248 3250 <li><a href="/graph">graph</a></li>
3249 3251 <li><a href="/tags">tags</a></li>
3250 3252 <li><a href="/bookmarks">bookmarks</a></li>
3251 3253 <li><a href="/branches">branches</a></li>
3252 3254 </ul>
3253 3255 <ul>
3254 3256 <li class="active"><a href="/help">help</a></li>
3255 3257 </ul>
3256 3258 </div>
3257 3259
3258 3260 <div class="main">
3259 3261 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3260 3262 <h3>Help: pager</h3>
3261 3263
3262 3264 <form class="search" action="/log">
3263 3265
3264 3266 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3265 3267 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3266 3268 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3267 3269 </form>
3268 3270 <div id="doc">
3269 3271 <h1>Pager Support</h1>
3270 3272 <p>
3271 3273 Some Mercurial commands can produce a lot of output, and Mercurial will
3272 3274 attempt to use a pager to make those commands more pleasant.
3273 3275 </p>
3274 3276 <p>
3275 3277 To set the pager that should be used, set the application variable:
3276 3278 </p>
3277 3279 <pre>
3278 3280 [pager]
3279 3281 pager = less -FRX
3280 3282 </pre>
3281 3283 <p>
3282 3284 If no pager is set in the user or repository configuration, Mercurial uses the
3283 3285 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3284 3286 or system configuration is used. If none of these are set, a default pager will
3285 3287 be used, typically 'less' on Unix and 'more' on Windows.
3286 3288 </p>
3287 3289 <p>
3288 3290 You can disable the pager for certain commands by adding them to the
3289 3291 pager.ignore list:
3290 3292 </p>
3291 3293 <pre>
3292 3294 [pager]
3293 3295 ignore = version, help, update
3294 3296 </pre>
3295 3297 <p>
3296 3298 To ignore global commands like 'hg version' or 'hg help', you have
3297 3299 to specify them in your user configuration file.
3298 3300 </p>
3299 3301 <p>
3300 3302 To control whether the pager is used at all for an individual command,
3301 3303 you can use --pager=&lt;value&gt;:
3302 3304 </p>
3303 3305 <ul>
3304 3306 <li> use as needed: 'auto'.
3305 3307 <li> require the pager: 'yes' or 'on'.
3306 3308 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3307 3309 </ul>
3308 3310 <p>
3309 3311 To globally turn off all attempts to use a pager, set:
3310 3312 </p>
3311 3313 <pre>
3312 3314 [ui]
3313 3315 paginate = never
3314 3316 </pre>
3315 3317 <p>
3316 3318 which will prevent the pager from running.
3317 3319 </p>
3318 3320
3319 3321 </div>
3320 3322 </div>
3321 3323 </div>
3322 3324
3323 3325
3324 3326
3325 3327 </body>
3326 3328 </html>
3327 3329
3328 3330
3329 3331 Sub-topic indexes rendered properly
3330 3332
3331 3333 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3332 3334 200 Script output follows
3333 3335
3334 3336 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3335 3337 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3336 3338 <head>
3337 3339 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3338 3340 <meta name="robots" content="index, nofollow" />
3339 3341 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3340 3342 <script type="text/javascript" src="/static/mercurial.js"></script>
3341 3343
3342 3344 <title>Help: internals</title>
3343 3345 </head>
3344 3346 <body>
3345 3347
3346 3348 <div class="container">
3347 3349 <div class="menu">
3348 3350 <div class="logo">
3349 3351 <a href="https://mercurial-scm.org/">
3350 3352 <img src="/static/hglogo.png" alt="mercurial" /></a>
3351 3353 </div>
3352 3354 <ul>
3353 3355 <li><a href="/shortlog">log</a></li>
3354 3356 <li><a href="/graph">graph</a></li>
3355 3357 <li><a href="/tags">tags</a></li>
3356 3358 <li><a href="/bookmarks">bookmarks</a></li>
3357 3359 <li><a href="/branches">branches</a></li>
3358 3360 </ul>
3359 3361 <ul>
3360 3362 <li><a href="/help">help</a></li>
3361 3363 </ul>
3362 3364 </div>
3363 3365
3364 3366 <div class="main">
3365 3367 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3366 3368
3367 3369 <form class="search" action="/log">
3368 3370
3369 3371 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3370 3372 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3371 3373 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3372 3374 </form>
3373 3375 <table class="bigtable">
3374 3376 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3375 3377
3376 3378 <tr><td>
3377 3379 <a href="/help/internals.bundle2">
3378 3380 bundle2
3379 3381 </a>
3380 3382 </td><td>
3381 3383 Bundle2
3382 3384 </td></tr>
3383 3385 <tr><td>
3384 3386 <a href="/help/internals.bundles">
3385 3387 bundles
3386 3388 </a>
3387 3389 </td><td>
3388 3390 Bundles
3389 3391 </td></tr>
3390 3392 <tr><td>
3391 3393 <a href="/help/internals.cbor">
3392 3394 cbor
3393 3395 </a>
3394 3396 </td><td>
3395 3397 CBOR
3396 3398 </td></tr>
3397 3399 <tr><td>
3398 3400 <a href="/help/internals.censor">
3399 3401 censor
3400 3402 </a>
3401 3403 </td><td>
3402 3404 Censor
3403 3405 </td></tr>
3404 3406 <tr><td>
3405 3407 <a href="/help/internals.changegroups">
3406 3408 changegroups
3407 3409 </a>
3408 3410 </td><td>
3409 3411 Changegroups
3410 3412 </td></tr>
3411 3413 <tr><td>
3412 3414 <a href="/help/internals.config">
3413 3415 config
3414 3416 </a>
3415 3417 </td><td>
3416 3418 Config Registrar
3417 3419 </td></tr>
3418 3420 <tr><td>
3419 3421 <a href="/help/internals.extensions">
3420 3422 extensions
3421 3423 </a>
3422 3424 </td><td>
3423 3425 Extension API
3424 3426 </td></tr>
3425 3427 <tr><td>
3426 3428 <a href="/help/internals.requirements">
3427 3429 requirements
3428 3430 </a>
3429 3431 </td><td>
3430 3432 Repository Requirements
3431 3433 </td></tr>
3432 3434 <tr><td>
3433 3435 <a href="/help/internals.revlogs">
3434 3436 revlogs
3435 3437 </a>
3436 3438 </td><td>
3437 3439 Revision Logs
3438 3440 </td></tr>
3439 3441 <tr><td>
3440 3442 <a href="/help/internals.wireprotocol">
3441 3443 wireprotocol
3442 3444 </a>
3443 3445 </td><td>
3444 3446 Wire Protocol
3445 3447 </td></tr>
3446 3448 <tr><td>
3447 3449 <a href="/help/internals.wireprotocolrpc">
3448 3450 wireprotocolrpc
3449 3451 </a>
3450 3452 </td><td>
3451 3453 Wire Protocol RPC
3452 3454 </td></tr>
3453 3455 <tr><td>
3454 3456 <a href="/help/internals.wireprotocolv2">
3455 3457 wireprotocolv2
3456 3458 </a>
3457 3459 </td><td>
3458 3460 Wire Protocol Version 2
3459 3461 </td></tr>
3460 3462
3461 3463
3462 3464
3463 3465
3464 3466
3465 3467 </table>
3466 3468 </div>
3467 3469 </div>
3468 3470
3469 3471
3470 3472
3471 3473 </body>
3472 3474 </html>
3473 3475
3474 3476
3475 3477 Sub-topic topics rendered properly
3476 3478
3477 3479 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3478 3480 200 Script output follows
3479 3481
3480 3482 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3481 3483 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3482 3484 <head>
3483 3485 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3484 3486 <meta name="robots" content="index, nofollow" />
3485 3487 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3486 3488 <script type="text/javascript" src="/static/mercurial.js"></script>
3487 3489
3488 3490 <title>Help: internals.changegroups</title>
3489 3491 </head>
3490 3492 <body>
3491 3493
3492 3494 <div class="container">
3493 3495 <div class="menu">
3494 3496 <div class="logo">
3495 3497 <a href="https://mercurial-scm.org/">
3496 3498 <img src="/static/hglogo.png" alt="mercurial" /></a>
3497 3499 </div>
3498 3500 <ul>
3499 3501 <li><a href="/shortlog">log</a></li>
3500 3502 <li><a href="/graph">graph</a></li>
3501 3503 <li><a href="/tags">tags</a></li>
3502 3504 <li><a href="/bookmarks">bookmarks</a></li>
3503 3505 <li><a href="/branches">branches</a></li>
3504 3506 </ul>
3505 3507 <ul>
3506 3508 <li class="active"><a href="/help">help</a></li>
3507 3509 </ul>
3508 3510 </div>
3509 3511
3510 3512 <div class="main">
3511 3513 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3512 3514 <h3>Help: internals.changegroups</h3>
3513 3515
3514 3516 <form class="search" action="/log">
3515 3517
3516 3518 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3517 3519 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3518 3520 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3519 3521 </form>
3520 3522 <div id="doc">
3521 3523 <h1>Changegroups</h1>
3522 3524 <p>
3523 3525 Changegroups are representations of repository revlog data, specifically
3524 3526 the changelog data, root/flat manifest data, treemanifest data, and
3525 3527 filelogs.
3526 3528 </p>
3527 3529 <p>
3528 3530 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3529 3531 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3530 3532 only difference being an additional item in the *delta header*. Version
3531 3533 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3532 3534 exchanging treemanifests (enabled by setting an option on the
3533 3535 &quot;changegroup&quot; part in the bundle2).
3534 3536 </p>
3535 3537 <p>
3536 3538 Changegroups when not exchanging treemanifests consist of 3 logical
3537 3539 segments:
3538 3540 </p>
3539 3541 <pre>
3540 3542 +---------------------------------+
3541 3543 | | | |
3542 3544 | changeset | manifest | filelogs |
3543 3545 | | | |
3544 3546 | | | |
3545 3547 +---------------------------------+
3546 3548 </pre>
3547 3549 <p>
3548 3550 When exchanging treemanifests, there are 4 logical segments:
3549 3551 </p>
3550 3552 <pre>
3551 3553 +-------------------------------------------------+
3552 3554 | | | | |
3553 3555 | changeset | root | treemanifests | filelogs |
3554 3556 | | manifest | | |
3555 3557 | | | | |
3556 3558 +-------------------------------------------------+
3557 3559 </pre>
3558 3560 <p>
3559 3561 The principle building block of each segment is a *chunk*. A *chunk*
3560 3562 is a framed piece of data:
3561 3563 </p>
3562 3564 <pre>
3563 3565 +---------------------------------------+
3564 3566 | | |
3565 3567 | length | data |
3566 3568 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3567 3569 | | |
3568 3570 +---------------------------------------+
3569 3571 </pre>
3570 3572 <p>
3571 3573 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3572 3574 integer indicating the length of the entire chunk (including the length field
3573 3575 itself).
3574 3576 </p>
3575 3577 <p>
3576 3578 There is a special case chunk that has a value of 0 for the length
3577 3579 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3578 3580 </p>
3579 3581 <h2>Delta Groups</h2>
3580 3582 <p>
3581 3583 A *delta group* expresses the content of a revlog as a series of deltas,
3582 3584 or patches against previous revisions.
3583 3585 </p>
3584 3586 <p>
3585 3587 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3586 3588 to signal the end of the delta group:
3587 3589 </p>
3588 3590 <pre>
3589 3591 +------------------------------------------------------------------------+
3590 3592 | | | | | |
3591 3593 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3592 3594 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3593 3595 | | | | | |
3594 3596 +------------------------------------------------------------------------+
3595 3597 </pre>
3596 3598 <p>
3597 3599 Each *chunk*'s data consists of the following:
3598 3600 </p>
3599 3601 <pre>
3600 3602 +---------------------------------------+
3601 3603 | | |
3602 3604 | delta header | delta data |
3603 3605 | (various by version) | (various) |
3604 3606 | | |
3605 3607 +---------------------------------------+
3606 3608 </pre>
3607 3609 <p>
3608 3610 The *delta data* is a series of *delta*s that describe a diff from an existing
3609 3611 entry (either that the recipient already has, or previously specified in the
3610 3612 bundle/changegroup).
3611 3613 </p>
3612 3614 <p>
3613 3615 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3614 3616 &quot;3&quot; of the changegroup format.
3615 3617 </p>
3616 3618 <p>
3617 3619 Version 1 (headerlen=80):
3618 3620 </p>
3619 3621 <pre>
3620 3622 +------------------------------------------------------+
3621 3623 | | | | |
3622 3624 | node | p1 node | p2 node | link node |
3623 3625 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3624 3626 | | | | |
3625 3627 +------------------------------------------------------+
3626 3628 </pre>
3627 3629 <p>
3628 3630 Version 2 (headerlen=100):
3629 3631 </p>
3630 3632 <pre>
3631 3633 +------------------------------------------------------------------+
3632 3634 | | | | | |
3633 3635 | node | p1 node | p2 node | base node | link node |
3634 3636 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3635 3637 | | | | | |
3636 3638 +------------------------------------------------------------------+
3637 3639 </pre>
3638 3640 <p>
3639 3641 Version 3 (headerlen=102):
3640 3642 </p>
3641 3643 <pre>
3642 3644 +------------------------------------------------------------------------------+
3643 3645 | | | | | | |
3644 3646 | node | p1 node | p2 node | base node | link node | flags |
3645 3647 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3646 3648 | | | | | | |
3647 3649 +------------------------------------------------------------------------------+
3648 3650 </pre>
3649 3651 <p>
3650 3652 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3651 3653 series of *delta*s, densely packed (no separators). These deltas describe a diff
3652 3654 from an existing entry (either that the recipient already has, or previously
3653 3655 specified in the bundle/changegroup). The format is described more fully in
3654 3656 &quot;hg help internals.bdiff&quot;, but briefly:
3655 3657 </p>
3656 3658 <pre>
3657 3659 +---------------------------------------------------------------+
3658 3660 | | | | |
3659 3661 | start offset | end offset | new length | content |
3660 3662 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3661 3663 | | | | |
3662 3664 +---------------------------------------------------------------+
3663 3665 </pre>
3664 3666 <p>
3665 3667 Please note that the length field in the delta data does *not* include itself.
3666 3668 </p>
3667 3669 <p>
3668 3670 In version 1, the delta is always applied against the previous node from
3669 3671 the changegroup or the first parent if this is the first entry in the
3670 3672 changegroup.
3671 3673 </p>
3672 3674 <p>
3673 3675 In version 2 and up, the delta base node is encoded in the entry in the
3674 3676 changegroup. This allows the delta to be expressed against any parent,
3675 3677 which can result in smaller deltas and more efficient encoding of data.
3676 3678 </p>
3677 3679 <p>
3678 3680 The *flags* field holds bitwise flags affecting the processing of revision
3679 3681 data. The following flags are defined:
3680 3682 </p>
3681 3683 <dl>
3682 3684 <dt>32768
3683 3685 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3684 3686 <dt>16384
3685 3687 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3686 3688 <dt>8192
3687 3689 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3688 3690 </dl>
3689 3691 <p>
3690 3692 For historical reasons, the integer values are identical to revlog version 1
3691 3693 per-revision storage flags and correspond to bits being set in this 2-byte
3692 3694 field. Bits were allocated starting from the most-significant bit, hence the
3693 3695 reverse ordering and allocation of these flags.
3694 3696 </p>
3695 3697 <h2>Changeset Segment</h2>
3696 3698 <p>
3697 3699 The *changeset segment* consists of a single *delta group* holding
3698 3700 changelog data. The *empty chunk* at the end of the *delta group* denotes
3699 3701 the boundary to the *manifest segment*.
3700 3702 </p>
3701 3703 <h2>Manifest Segment</h2>
3702 3704 <p>
3703 3705 The *manifest segment* consists of a single *delta group* holding manifest
3704 3706 data. If treemanifests are in use, it contains only the manifest for the
3705 3707 root directory of the repository. Otherwise, it contains the entire
3706 3708 manifest data. The *empty chunk* at the end of the *delta group* denotes
3707 3709 the boundary to the next segment (either the *treemanifests segment* or the
3708 3710 *filelogs segment*, depending on version and the request options).
3709 3711 </p>
3710 3712 <h3>Treemanifests Segment</h3>
3711 3713 <p>
3712 3714 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3713 3715 only if the 'treemanifest' param is part of the bundle2 changegroup part
3714 3716 (it is not possible to use changegroup version 3 outside of bundle2).
3715 3717 Aside from the filenames in the *treemanifests segment* containing a
3716 3718 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3717 3719 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3718 3720 a sub-segment with filename size 0). This denotes the boundary to the
3719 3721 *filelogs segment*.
3720 3722 </p>
3721 3723 <h2>Filelogs Segment</h2>
3722 3724 <p>
3723 3725 The *filelogs segment* consists of multiple sub-segments, each
3724 3726 corresponding to an individual file whose data is being described:
3725 3727 </p>
3726 3728 <pre>
3727 3729 +--------------------------------------------------+
3728 3730 | | | | | |
3729 3731 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3730 3732 | | | | | (4 bytes) |
3731 3733 | | | | | |
3732 3734 +--------------------------------------------------+
3733 3735 </pre>
3734 3736 <p>
3735 3737 The final filelog sub-segment is followed by an *empty chunk* (logically,
3736 3738 a sub-segment with filename size 0). This denotes the end of the segment
3737 3739 and of the overall changegroup.
3738 3740 </p>
3739 3741 <p>
3740 3742 Each filelog sub-segment consists of the following:
3741 3743 </p>
3742 3744 <pre>
3743 3745 +------------------------------------------------------+
3744 3746 | | | |
3745 3747 | filename length | filename | delta group |
3746 3748 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3747 3749 | | | |
3748 3750 +------------------------------------------------------+
3749 3751 </pre>
3750 3752 <p>
3751 3753 That is, a *chunk* consisting of the filename (not terminated or padded)
3752 3754 followed by N chunks constituting the *delta group* for this file. The
3753 3755 *empty chunk* at the end of each *delta group* denotes the boundary to the
3754 3756 next filelog sub-segment.
3755 3757 </p>
3756 3758
3757 3759 </div>
3758 3760 </div>
3759 3761 </div>
3760 3762
3761 3763
3762 3764
3763 3765 </body>
3764 3766 </html>
3765 3767
3766 3768
3767 3769 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3768 3770 404 Not Found
3769 3771
3770 3772 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3771 3773 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3772 3774 <head>
3773 3775 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3774 3776 <meta name="robots" content="index, nofollow" />
3775 3777 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3776 3778 <script type="text/javascript" src="/static/mercurial.js"></script>
3777 3779
3778 3780 <title>test: error</title>
3779 3781 </head>
3780 3782 <body>
3781 3783
3782 3784 <div class="container">
3783 3785 <div class="menu">
3784 3786 <div class="logo">
3785 3787 <a href="https://mercurial-scm.org/">
3786 3788 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3787 3789 </div>
3788 3790 <ul>
3789 3791 <li><a href="/shortlog">log</a></li>
3790 3792 <li><a href="/graph">graph</a></li>
3791 3793 <li><a href="/tags">tags</a></li>
3792 3794 <li><a href="/bookmarks">bookmarks</a></li>
3793 3795 <li><a href="/branches">branches</a></li>
3794 3796 </ul>
3795 3797 <ul>
3796 3798 <li><a href="/help">help</a></li>
3797 3799 </ul>
3798 3800 </div>
3799 3801
3800 3802 <div class="main">
3801 3803
3802 3804 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3803 3805 <h3>error</h3>
3804 3806
3805 3807
3806 3808 <form class="search" action="/log">
3807 3809
3808 3810 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3809 3811 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3810 3812 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3811 3813 </form>
3812 3814
3813 3815 <div class="description">
3814 3816 <p>
3815 3817 An error occurred while processing your request:
3816 3818 </p>
3817 3819 <p>
3818 3820 Not Found
3819 3821 </p>
3820 3822 </div>
3821 3823 </div>
3822 3824 </div>
3823 3825
3824 3826
3825 3827
3826 3828 </body>
3827 3829 </html>
3828 3830
3829 3831 [1]
3830 3832
3831 3833 $ killdaemons.py
3832 3834
3833 3835 #endif
General Comments 0
You need to be logged in to leave comments. Login now