##// END OF EJS Templates
abort: added logic for of hg abort...
Taapas Agrawal -
r42784:bb135a78 default
parent child Browse files
Show More
@@ -1,6370 +1,6395 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 revsetlang,
57 57 rewriteutil,
58 58 scmutil,
59 59 server,
60 60 shelve as shelvemod,
61 61 state as statemod,
62 62 streamclone,
63 63 tags as tagsmod,
64 64 ui as uimod,
65 65 util,
66 66 verify as verifymod,
67 67 wireprotoserver,
68 68 )
69 69 from .utils import (
70 70 dateutil,
71 71 stringutil,
72 72 )
73 73
74 74 table = {}
75 75 table.update(debugcommandsmod.command._table)
76 76
77 77 command = registrar.command(table)
78 78 INTENT_READONLY = registrar.INTENT_READONLY
79 79
80 80 # common command options
81 81
82 82 globalopts = [
83 83 ('R', 'repository', '',
84 84 _('repository root directory or name of overlay bundle file'),
85 85 _('REPO')),
86 86 ('', 'cwd', '',
87 87 _('change working directory'), _('DIR')),
88 88 ('y', 'noninteractive', None,
89 89 _('do not prompt, automatically pick the first choice for all prompts')),
90 90 ('q', 'quiet', None, _('suppress output')),
91 91 ('v', 'verbose', None, _('enable additional output')),
92 92 ('', 'color', '',
93 93 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
94 94 # and should not be translated
95 95 _("when to colorize (boolean, always, auto, never, or debug)"),
96 96 _('TYPE')),
97 97 ('', 'config', [],
98 98 _('set/override config option (use \'section.name=value\')'),
99 99 _('CONFIG')),
100 100 ('', 'debug', None, _('enable debugging output')),
101 101 ('', 'debugger', None, _('start debugger')),
102 102 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
103 103 _('ENCODE')),
104 104 ('', 'encodingmode', encoding.encodingmode,
105 105 _('set the charset encoding mode'), _('MODE')),
106 106 ('', 'traceback', None, _('always print a traceback on exception')),
107 107 ('', 'time', None, _('time how long the command takes')),
108 108 ('', 'profile', None, _('print command execution profile')),
109 109 ('', 'version', None, _('output version information and exit')),
110 110 ('h', 'help', None, _('display help and exit')),
111 111 ('', 'hidden', False, _('consider hidden changesets')),
112 112 ('', 'pager', 'auto',
113 113 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
114 114 ]
115 115
116 116 dryrunopts = cmdutil.dryrunopts
117 117 remoteopts = cmdutil.remoteopts
118 118 walkopts = cmdutil.walkopts
119 119 commitopts = cmdutil.commitopts
120 120 commitopts2 = cmdutil.commitopts2
121 121 formatteropts = cmdutil.formatteropts
122 122 templateopts = cmdutil.templateopts
123 123 logopts = cmdutil.logopts
124 124 diffopts = cmdutil.diffopts
125 125 diffwsopts = cmdutil.diffwsopts
126 126 diffopts2 = cmdutil.diffopts2
127 127 mergetoolopts = cmdutil.mergetoolopts
128 128 similarityopts = cmdutil.similarityopts
129 129 subrepoopts = cmdutil.subrepoopts
130 130 debugrevlogopts = cmdutil.debugrevlogopts
131 131
132 132 # Commands start here, listed alphabetically
133 133
134 @command('abort',
135 dryrunopts, helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
136 helpbasic=True)
137 def abort(ui, repo, **opts):
138 """abort an unfinished operation (EXPERIMENTAL)
139
140 Aborts a multistep operation like graft, histedit, rebase, merge,
141 and unshelve if they are in an unfinished state.
142
143 use --dry-run/-n to dry run the command.
144 A new operation can be added to this by registering the operation and
145 abort logic in the unfinishedstates list under statemod.
146 """
147 dryrun = opts.get(r'dry_run')
148 abortstate = cmdutil.getunfinishedstate(repo)
149 if not abortstate:
150 raise error.Abort(_('no operation in progress'))
151 if not abortstate.abortfunc:
152 raise error.Abort((_("%s in progress but does not support 'hg abort'") %
153 (abortstate._opname)), hint=abortstate.hint())
154 if dryrun:
155 ui.status(_('%s in progress, will be aborted\n') % (abortstate._opname))
156 return
157 return abortstate.abortfunc(ui, repo)
158
134 159 @command('add',
135 160 walkopts + subrepoopts + dryrunopts,
136 161 _('[OPTION]... [FILE]...'),
137 162 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
138 163 helpbasic=True, inferrepo=True)
139 164 def add(ui, repo, *pats, **opts):
140 165 """add the specified files on the next commit
141 166
142 167 Schedule files to be version controlled and added to the
143 168 repository.
144 169
145 170 The files will be added to the repository at the next commit. To
146 171 undo an add before that, see :hg:`forget`.
147 172
148 173 If no names are given, add all files to the repository (except
149 174 files matching ``.hgignore``).
150 175
151 176 .. container:: verbose
152 177
153 178 Examples:
154 179
155 180 - New (unknown) files are added
156 181 automatically by :hg:`add`::
157 182
158 183 $ ls
159 184 foo.c
160 185 $ hg status
161 186 ? foo.c
162 187 $ hg add
163 188 adding foo.c
164 189 $ hg status
165 190 A foo.c
166 191
167 192 - Specific files to be added can be specified::
168 193
169 194 $ ls
170 195 bar.c foo.c
171 196 $ hg status
172 197 ? bar.c
173 198 ? foo.c
174 199 $ hg add bar.c
175 200 $ hg status
176 201 A bar.c
177 202 ? foo.c
178 203
179 204 Returns 0 if all files are successfully added.
180 205 """
181 206
182 207 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
183 208 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
184 209 rejected = cmdutil.add(ui, repo, m, "", uipathfn, False, **opts)
185 210 return rejected and 1 or 0
186 211
187 212 @command('addremove',
188 213 similarityopts + subrepoopts + walkopts + dryrunopts,
189 214 _('[OPTION]... [FILE]...'),
190 215 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
191 216 inferrepo=True)
192 217 def addremove(ui, repo, *pats, **opts):
193 218 """add all new files, delete all missing files
194 219
195 220 Add all new files and remove all missing files from the
196 221 repository.
197 222
198 223 Unless names are given, new files are ignored if they match any of
199 224 the patterns in ``.hgignore``. As with add, these changes take
200 225 effect at the next commit.
201 226
202 227 Use the -s/--similarity option to detect renamed files. This
203 228 option takes a percentage between 0 (disabled) and 100 (files must
204 229 be identical) as its parameter. With a parameter greater than 0,
205 230 this compares every removed file with every added file and records
206 231 those similar enough as renames. Detecting renamed files this way
207 232 can be expensive. After using this option, :hg:`status -C` can be
208 233 used to check which files were identified as moved or renamed. If
209 234 not specified, -s/--similarity defaults to 100 and only renames of
210 235 identical files are detected.
211 236
212 237 .. container:: verbose
213 238
214 239 Examples:
215 240
216 241 - A number of files (bar.c and foo.c) are new,
217 242 while foobar.c has been removed (without using :hg:`remove`)
218 243 from the repository::
219 244
220 245 $ ls
221 246 bar.c foo.c
222 247 $ hg status
223 248 ! foobar.c
224 249 ? bar.c
225 250 ? foo.c
226 251 $ hg addremove
227 252 adding bar.c
228 253 adding foo.c
229 254 removing foobar.c
230 255 $ hg status
231 256 A bar.c
232 257 A foo.c
233 258 R foobar.c
234 259
235 260 - A file foobar.c was moved to foo.c without using :hg:`rename`.
236 261 Afterwards, it was edited slightly::
237 262
238 263 $ ls
239 264 foo.c
240 265 $ hg status
241 266 ! foobar.c
242 267 ? foo.c
243 268 $ hg addremove --similarity 90
244 269 removing foobar.c
245 270 adding foo.c
246 271 recording removal of foobar.c as rename to foo.c (94% similar)
247 272 $ hg status -C
248 273 A foo.c
249 274 foobar.c
250 275 R foobar.c
251 276
252 277 Returns 0 if all files are successfully added.
253 278 """
254 279 opts = pycompat.byteskwargs(opts)
255 280 if not opts.get('similarity'):
256 281 opts['similarity'] = '100'
257 282 matcher = scmutil.match(repo[None], pats, opts)
258 283 relative = scmutil.anypats(pats, opts)
259 284 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
260 285 return scmutil.addremove(repo, matcher, "", uipathfn, opts)
261 286
262 287 @command('annotate|blame',
263 288 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
264 289 ('', 'follow', None,
265 290 _('follow copies/renames and list the filename (DEPRECATED)')),
266 291 ('', 'no-follow', None, _("don't follow copies and renames")),
267 292 ('a', 'text', None, _('treat all files as text')),
268 293 ('u', 'user', None, _('list the author (long with -v)')),
269 294 ('f', 'file', None, _('list the filename')),
270 295 ('d', 'date', None, _('list the date (short with -q)')),
271 296 ('n', 'number', None, _('list the revision number (default)')),
272 297 ('c', 'changeset', None, _('list the changeset')),
273 298 ('l', 'line-number', None, _('show line number at the first appearance')),
274 299 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
275 300 ] + diffwsopts + walkopts + formatteropts,
276 301 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
277 302 helpcategory=command.CATEGORY_FILE_CONTENTS,
278 303 helpbasic=True, inferrepo=True)
279 304 def annotate(ui, repo, *pats, **opts):
280 305 """show changeset information by line for each file
281 306
282 307 List changes in files, showing the revision id responsible for
283 308 each line.
284 309
285 310 This command is useful for discovering when a change was made and
286 311 by whom.
287 312
288 313 If you include --file, --user, or --date, the revision number is
289 314 suppressed unless you also include --number.
290 315
291 316 Without the -a/--text option, annotate will avoid processing files
292 317 it detects as binary. With -a, annotate will annotate the file
293 318 anyway, although the results will probably be neither useful
294 319 nor desirable.
295 320
296 321 .. container:: verbose
297 322
298 323 Template:
299 324
300 325 The following keywords are supported in addition to the common template
301 326 keywords and functions. See also :hg:`help templates`.
302 327
303 328 :lines: List of lines with annotation data.
304 329 :path: String. Repository-absolute path of the specified file.
305 330
306 331 And each entry of ``{lines}`` provides the following sub-keywords in
307 332 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
308 333
309 334 :line: String. Line content.
310 335 :lineno: Integer. Line number at that revision.
311 336 :path: String. Repository-absolute path of the file at that revision.
312 337
313 338 See :hg:`help templates.operators` for the list expansion syntax.
314 339
315 340 Returns 0 on success.
316 341 """
317 342 opts = pycompat.byteskwargs(opts)
318 343 if not pats:
319 344 raise error.Abort(_('at least one filename or pattern is required'))
320 345
321 346 if opts.get('follow'):
322 347 # --follow is deprecated and now just an alias for -f/--file
323 348 # to mimic the behavior of Mercurial before version 1.5
324 349 opts['file'] = True
325 350
326 351 if (not opts.get('user') and not opts.get('changeset')
327 352 and not opts.get('date') and not opts.get('file')):
328 353 opts['number'] = True
329 354
330 355 linenumber = opts.get('line_number') is not None
331 356 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
332 357 raise error.Abort(_('at least one of -n/-c is required for -l'))
333 358
334 359 rev = opts.get('rev')
335 360 if rev:
336 361 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
337 362 ctx = scmutil.revsingle(repo, rev)
338 363
339 364 ui.pager('annotate')
340 365 rootfm = ui.formatter('annotate', opts)
341 366 if ui.debugflag:
342 367 shorthex = pycompat.identity
343 368 else:
344 369 def shorthex(h):
345 370 return h[:12]
346 371 if ui.quiet:
347 372 datefunc = dateutil.shortdate
348 373 else:
349 374 datefunc = dateutil.datestr
350 375 if ctx.rev() is None:
351 376 if opts.get('changeset'):
352 377 # omit "+" suffix which is appended to node hex
353 378 def formatrev(rev):
354 379 if rev == wdirrev:
355 380 return '%d' % ctx.p1().rev()
356 381 else:
357 382 return '%d' % rev
358 383 else:
359 384 def formatrev(rev):
360 385 if rev == wdirrev:
361 386 return '%d+' % ctx.p1().rev()
362 387 else:
363 388 return '%d ' % rev
364 389 def formathex(h):
365 390 if h == wdirhex:
366 391 return '%s+' % shorthex(hex(ctx.p1().node()))
367 392 else:
368 393 return '%s ' % shorthex(h)
369 394 else:
370 395 formatrev = b'%d'.__mod__
371 396 formathex = shorthex
372 397
373 398 opmap = [
374 399 ('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
375 400 ('rev', ' ', lambda x: scmutil.intrev(x.fctx), formatrev),
376 401 ('node', ' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
377 402 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
378 403 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
379 404 ('lineno', ':', lambda x: x.lineno, pycompat.bytestr),
380 405 ]
381 406 opnamemap = {
382 407 'rev': 'number',
383 408 'node': 'changeset',
384 409 'path': 'file',
385 410 'lineno': 'line_number',
386 411 }
387 412
388 413 if rootfm.isplain():
389 414 def makefunc(get, fmt):
390 415 return lambda x: fmt(get(x))
391 416 else:
392 417 def makefunc(get, fmt):
393 418 return get
394 419 datahint = rootfm.datahint()
395 420 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
396 421 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
397 422 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
398 423 fields = ' '.join(fn for fn, sep, get, fmt in opmap
399 424 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
400 425
401 426 def bad(x, y):
402 427 raise error.Abort("%s: %s" % (x, y))
403 428
404 429 m = scmutil.match(ctx, pats, opts, badfn=bad)
405 430
406 431 follow = not opts.get('no_follow')
407 432 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
408 433 whitespace=True)
409 434 skiprevs = opts.get('skip')
410 435 if skiprevs:
411 436 skiprevs = scmutil.revrange(repo, skiprevs)
412 437
413 438 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
414 439 for abs in ctx.walk(m):
415 440 fctx = ctx[abs]
416 441 rootfm.startitem()
417 442 rootfm.data(path=abs)
418 443 if not opts.get('text') and fctx.isbinary():
419 444 rootfm.plain(_("%s: binary file\n") % uipathfn(abs))
420 445 continue
421 446
422 447 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
423 448 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
424 449 diffopts=diffopts)
425 450 if not lines:
426 451 fm.end()
427 452 continue
428 453 formats = []
429 454 pieces = []
430 455
431 456 for f, sep in funcmap:
432 457 l = [f(n) for n in lines]
433 458 if fm.isplain():
434 459 sizes = [encoding.colwidth(x) for x in l]
435 460 ml = max(sizes)
436 461 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
437 462 else:
438 463 formats.append(['%s' for x in l])
439 464 pieces.append(l)
440 465
441 466 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
442 467 fm.startitem()
443 468 fm.context(fctx=n.fctx)
444 469 fm.write(fields, "".join(f), *p)
445 470 if n.skip:
446 471 fmt = "* %s"
447 472 else:
448 473 fmt = ": %s"
449 474 fm.write('line', fmt, n.text)
450 475
451 476 if not lines[-1].text.endswith('\n'):
452 477 fm.plain('\n')
453 478 fm.end()
454 479
455 480 rootfm.end()
456 481
457 482 @command('archive',
458 483 [('', 'no-decode', None, _('do not pass files through decoders')),
459 484 ('p', 'prefix', '', _('directory prefix for files in archive'),
460 485 _('PREFIX')),
461 486 ('r', 'rev', '', _('revision to distribute'), _('REV')),
462 487 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
463 488 ] + subrepoopts + walkopts,
464 489 _('[OPTION]... DEST'),
465 490 helpcategory=command.CATEGORY_IMPORT_EXPORT)
466 491 def archive(ui, repo, dest, **opts):
467 492 '''create an unversioned archive of a repository revision
468 493
469 494 By default, the revision used is the parent of the working
470 495 directory; use -r/--rev to specify a different revision.
471 496
472 497 The archive type is automatically detected based on file
473 498 extension (to override, use -t/--type).
474 499
475 500 .. container:: verbose
476 501
477 502 Examples:
478 503
479 504 - create a zip file containing the 1.0 release::
480 505
481 506 hg archive -r 1.0 project-1.0.zip
482 507
483 508 - create a tarball excluding .hg files::
484 509
485 510 hg archive project.tar.gz -X ".hg*"
486 511
487 512 Valid types are:
488 513
489 514 :``files``: a directory full of files (default)
490 515 :``tar``: tar archive, uncompressed
491 516 :``tbz2``: tar archive, compressed using bzip2
492 517 :``tgz``: tar archive, compressed using gzip
493 518 :``uzip``: zip archive, uncompressed
494 519 :``zip``: zip archive, compressed using deflate
495 520
496 521 The exact name of the destination archive or directory is given
497 522 using a format string; see :hg:`help export` for details.
498 523
499 524 Each member added to an archive file has a directory prefix
500 525 prepended. Use -p/--prefix to specify a format string for the
501 526 prefix. The default is the basename of the archive, with suffixes
502 527 removed.
503 528
504 529 Returns 0 on success.
505 530 '''
506 531
507 532 opts = pycompat.byteskwargs(opts)
508 533 rev = opts.get('rev')
509 534 if rev:
510 535 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
511 536 ctx = scmutil.revsingle(repo, rev)
512 537 if not ctx:
513 538 raise error.Abort(_('no working directory: please specify a revision'))
514 539 node = ctx.node()
515 540 dest = cmdutil.makefilename(ctx, dest)
516 541 if os.path.realpath(dest) == repo.root:
517 542 raise error.Abort(_('repository root cannot be destination'))
518 543
519 544 kind = opts.get('type') or archival.guesskind(dest) or 'files'
520 545 prefix = opts.get('prefix')
521 546
522 547 if dest == '-':
523 548 if kind == 'files':
524 549 raise error.Abort(_('cannot archive plain files to stdout'))
525 550 dest = cmdutil.makefileobj(ctx, dest)
526 551 if not prefix:
527 552 prefix = os.path.basename(repo.root) + '-%h'
528 553
529 554 prefix = cmdutil.makefilename(ctx, prefix)
530 555 match = scmutil.match(ctx, [], opts)
531 556 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
532 557 match, prefix, subrepos=opts.get('subrepos'))
533 558
534 559 @command('backout',
535 560 [('', 'merge', None, _('merge with old dirstate parent after backout')),
536 561 ('', 'commit', None,
537 562 _('commit if no conflicts were encountered (DEPRECATED)')),
538 563 ('', 'no-commit', None, _('do not commit')),
539 564 ('', 'parent', '',
540 565 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
541 566 ('r', 'rev', '', _('revision to backout'), _('REV')),
542 567 ('e', 'edit', False, _('invoke editor on commit messages')),
543 568 ] + mergetoolopts + walkopts + commitopts + commitopts2,
544 569 _('[OPTION]... [-r] REV'),
545 570 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
546 571 def backout(ui, repo, node=None, rev=None, **opts):
547 572 '''reverse effect of earlier changeset
548 573
549 574 Prepare a new changeset with the effect of REV undone in the
550 575 current working directory. If no conflicts were encountered,
551 576 it will be committed immediately.
552 577
553 578 If REV is the parent of the working directory, then this new changeset
554 579 is committed automatically (unless --no-commit is specified).
555 580
556 581 .. note::
557 582
558 583 :hg:`backout` cannot be used to fix either an unwanted or
559 584 incorrect merge.
560 585
561 586 .. container:: verbose
562 587
563 588 Examples:
564 589
565 590 - Reverse the effect of the parent of the working directory.
566 591 This backout will be committed immediately::
567 592
568 593 hg backout -r .
569 594
570 595 - Reverse the effect of previous bad revision 23::
571 596
572 597 hg backout -r 23
573 598
574 599 - Reverse the effect of previous bad revision 23 and
575 600 leave changes uncommitted::
576 601
577 602 hg backout -r 23 --no-commit
578 603 hg commit -m "Backout revision 23"
579 604
580 605 By default, the pending changeset will have one parent,
581 606 maintaining a linear history. With --merge, the pending
582 607 changeset will instead have two parents: the old parent of the
583 608 working directory and a new child of REV that simply undoes REV.
584 609
585 610 Before version 1.7, the behavior without --merge was equivalent
586 611 to specifying --merge followed by :hg:`update --clean .` to
587 612 cancel the merge and leave the child of REV as a head to be
588 613 merged separately.
589 614
590 615 See :hg:`help dates` for a list of formats valid for -d/--date.
591 616
592 617 See :hg:`help revert` for a way to restore files to the state
593 618 of another revision.
594 619
595 620 Returns 0 on success, 1 if nothing to backout or there are unresolved
596 621 files.
597 622 '''
598 623 with repo.wlock(), repo.lock():
599 624 return _dobackout(ui, repo, node, rev, **opts)
600 625
601 626 def _dobackout(ui, repo, node=None, rev=None, **opts):
602 627 opts = pycompat.byteskwargs(opts)
603 628 if opts.get('commit') and opts.get('no_commit'):
604 629 raise error.Abort(_("cannot use --commit with --no-commit"))
605 630 if opts.get('merge') and opts.get('no_commit'):
606 631 raise error.Abort(_("cannot use --merge with --no-commit"))
607 632
608 633 if rev and node:
609 634 raise error.Abort(_("please specify just one revision"))
610 635
611 636 if not rev:
612 637 rev = node
613 638
614 639 if not rev:
615 640 raise error.Abort(_("please specify a revision to backout"))
616 641
617 642 date = opts.get('date')
618 643 if date:
619 644 opts['date'] = dateutil.parsedate(date)
620 645
621 646 cmdutil.checkunfinished(repo)
622 647 cmdutil.bailifchanged(repo)
623 648 node = scmutil.revsingle(repo, rev).node()
624 649
625 650 op1, op2 = repo.dirstate.parents()
626 651 if not repo.changelog.isancestor(node, op1):
627 652 raise error.Abort(_('cannot backout change that is not an ancestor'))
628 653
629 654 p1, p2 = repo.changelog.parents(node)
630 655 if p1 == nullid:
631 656 raise error.Abort(_('cannot backout a change with no parents'))
632 657 if p2 != nullid:
633 658 if not opts.get('parent'):
634 659 raise error.Abort(_('cannot backout a merge changeset'))
635 660 p = repo.lookup(opts['parent'])
636 661 if p not in (p1, p2):
637 662 raise error.Abort(_('%s is not a parent of %s') %
638 663 (short(p), short(node)))
639 664 parent = p
640 665 else:
641 666 if opts.get('parent'):
642 667 raise error.Abort(_('cannot use --parent on non-merge changeset'))
643 668 parent = p1
644 669
645 670 # the backout should appear on the same branch
646 671 branch = repo.dirstate.branch()
647 672 bheads = repo.branchheads(branch)
648 673 rctx = scmutil.revsingle(repo, hex(parent))
649 674 if not opts.get('merge') and op1 != node:
650 675 with dirstateguard.dirstateguard(repo, 'backout'):
651 676 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
652 677 with ui.configoverride(overrides, 'backout'):
653 678 stats = mergemod.update(repo, parent, branchmerge=True,
654 679 force=True, ancestor=node,
655 680 mergeancestor=False)
656 681 repo.setparents(op1, op2)
657 682 hg._showstats(repo, stats)
658 683 if stats.unresolvedcount:
659 684 repo.ui.status(_("use 'hg resolve' to retry unresolved "
660 685 "file merges\n"))
661 686 return 1
662 687 else:
663 688 hg.clean(repo, node, show_stats=False)
664 689 repo.dirstate.setbranch(branch)
665 690 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
666 691
667 692 if opts.get('no_commit'):
668 693 msg = _("changeset %s backed out, "
669 694 "don't forget to commit.\n")
670 695 ui.status(msg % short(node))
671 696 return 0
672 697
673 698 def commitfunc(ui, repo, message, match, opts):
674 699 editform = 'backout'
675 700 e = cmdutil.getcommiteditor(editform=editform,
676 701 **pycompat.strkwargs(opts))
677 702 if not message:
678 703 # we don't translate commit messages
679 704 message = "Backed out changeset %s" % short(node)
680 705 e = cmdutil.getcommiteditor(edit=True, editform=editform)
681 706 return repo.commit(message, opts.get('user'), opts.get('date'),
682 707 match, editor=e)
683 708 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
684 709 if not newnode:
685 710 ui.status(_("nothing changed\n"))
686 711 return 1
687 712 cmdutil.commitstatus(repo, newnode, branch, bheads)
688 713
689 714 def nice(node):
690 715 return '%d:%s' % (repo.changelog.rev(node), short(node))
691 716 ui.status(_('changeset %s backs out changeset %s\n') %
692 717 (nice(repo.changelog.tip()), nice(node)))
693 718 if opts.get('merge') and op1 != node:
694 719 hg.clean(repo, op1, show_stats=False)
695 720 ui.status(_('merging with changeset %s\n')
696 721 % nice(repo.changelog.tip()))
697 722 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
698 723 with ui.configoverride(overrides, 'backout'):
699 724 return hg.merge(repo, hex(repo.changelog.tip()))
700 725 return 0
701 726
702 727 @command('bisect',
703 728 [('r', 'reset', False, _('reset bisect state')),
704 729 ('g', 'good', False, _('mark changeset good')),
705 730 ('b', 'bad', False, _('mark changeset bad')),
706 731 ('s', 'skip', False, _('skip testing changeset')),
707 732 ('e', 'extend', False, _('extend the bisect range')),
708 733 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
709 734 ('U', 'noupdate', False, _('do not update to target'))],
710 735 _("[-gbsr] [-U] [-c CMD] [REV]"),
711 736 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
712 737 def bisect(ui, repo, rev=None, extra=None, command=None,
713 738 reset=None, good=None, bad=None, skip=None, extend=None,
714 739 noupdate=None):
715 740 """subdivision search of changesets
716 741
717 742 This command helps to find changesets which introduce problems. To
718 743 use, mark the earliest changeset you know exhibits the problem as
719 744 bad, then mark the latest changeset which is free from the problem
720 745 as good. Bisect will update your working directory to a revision
721 746 for testing (unless the -U/--noupdate option is specified). Once
722 747 you have performed tests, mark the working directory as good or
723 748 bad, and bisect will either update to another candidate changeset
724 749 or announce that it has found the bad revision.
725 750
726 751 As a shortcut, you can also use the revision argument to mark a
727 752 revision as good or bad without checking it out first.
728 753
729 754 If you supply a command, it will be used for automatic bisection.
730 755 The environment variable HG_NODE will contain the ID of the
731 756 changeset being tested. The exit status of the command will be
732 757 used to mark revisions as good or bad: status 0 means good, 125
733 758 means to skip the revision, 127 (command not found) will abort the
734 759 bisection, and any other non-zero exit status means the revision
735 760 is bad.
736 761
737 762 .. container:: verbose
738 763
739 764 Some examples:
740 765
741 766 - start a bisection with known bad revision 34, and good revision 12::
742 767
743 768 hg bisect --bad 34
744 769 hg bisect --good 12
745 770
746 771 - advance the current bisection by marking current revision as good or
747 772 bad::
748 773
749 774 hg bisect --good
750 775 hg bisect --bad
751 776
752 777 - mark the current revision, or a known revision, to be skipped (e.g. if
753 778 that revision is not usable because of another issue)::
754 779
755 780 hg bisect --skip
756 781 hg bisect --skip 23
757 782
758 783 - skip all revisions that do not touch directories ``foo`` or ``bar``::
759 784
760 785 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
761 786
762 787 - forget the current bisection::
763 788
764 789 hg bisect --reset
765 790
766 791 - use 'make && make tests' to automatically find the first broken
767 792 revision::
768 793
769 794 hg bisect --reset
770 795 hg bisect --bad 34
771 796 hg bisect --good 12
772 797 hg bisect --command "make && make tests"
773 798
774 799 - see all changesets whose states are already known in the current
775 800 bisection::
776 801
777 802 hg log -r "bisect(pruned)"
778 803
779 804 - see the changeset currently being bisected (especially useful
780 805 if running with -U/--noupdate)::
781 806
782 807 hg log -r "bisect(current)"
783 808
784 809 - see all changesets that took part in the current bisection::
785 810
786 811 hg log -r "bisect(range)"
787 812
788 813 - you can even get a nice graph::
789 814
790 815 hg log --graph -r "bisect(range)"
791 816
792 817 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
793 818
794 819 Returns 0 on success.
795 820 """
796 821 # backward compatibility
797 822 if rev in "good bad reset init".split():
798 823 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
799 824 cmd, rev, extra = rev, extra, None
800 825 if cmd == "good":
801 826 good = True
802 827 elif cmd == "bad":
803 828 bad = True
804 829 else:
805 830 reset = True
806 831 elif extra:
807 832 raise error.Abort(_('incompatible arguments'))
808 833
809 834 incompatibles = {
810 835 '--bad': bad,
811 836 '--command': bool(command),
812 837 '--extend': extend,
813 838 '--good': good,
814 839 '--reset': reset,
815 840 '--skip': skip,
816 841 }
817 842
818 843 enabled = [x for x in incompatibles if incompatibles[x]]
819 844
820 845 if len(enabled) > 1:
821 846 raise error.Abort(_('%s and %s are incompatible') %
822 847 tuple(sorted(enabled)[0:2]))
823 848
824 849 if reset:
825 850 hbisect.resetstate(repo)
826 851 return
827 852
828 853 state = hbisect.load_state(repo)
829 854
830 855 # update state
831 856 if good or bad or skip:
832 857 if rev:
833 858 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
834 859 else:
835 860 nodes = [repo.lookup('.')]
836 861 if good:
837 862 state['good'] += nodes
838 863 elif bad:
839 864 state['bad'] += nodes
840 865 elif skip:
841 866 state['skip'] += nodes
842 867 hbisect.save_state(repo, state)
843 868 if not (state['good'] and state['bad']):
844 869 return
845 870
846 871 def mayupdate(repo, node, show_stats=True):
847 872 """common used update sequence"""
848 873 if noupdate:
849 874 return
850 875 cmdutil.checkunfinished(repo)
851 876 cmdutil.bailifchanged(repo)
852 877 return hg.clean(repo, node, show_stats=show_stats)
853 878
854 879 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
855 880
856 881 if command:
857 882 changesets = 1
858 883 if noupdate:
859 884 try:
860 885 node = state['current'][0]
861 886 except LookupError:
862 887 raise error.Abort(_('current bisect revision is unknown - '
863 888 'start a new bisect to fix'))
864 889 else:
865 890 node, p2 = repo.dirstate.parents()
866 891 if p2 != nullid:
867 892 raise error.Abort(_('current bisect revision is a merge'))
868 893 if rev:
869 894 node = repo[scmutil.revsingle(repo, rev, node)].node()
870 895 try:
871 896 while changesets:
872 897 # update state
873 898 state['current'] = [node]
874 899 hbisect.save_state(repo, state)
875 900 status = ui.system(command, environ={'HG_NODE': hex(node)},
876 901 blockedtag='bisect_check')
877 902 if status == 125:
878 903 transition = "skip"
879 904 elif status == 0:
880 905 transition = "good"
881 906 # status < 0 means process was killed
882 907 elif status == 127:
883 908 raise error.Abort(_("failed to execute %s") % command)
884 909 elif status < 0:
885 910 raise error.Abort(_("%s killed") % command)
886 911 else:
887 912 transition = "bad"
888 913 state[transition].append(node)
889 914 ctx = repo[node]
890 915 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
891 916 transition))
892 917 hbisect.checkstate(state)
893 918 # bisect
894 919 nodes, changesets, bgood = hbisect.bisect(repo, state)
895 920 # update to next check
896 921 node = nodes[0]
897 922 mayupdate(repo, node, show_stats=False)
898 923 finally:
899 924 state['current'] = [node]
900 925 hbisect.save_state(repo, state)
901 926 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
902 927 return
903 928
904 929 hbisect.checkstate(state)
905 930
906 931 # actually bisect
907 932 nodes, changesets, good = hbisect.bisect(repo, state)
908 933 if extend:
909 934 if not changesets:
910 935 extendnode = hbisect.extendrange(repo, state, nodes, good)
911 936 if extendnode is not None:
912 937 ui.write(_("Extending search to changeset %d:%s\n")
913 938 % (extendnode.rev(), extendnode))
914 939 state['current'] = [extendnode.node()]
915 940 hbisect.save_state(repo, state)
916 941 return mayupdate(repo, extendnode.node())
917 942 raise error.Abort(_("nothing to extend"))
918 943
919 944 if changesets == 0:
920 945 hbisect.printresult(ui, repo, state, displayer, nodes, good)
921 946 else:
922 947 assert len(nodes) == 1 # only a single node can be tested next
923 948 node = nodes[0]
924 949 # compute the approximate number of remaining tests
925 950 tests, size = 0, 2
926 951 while size <= changesets:
927 952 tests, size = tests + 1, size * 2
928 953 rev = repo.changelog.rev(node)
929 954 ui.write(_("Testing changeset %d:%s "
930 955 "(%d changesets remaining, ~%d tests)\n")
931 956 % (rev, short(node), changesets, tests))
932 957 state['current'] = [node]
933 958 hbisect.save_state(repo, state)
934 959 return mayupdate(repo, node)
935 960
936 961 @command('bookmarks|bookmark',
937 962 [('f', 'force', False, _('force')),
938 963 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
939 964 ('d', 'delete', False, _('delete a given bookmark')),
940 965 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
941 966 ('i', 'inactive', False, _('mark a bookmark inactive')),
942 967 ('l', 'list', False, _('list existing bookmarks')),
943 968 ] + formatteropts,
944 969 _('hg bookmarks [OPTIONS]... [NAME]...'),
945 970 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
946 971 def bookmark(ui, repo, *names, **opts):
947 972 '''create a new bookmark or list existing bookmarks
948 973
949 974 Bookmarks are labels on changesets to help track lines of development.
950 975 Bookmarks are unversioned and can be moved, renamed and deleted.
951 976 Deleting or moving a bookmark has no effect on the associated changesets.
952 977
953 978 Creating or updating to a bookmark causes it to be marked as 'active'.
954 979 The active bookmark is indicated with a '*'.
955 980 When a commit is made, the active bookmark will advance to the new commit.
956 981 A plain :hg:`update` will also advance an active bookmark, if possible.
957 982 Updating away from a bookmark will cause it to be deactivated.
958 983
959 984 Bookmarks can be pushed and pulled between repositories (see
960 985 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
961 986 diverged, a new 'divergent bookmark' of the form 'name@path' will
962 987 be created. Using :hg:`merge` will resolve the divergence.
963 988
964 989 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
965 990 the active bookmark's name.
966 991
967 992 A bookmark named '@' has the special property that :hg:`clone` will
968 993 check it out by default if it exists.
969 994
970 995 .. container:: verbose
971 996
972 997 Template:
973 998
974 999 The following keywords are supported in addition to the common template
975 1000 keywords and functions such as ``{bookmark}``. See also
976 1001 :hg:`help templates`.
977 1002
978 1003 :active: Boolean. True if the bookmark is active.
979 1004
980 1005 Examples:
981 1006
982 1007 - create an active bookmark for a new line of development::
983 1008
984 1009 hg book new-feature
985 1010
986 1011 - create an inactive bookmark as a place marker::
987 1012
988 1013 hg book -i reviewed
989 1014
990 1015 - create an inactive bookmark on another changeset::
991 1016
992 1017 hg book -r .^ tested
993 1018
994 1019 - rename bookmark turkey to dinner::
995 1020
996 1021 hg book -m turkey dinner
997 1022
998 1023 - move the '@' bookmark from another branch::
999 1024
1000 1025 hg book -f @
1001 1026
1002 1027 - print only the active bookmark name::
1003 1028
1004 1029 hg book -ql .
1005 1030 '''
1006 1031 opts = pycompat.byteskwargs(opts)
1007 1032 force = opts.get('force')
1008 1033 rev = opts.get('rev')
1009 1034 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1010 1035
1011 1036 selactions = [k for k in ['delete', 'rename', 'list'] if opts.get(k)]
1012 1037 if len(selactions) > 1:
1013 1038 raise error.Abort(_('--%s and --%s are incompatible')
1014 1039 % tuple(selactions[:2]))
1015 1040 if selactions:
1016 1041 action = selactions[0]
1017 1042 elif names or rev:
1018 1043 action = 'add'
1019 1044 elif inactive:
1020 1045 action = 'inactive' # meaning deactivate
1021 1046 else:
1022 1047 action = 'list'
1023 1048
1024 1049 if rev and action in {'delete', 'rename', 'list'}:
1025 1050 raise error.Abort(_("--rev is incompatible with --%s") % action)
1026 1051 if inactive and action in {'delete', 'list'}:
1027 1052 raise error.Abort(_("--inactive is incompatible with --%s") % action)
1028 1053 if not names and action in {'add', 'delete'}:
1029 1054 raise error.Abort(_("bookmark name required"))
1030 1055
1031 1056 if action in {'add', 'delete', 'rename', 'inactive'}:
1032 1057 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
1033 1058 if action == 'delete':
1034 1059 names = pycompat.maplist(repo._bookmarks.expandname, names)
1035 1060 bookmarks.delete(repo, tr, names)
1036 1061 elif action == 'rename':
1037 1062 if not names:
1038 1063 raise error.Abort(_("new bookmark name required"))
1039 1064 elif len(names) > 1:
1040 1065 raise error.Abort(_("only one new bookmark name allowed"))
1041 1066 oldname = repo._bookmarks.expandname(opts['rename'])
1042 1067 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1043 1068 elif action == 'add':
1044 1069 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1045 1070 elif action == 'inactive':
1046 1071 if len(repo._bookmarks) == 0:
1047 1072 ui.status(_("no bookmarks set\n"))
1048 1073 elif not repo._activebookmark:
1049 1074 ui.status(_("no active bookmark\n"))
1050 1075 else:
1051 1076 bookmarks.deactivate(repo)
1052 1077 elif action == 'list':
1053 1078 names = pycompat.maplist(repo._bookmarks.expandname, names)
1054 1079 with ui.formatter('bookmarks', opts) as fm:
1055 1080 bookmarks.printbookmarks(ui, repo, fm, names)
1056 1081 else:
1057 1082 raise error.ProgrammingError('invalid action: %s' % action)
1058 1083
1059 1084 @command('branch',
1060 1085 [('f', 'force', None,
1061 1086 _('set branch name even if it shadows an existing branch')),
1062 1087 ('C', 'clean', None, _('reset branch name to parent branch name')),
1063 1088 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1064 1089 ],
1065 1090 _('[-fC] [NAME]'),
1066 1091 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
1067 1092 def branch(ui, repo, label=None, **opts):
1068 1093 """set or show the current branch name
1069 1094
1070 1095 .. note::
1071 1096
1072 1097 Branch names are permanent and global. Use :hg:`bookmark` to create a
1073 1098 light-weight bookmark instead. See :hg:`help glossary` for more
1074 1099 information about named branches and bookmarks.
1075 1100
1076 1101 With no argument, show the current branch name. With one argument,
1077 1102 set the working directory branch name (the branch will not exist
1078 1103 in the repository until the next commit). Standard practice
1079 1104 recommends that primary development take place on the 'default'
1080 1105 branch.
1081 1106
1082 1107 Unless -f/--force is specified, branch will not let you set a
1083 1108 branch name that already exists.
1084 1109
1085 1110 Use -C/--clean to reset the working directory branch to that of
1086 1111 the parent of the working directory, negating a previous branch
1087 1112 change.
1088 1113
1089 1114 Use the command :hg:`update` to switch to an existing branch. Use
1090 1115 :hg:`commit --close-branch` to mark this branch head as closed.
1091 1116 When all heads of a branch are closed, the branch will be
1092 1117 considered closed.
1093 1118
1094 1119 Returns 0 on success.
1095 1120 """
1096 1121 opts = pycompat.byteskwargs(opts)
1097 1122 revs = opts.get('rev')
1098 1123 if label:
1099 1124 label = label.strip()
1100 1125
1101 1126 if not opts.get('clean') and not label:
1102 1127 if revs:
1103 1128 raise error.Abort(_("no branch name specified for the revisions"))
1104 1129 ui.write("%s\n" % repo.dirstate.branch())
1105 1130 return
1106 1131
1107 1132 with repo.wlock():
1108 1133 if opts.get('clean'):
1109 1134 label = repo['.'].branch()
1110 1135 repo.dirstate.setbranch(label)
1111 1136 ui.status(_('reset working directory to branch %s\n') % label)
1112 1137 elif label:
1113 1138
1114 1139 scmutil.checknewlabel(repo, label, 'branch')
1115 1140 if revs:
1116 1141 return cmdutil.changebranch(ui, repo, revs, label)
1117 1142
1118 1143 if not opts.get('force') and label in repo.branchmap():
1119 1144 if label not in [p.branch() for p in repo[None].parents()]:
1120 1145 raise error.Abort(_('a branch of the same name already'
1121 1146 ' exists'),
1122 1147 # i18n: "it" refers to an existing branch
1123 1148 hint=_("use 'hg update' to switch to it"))
1124 1149
1125 1150 repo.dirstate.setbranch(label)
1126 1151 ui.status(_('marked working directory as branch %s\n') % label)
1127 1152
1128 1153 # find any open named branches aside from default
1129 1154 for n, h, t, c in repo.branchmap().iterbranches():
1130 1155 if n != "default" and not c:
1131 1156 return 0
1132 1157 ui.status(_('(branches are permanent and global, '
1133 1158 'did you want a bookmark?)\n'))
1134 1159
1135 1160 @command('branches',
1136 1161 [('a', 'active', False,
1137 1162 _('show only branches that have unmerged heads (DEPRECATED)')),
1138 1163 ('c', 'closed', False, _('show normal and closed branches')),
1139 1164 ('r', 'rev', [], _('show branch name(s) of the given rev'))
1140 1165 ] + formatteropts,
1141 1166 _('[-c]'),
1142 1167 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1143 1168 intents={INTENT_READONLY})
1144 1169 def branches(ui, repo, active=False, closed=False, **opts):
1145 1170 """list repository named branches
1146 1171
1147 1172 List the repository's named branches, indicating which ones are
1148 1173 inactive. If -c/--closed is specified, also list branches which have
1149 1174 been marked closed (see :hg:`commit --close-branch`).
1150 1175
1151 1176 Use the command :hg:`update` to switch to an existing branch.
1152 1177
1153 1178 .. container:: verbose
1154 1179
1155 1180 Template:
1156 1181
1157 1182 The following keywords are supported in addition to the common template
1158 1183 keywords and functions such as ``{branch}``. See also
1159 1184 :hg:`help templates`.
1160 1185
1161 1186 :active: Boolean. True if the branch is active.
1162 1187 :closed: Boolean. True if the branch is closed.
1163 1188 :current: Boolean. True if it is the current branch.
1164 1189
1165 1190 Returns 0.
1166 1191 """
1167 1192
1168 1193 opts = pycompat.byteskwargs(opts)
1169 1194 revs = opts.get('rev')
1170 1195 selectedbranches = None
1171 1196 if revs:
1172 1197 revs = scmutil.revrange(repo, revs)
1173 1198 getbi = repo.revbranchcache().branchinfo
1174 1199 selectedbranches = {getbi(r)[0] for r in revs}
1175 1200
1176 1201 ui.pager('branches')
1177 1202 fm = ui.formatter('branches', opts)
1178 1203 hexfunc = fm.hexfunc
1179 1204
1180 1205 allheads = set(repo.heads())
1181 1206 branches = []
1182 1207 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1183 1208 if selectedbranches is not None and tag not in selectedbranches:
1184 1209 continue
1185 1210 isactive = False
1186 1211 if not isclosed:
1187 1212 openheads = set(repo.branchmap().iteropen(heads))
1188 1213 isactive = bool(openheads & allheads)
1189 1214 branches.append((tag, repo[tip], isactive, not isclosed))
1190 1215 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1191 1216 reverse=True)
1192 1217
1193 1218 for tag, ctx, isactive, isopen in branches:
1194 1219 if active and not isactive:
1195 1220 continue
1196 1221 if isactive:
1197 1222 label = 'branches.active'
1198 1223 notice = ''
1199 1224 elif not isopen:
1200 1225 if not closed:
1201 1226 continue
1202 1227 label = 'branches.closed'
1203 1228 notice = _(' (closed)')
1204 1229 else:
1205 1230 label = 'branches.inactive'
1206 1231 notice = _(' (inactive)')
1207 1232 current = (tag == repo.dirstate.branch())
1208 1233 if current:
1209 1234 label = 'branches.current'
1210 1235
1211 1236 fm.startitem()
1212 1237 fm.write('branch', '%s', tag, label=label)
1213 1238 rev = ctx.rev()
1214 1239 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1215 1240 fmt = ' ' * padsize + ' %d:%s'
1216 1241 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1217 1242 label='log.changeset changeset.%s' % ctx.phasestr())
1218 1243 fm.context(ctx=ctx)
1219 1244 fm.data(active=isactive, closed=not isopen, current=current)
1220 1245 if not ui.quiet:
1221 1246 fm.plain(notice)
1222 1247 fm.plain('\n')
1223 1248 fm.end()
1224 1249
1225 1250 @command('bundle',
1226 1251 [('f', 'force', None, _('run even when the destination is unrelated')),
1227 1252 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1228 1253 _('REV')),
1229 1254 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1230 1255 _('BRANCH')),
1231 1256 ('', 'base', [],
1232 1257 _('a base changeset assumed to be available at the destination'),
1233 1258 _('REV')),
1234 1259 ('a', 'all', None, _('bundle all changesets in the repository')),
1235 1260 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1236 1261 ] + remoteopts,
1237 1262 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1238 1263 helpcategory=command.CATEGORY_IMPORT_EXPORT)
1239 1264 def bundle(ui, repo, fname, dest=None, **opts):
1240 1265 """create a bundle file
1241 1266
1242 1267 Generate a bundle file containing data to be transferred to another
1243 1268 repository.
1244 1269
1245 1270 To create a bundle containing all changesets, use -a/--all
1246 1271 (or --base null). Otherwise, hg assumes the destination will have
1247 1272 all the nodes you specify with --base parameters. Otherwise, hg
1248 1273 will assume the repository has all the nodes in destination, or
1249 1274 default-push/default if no destination is specified, where destination
1250 1275 is the repository you provide through DEST option.
1251 1276
1252 1277 You can change bundle format with the -t/--type option. See
1253 1278 :hg:`help bundlespec` for documentation on this format. By default,
1254 1279 the most appropriate format is used and compression defaults to
1255 1280 bzip2.
1256 1281
1257 1282 The bundle file can then be transferred using conventional means
1258 1283 and applied to another repository with the unbundle or pull
1259 1284 command. This is useful when direct push and pull are not
1260 1285 available or when exporting an entire repository is undesirable.
1261 1286
1262 1287 Applying bundles preserves all changeset contents including
1263 1288 permissions, copy/rename information, and revision history.
1264 1289
1265 1290 Returns 0 on success, 1 if no changes found.
1266 1291 """
1267 1292 opts = pycompat.byteskwargs(opts)
1268 1293 revs = None
1269 1294 if 'rev' in opts:
1270 1295 revstrings = opts['rev']
1271 1296 revs = scmutil.revrange(repo, revstrings)
1272 1297 if revstrings and not revs:
1273 1298 raise error.Abort(_('no commits to bundle'))
1274 1299
1275 1300 bundletype = opts.get('type', 'bzip2').lower()
1276 1301 try:
1277 1302 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1278 1303 except error.UnsupportedBundleSpecification as e:
1279 1304 raise error.Abort(pycompat.bytestr(e),
1280 1305 hint=_("see 'hg help bundlespec' for supported "
1281 1306 "values for --type"))
1282 1307 cgversion = bundlespec.contentopts["cg.version"]
1283 1308
1284 1309 # Packed bundles are a pseudo bundle format for now.
1285 1310 if cgversion == 's1':
1286 1311 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1287 1312 hint=_("use 'hg debugcreatestreamclonebundle'"))
1288 1313
1289 1314 if opts.get('all'):
1290 1315 if dest:
1291 1316 raise error.Abort(_("--all is incompatible with specifying "
1292 1317 "a destination"))
1293 1318 if opts.get('base'):
1294 1319 ui.warn(_("ignoring --base because --all was specified\n"))
1295 1320 base = [nullrev]
1296 1321 else:
1297 1322 base = scmutil.revrange(repo, opts.get('base'))
1298 1323 if cgversion not in changegroup.supportedoutgoingversions(repo):
1299 1324 raise error.Abort(_("repository does not support bundle version %s") %
1300 1325 cgversion)
1301 1326
1302 1327 if base:
1303 1328 if dest:
1304 1329 raise error.Abort(_("--base is incompatible with specifying "
1305 1330 "a destination"))
1306 1331 common = [repo[rev].node() for rev in base]
1307 1332 heads = [repo[r].node() for r in revs] if revs else None
1308 1333 outgoing = discovery.outgoing(repo, common, heads)
1309 1334 else:
1310 1335 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1311 1336 dest, branches = hg.parseurl(dest, opts.get('branch'))
1312 1337 other = hg.peer(repo, opts, dest)
1313 1338 revs = [repo[r].hex() for r in revs]
1314 1339 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1315 1340 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1316 1341 outgoing = discovery.findcommonoutgoing(repo, other,
1317 1342 onlyheads=heads,
1318 1343 force=opts.get('force'),
1319 1344 portable=True)
1320 1345
1321 1346 if not outgoing.missing:
1322 1347 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1323 1348 return 1
1324 1349
1325 1350 if cgversion == '01': #bundle1
1326 1351 bversion = 'HG10' + bundlespec.wirecompression
1327 1352 bcompression = None
1328 1353 elif cgversion in ('02', '03'):
1329 1354 bversion = 'HG20'
1330 1355 bcompression = bundlespec.wirecompression
1331 1356 else:
1332 1357 raise error.ProgrammingError(
1333 1358 'bundle: unexpected changegroup version %s' % cgversion)
1334 1359
1335 1360 # TODO compression options should be derived from bundlespec parsing.
1336 1361 # This is a temporary hack to allow adjusting bundle compression
1337 1362 # level without a) formalizing the bundlespec changes to declare it
1338 1363 # b) introducing a command flag.
1339 1364 compopts = {}
1340 1365 complevel = ui.configint('experimental',
1341 1366 'bundlecomplevel.' + bundlespec.compression)
1342 1367 if complevel is None:
1343 1368 complevel = ui.configint('experimental', 'bundlecomplevel')
1344 1369 if complevel is not None:
1345 1370 compopts['level'] = complevel
1346 1371
1347 1372 # Allow overriding the bundling of obsmarker in phases through
1348 1373 # configuration while we don't have a bundle version that include them
1349 1374 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1350 1375 bundlespec.contentopts['obsolescence'] = True
1351 1376 if repo.ui.configbool('experimental', 'bundle-phases'):
1352 1377 bundlespec.contentopts['phases'] = True
1353 1378
1354 1379 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1355 1380 bundlespec.contentopts, compression=bcompression,
1356 1381 compopts=compopts)
1357 1382
1358 1383 @command('cat',
1359 1384 [('o', 'output', '',
1360 1385 _('print output to file with formatted name'), _('FORMAT')),
1361 1386 ('r', 'rev', '', _('print the given revision'), _('REV')),
1362 1387 ('', 'decode', None, _('apply any matching decode filter')),
1363 1388 ] + walkopts + formatteropts,
1364 1389 _('[OPTION]... FILE...'),
1365 1390 helpcategory=command.CATEGORY_FILE_CONTENTS,
1366 1391 inferrepo=True,
1367 1392 intents={INTENT_READONLY})
1368 1393 def cat(ui, repo, file1, *pats, **opts):
1369 1394 """output the current or given revision of files
1370 1395
1371 1396 Print the specified files as they were at the given revision. If
1372 1397 no revision is given, the parent of the working directory is used.
1373 1398
1374 1399 Output may be to a file, in which case the name of the file is
1375 1400 given using a template string. See :hg:`help templates`. In addition
1376 1401 to the common template keywords, the following formatting rules are
1377 1402 supported:
1378 1403
1379 1404 :``%%``: literal "%" character
1380 1405 :``%s``: basename of file being printed
1381 1406 :``%d``: dirname of file being printed, or '.' if in repository root
1382 1407 :``%p``: root-relative path name of file being printed
1383 1408 :``%H``: changeset hash (40 hexadecimal digits)
1384 1409 :``%R``: changeset revision number
1385 1410 :``%h``: short-form changeset hash (12 hexadecimal digits)
1386 1411 :``%r``: zero-padded changeset revision number
1387 1412 :``%b``: basename of the exporting repository
1388 1413 :``\\``: literal "\\" character
1389 1414
1390 1415 .. container:: verbose
1391 1416
1392 1417 Template:
1393 1418
1394 1419 The following keywords are supported in addition to the common template
1395 1420 keywords and functions. See also :hg:`help templates`.
1396 1421
1397 1422 :data: String. File content.
1398 1423 :path: String. Repository-absolute path of the file.
1399 1424
1400 1425 Returns 0 on success.
1401 1426 """
1402 1427 opts = pycompat.byteskwargs(opts)
1403 1428 rev = opts.get('rev')
1404 1429 if rev:
1405 1430 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1406 1431 ctx = scmutil.revsingle(repo, rev)
1407 1432 m = scmutil.match(ctx, (file1,) + pats, opts)
1408 1433 fntemplate = opts.pop('output', '')
1409 1434 if cmdutil.isstdiofilename(fntemplate):
1410 1435 fntemplate = ''
1411 1436
1412 1437 if fntemplate:
1413 1438 fm = formatter.nullformatter(ui, 'cat', opts)
1414 1439 else:
1415 1440 ui.pager('cat')
1416 1441 fm = ui.formatter('cat', opts)
1417 1442 with fm:
1418 1443 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1419 1444 **pycompat.strkwargs(opts))
1420 1445
1421 1446 @command('clone',
1422 1447 [('U', 'noupdate', None, _('the clone will include an empty working '
1423 1448 'directory (only a repository)')),
1424 1449 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1425 1450 _('REV')),
1426 1451 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1427 1452 ' and its ancestors'), _('REV')),
1428 1453 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1429 1454 ' changesets and their ancestors'), _('BRANCH')),
1430 1455 ('', 'pull', None, _('use pull protocol to copy metadata')),
1431 1456 ('', 'uncompressed', None,
1432 1457 _('an alias to --stream (DEPRECATED)')),
1433 1458 ('', 'stream', None,
1434 1459 _('clone with minimal data processing')),
1435 1460 ] + remoteopts,
1436 1461 _('[OPTION]... SOURCE [DEST]'),
1437 1462 helpcategory=command.CATEGORY_REPO_CREATION,
1438 1463 helpbasic=True, norepo=True)
1439 1464 def clone(ui, source, dest=None, **opts):
1440 1465 """make a copy of an existing repository
1441 1466
1442 1467 Create a copy of an existing repository in a new directory.
1443 1468
1444 1469 If no destination directory name is specified, it defaults to the
1445 1470 basename of the source.
1446 1471
1447 1472 The location of the source is added to the new repository's
1448 1473 ``.hg/hgrc`` file, as the default to be used for future pulls.
1449 1474
1450 1475 Only local paths and ``ssh://`` URLs are supported as
1451 1476 destinations. For ``ssh://`` destinations, no working directory or
1452 1477 ``.hg/hgrc`` will be created on the remote side.
1453 1478
1454 1479 If the source repository has a bookmark called '@' set, that
1455 1480 revision will be checked out in the new repository by default.
1456 1481
1457 1482 To check out a particular version, use -u/--update, or
1458 1483 -U/--noupdate to create a clone with no working directory.
1459 1484
1460 1485 To pull only a subset of changesets, specify one or more revisions
1461 1486 identifiers with -r/--rev or branches with -b/--branch. The
1462 1487 resulting clone will contain only the specified changesets and
1463 1488 their ancestors. These options (or 'clone src#rev dest') imply
1464 1489 --pull, even for local source repositories.
1465 1490
1466 1491 In normal clone mode, the remote normalizes repository data into a common
1467 1492 exchange format and the receiving end translates this data into its local
1468 1493 storage format. --stream activates a different clone mode that essentially
1469 1494 copies repository files from the remote with minimal data processing. This
1470 1495 significantly reduces the CPU cost of a clone both remotely and locally.
1471 1496 However, it often increases the transferred data size by 30-40%. This can
1472 1497 result in substantially faster clones where I/O throughput is plentiful,
1473 1498 especially for larger repositories. A side-effect of --stream clones is
1474 1499 that storage settings and requirements on the remote are applied locally:
1475 1500 a modern client may inherit legacy or inefficient storage used by the
1476 1501 remote or a legacy Mercurial client may not be able to clone from a
1477 1502 modern Mercurial remote.
1478 1503
1479 1504 .. note::
1480 1505
1481 1506 Specifying a tag will include the tagged changeset but not the
1482 1507 changeset containing the tag.
1483 1508
1484 1509 .. container:: verbose
1485 1510
1486 1511 For efficiency, hardlinks are used for cloning whenever the
1487 1512 source and destination are on the same filesystem (note this
1488 1513 applies only to the repository data, not to the working
1489 1514 directory). Some filesystems, such as AFS, implement hardlinking
1490 1515 incorrectly, but do not report errors. In these cases, use the
1491 1516 --pull option to avoid hardlinking.
1492 1517
1493 1518 Mercurial will update the working directory to the first applicable
1494 1519 revision from this list:
1495 1520
1496 1521 a) null if -U or the source repository has no changesets
1497 1522 b) if -u . and the source repository is local, the first parent of
1498 1523 the source repository's working directory
1499 1524 c) the changeset specified with -u (if a branch name, this means the
1500 1525 latest head of that branch)
1501 1526 d) the changeset specified with -r
1502 1527 e) the tipmost head specified with -b
1503 1528 f) the tipmost head specified with the url#branch source syntax
1504 1529 g) the revision marked with the '@' bookmark, if present
1505 1530 h) the tipmost head of the default branch
1506 1531 i) tip
1507 1532
1508 1533 When cloning from servers that support it, Mercurial may fetch
1509 1534 pre-generated data from a server-advertised URL or inline from the
1510 1535 same stream. When this is done, hooks operating on incoming changesets
1511 1536 and changegroups may fire more than once, once for each pre-generated
1512 1537 bundle and as well as for any additional remaining data. In addition,
1513 1538 if an error occurs, the repository may be rolled back to a partial
1514 1539 clone. This behavior may change in future releases.
1515 1540 See :hg:`help -e clonebundles` for more.
1516 1541
1517 1542 Examples:
1518 1543
1519 1544 - clone a remote repository to a new directory named hg/::
1520 1545
1521 1546 hg clone https://www.mercurial-scm.org/repo/hg/
1522 1547
1523 1548 - create a lightweight local clone::
1524 1549
1525 1550 hg clone project/ project-feature/
1526 1551
1527 1552 - clone from an absolute path on an ssh server (note double-slash)::
1528 1553
1529 1554 hg clone ssh://user@server//home/projects/alpha/
1530 1555
1531 1556 - do a streaming clone while checking out a specified version::
1532 1557
1533 1558 hg clone --stream http://server/repo -u 1.5
1534 1559
1535 1560 - create a repository without changesets after a particular revision::
1536 1561
1537 1562 hg clone -r 04e544 experimental/ good/
1538 1563
1539 1564 - clone (and track) a particular named branch::
1540 1565
1541 1566 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1542 1567
1543 1568 See :hg:`help urls` for details on specifying URLs.
1544 1569
1545 1570 Returns 0 on success.
1546 1571 """
1547 1572 opts = pycompat.byteskwargs(opts)
1548 1573 if opts.get('noupdate') and opts.get('updaterev'):
1549 1574 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1550 1575
1551 1576 # --include/--exclude can come from narrow or sparse.
1552 1577 includepats, excludepats = None, None
1553 1578
1554 1579 # hg.clone() differentiates between None and an empty set. So make sure
1555 1580 # patterns are sets if narrow is requested without patterns.
1556 1581 if opts.get('narrow'):
1557 1582 includepats = set()
1558 1583 excludepats = set()
1559 1584
1560 1585 if opts.get('include'):
1561 1586 includepats = narrowspec.parsepatterns(opts.get('include'))
1562 1587 if opts.get('exclude'):
1563 1588 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1564 1589
1565 1590 r = hg.clone(ui, opts, source, dest,
1566 1591 pull=opts.get('pull'),
1567 1592 stream=opts.get('stream') or opts.get('uncompressed'),
1568 1593 revs=opts.get('rev'),
1569 1594 update=opts.get('updaterev') or not opts.get('noupdate'),
1570 1595 branch=opts.get('branch'),
1571 1596 shareopts=opts.get('shareopts'),
1572 1597 storeincludepats=includepats,
1573 1598 storeexcludepats=excludepats,
1574 1599 depth=opts.get('depth') or None)
1575 1600
1576 1601 return r is None
1577 1602
1578 1603 @command('commit|ci',
1579 1604 [('A', 'addremove', None,
1580 1605 _('mark new/missing files as added/removed before committing')),
1581 1606 ('', 'close-branch', None,
1582 1607 _('mark a branch head as closed')),
1583 1608 ('', 'amend', None, _('amend the parent of the working directory')),
1584 1609 ('s', 'secret', None, _('use the secret phase for committing')),
1585 1610 ('e', 'edit', None, _('invoke editor on commit messages')),
1586 1611 ('', 'force-close-branch', None,
1587 1612 _('forcibly close branch from a non-head changeset (ADVANCED)')),
1588 1613 ('i', 'interactive', None, _('use interactive mode')),
1589 1614 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1590 1615 _('[OPTION]... [FILE]...'),
1591 1616 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True,
1592 1617 inferrepo=True)
1593 1618 def commit(ui, repo, *pats, **opts):
1594 1619 """commit the specified files or all outstanding changes
1595 1620
1596 1621 Commit changes to the given files into the repository. Unlike a
1597 1622 centralized SCM, this operation is a local operation. See
1598 1623 :hg:`push` for a way to actively distribute your changes.
1599 1624
1600 1625 If a list of files is omitted, all changes reported by :hg:`status`
1601 1626 will be committed.
1602 1627
1603 1628 If you are committing the result of a merge, do not provide any
1604 1629 filenames or -I/-X filters.
1605 1630
1606 1631 If no commit message is specified, Mercurial starts your
1607 1632 configured editor where you can enter a message. In case your
1608 1633 commit fails, you will find a backup of your message in
1609 1634 ``.hg/last-message.txt``.
1610 1635
1611 1636 The --close-branch flag can be used to mark the current branch
1612 1637 head closed. When all heads of a branch are closed, the branch
1613 1638 will be considered closed and no longer listed.
1614 1639
1615 1640 The --amend flag can be used to amend the parent of the
1616 1641 working directory with a new commit that contains the changes
1617 1642 in the parent in addition to those currently reported by :hg:`status`,
1618 1643 if there are any. The old commit is stored in a backup bundle in
1619 1644 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1620 1645 on how to restore it).
1621 1646
1622 1647 Message, user and date are taken from the amended commit unless
1623 1648 specified. When a message isn't specified on the command line,
1624 1649 the editor will open with the message of the amended commit.
1625 1650
1626 1651 It is not possible to amend public changesets (see :hg:`help phases`)
1627 1652 or changesets that have children.
1628 1653
1629 1654 See :hg:`help dates` for a list of formats valid for -d/--date.
1630 1655
1631 1656 Returns 0 on success, 1 if nothing changed.
1632 1657
1633 1658 .. container:: verbose
1634 1659
1635 1660 Examples:
1636 1661
1637 1662 - commit all files ending in .py::
1638 1663
1639 1664 hg commit --include "set:**.py"
1640 1665
1641 1666 - commit all non-binary files::
1642 1667
1643 1668 hg commit --exclude "set:binary()"
1644 1669
1645 1670 - amend the current commit and set the date to now::
1646 1671
1647 1672 hg commit --amend --date now
1648 1673 """
1649 1674 with repo.wlock(), repo.lock():
1650 1675 return _docommit(ui, repo, *pats, **opts)
1651 1676
1652 1677 def _docommit(ui, repo, *pats, **opts):
1653 1678 if opts.get(r'interactive'):
1654 1679 opts.pop(r'interactive')
1655 1680 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1656 1681 cmdutil.recordfilter, *pats,
1657 1682 **opts)
1658 1683 # ret can be 0 (no changes to record) or the value returned by
1659 1684 # commit(), 1 if nothing changed or None on success.
1660 1685 return 1 if ret == 0 else ret
1661 1686
1662 1687 opts = pycompat.byteskwargs(opts)
1663 1688 if opts.get('subrepos'):
1664 1689 if opts.get('amend'):
1665 1690 raise error.Abort(_('cannot amend with --subrepos'))
1666 1691 # Let --subrepos on the command line override config setting.
1667 1692 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1668 1693
1669 1694 cmdutil.checkunfinished(repo, commit=True)
1670 1695
1671 1696 branch = repo[None].branch()
1672 1697 bheads = repo.branchheads(branch)
1673 1698
1674 1699 extra = {}
1675 1700 if opts.get('close_branch') or opts.get('force_close_branch'):
1676 1701 extra['close'] = '1'
1677 1702
1678 1703 if repo['.'].closesbranch():
1679 1704 raise error.Abort(_('current revision is already a branch closing'
1680 1705 ' head'))
1681 1706 elif not bheads:
1682 1707 raise error.Abort(_('branch "%s" has no heads to close') % branch)
1683 1708 elif (branch == repo['.'].branch() and repo['.'].node() not in bheads
1684 1709 and not opts.get('force_close_branch')):
1685 1710 hint = _('use --force-close-branch to close branch from a non-head'
1686 1711 ' changeset')
1687 1712 raise error.Abort(_('can only close branch heads'), hint=hint)
1688 1713 elif opts.get('amend'):
1689 1714 if (repo['.'].p1().branch() != branch and
1690 1715 repo['.'].p2().branch() != branch):
1691 1716 raise error.Abort(_('can only close branch heads'))
1692 1717
1693 1718 if opts.get('amend'):
1694 1719 if ui.configbool('ui', 'commitsubrepos'):
1695 1720 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1696 1721
1697 1722 old = repo['.']
1698 1723 rewriteutil.precheck(repo, [old.rev()], 'amend')
1699 1724
1700 1725 # Currently histedit gets confused if an amend happens while histedit
1701 1726 # is in progress. Since we have a checkunfinished command, we are
1702 1727 # temporarily honoring it.
1703 1728 #
1704 1729 # Note: eventually this guard will be removed. Please do not expect
1705 1730 # this behavior to remain.
1706 1731 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1707 1732 cmdutil.checkunfinished(repo)
1708 1733
1709 1734 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1710 1735 if node == old.node():
1711 1736 ui.status(_("nothing changed\n"))
1712 1737 return 1
1713 1738 else:
1714 1739 def commitfunc(ui, repo, message, match, opts):
1715 1740 overrides = {}
1716 1741 if opts.get('secret'):
1717 1742 overrides[('phases', 'new-commit')] = 'secret'
1718 1743
1719 1744 baseui = repo.baseui
1720 1745 with baseui.configoverride(overrides, 'commit'):
1721 1746 with ui.configoverride(overrides, 'commit'):
1722 1747 editform = cmdutil.mergeeditform(repo[None],
1723 1748 'commit.normal')
1724 1749 editor = cmdutil.getcommiteditor(
1725 1750 editform=editform, **pycompat.strkwargs(opts))
1726 1751 return repo.commit(message,
1727 1752 opts.get('user'),
1728 1753 opts.get('date'),
1729 1754 match,
1730 1755 editor=editor,
1731 1756 extra=extra)
1732 1757
1733 1758 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1734 1759
1735 1760 if not node:
1736 1761 stat = cmdutil.postcommitstatus(repo, pats, opts)
1737 1762 if stat[3]:
1738 1763 ui.status(_("nothing changed (%d missing files, see "
1739 1764 "'hg status')\n") % len(stat[3]))
1740 1765 else:
1741 1766 ui.status(_("nothing changed\n"))
1742 1767 return 1
1743 1768
1744 1769 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1745 1770
1746 1771 if not ui.quiet and ui.configbool('commands', 'commit.post-status'):
1747 1772 status(ui, repo, modified=True, added=True, removed=True, deleted=True,
1748 1773 unknown=True, subrepos=opts.get('subrepos'))
1749 1774
1750 1775 @command('config|showconfig|debugconfig',
1751 1776 [('u', 'untrusted', None, _('show untrusted configuration options')),
1752 1777 ('e', 'edit', None, _('edit user config')),
1753 1778 ('l', 'local', None, _('edit repository config')),
1754 1779 ('g', 'global', None, _('edit global config'))] + formatteropts,
1755 1780 _('[-u] [NAME]...'),
1756 1781 helpcategory=command.CATEGORY_HELP,
1757 1782 optionalrepo=True,
1758 1783 intents={INTENT_READONLY})
1759 1784 def config(ui, repo, *values, **opts):
1760 1785 """show combined config settings from all hgrc files
1761 1786
1762 1787 With no arguments, print names and values of all config items.
1763 1788
1764 1789 With one argument of the form section.name, print just the value
1765 1790 of that config item.
1766 1791
1767 1792 With multiple arguments, print names and values of all config
1768 1793 items with matching section names or section.names.
1769 1794
1770 1795 With --edit, start an editor on the user-level config file. With
1771 1796 --global, edit the system-wide config file. With --local, edit the
1772 1797 repository-level config file.
1773 1798
1774 1799 With --debug, the source (filename and line number) is printed
1775 1800 for each config item.
1776 1801
1777 1802 See :hg:`help config` for more information about config files.
1778 1803
1779 1804 .. container:: verbose
1780 1805
1781 1806 Template:
1782 1807
1783 1808 The following keywords are supported. See also :hg:`help templates`.
1784 1809
1785 1810 :name: String. Config name.
1786 1811 :source: String. Filename and line number where the item is defined.
1787 1812 :value: String. Config value.
1788 1813
1789 1814 Returns 0 on success, 1 if NAME does not exist.
1790 1815
1791 1816 """
1792 1817
1793 1818 opts = pycompat.byteskwargs(opts)
1794 1819 if opts.get('edit') or opts.get('local') or opts.get('global'):
1795 1820 if opts.get('local') and opts.get('global'):
1796 1821 raise error.Abort(_("can't use --local and --global together"))
1797 1822
1798 1823 if opts.get('local'):
1799 1824 if not repo:
1800 1825 raise error.Abort(_("can't use --local outside a repository"))
1801 1826 paths = [repo.vfs.join('hgrc')]
1802 1827 elif opts.get('global'):
1803 1828 paths = rcutil.systemrcpath()
1804 1829 else:
1805 1830 paths = rcutil.userrcpath()
1806 1831
1807 1832 for f in paths:
1808 1833 if os.path.exists(f):
1809 1834 break
1810 1835 else:
1811 1836 if opts.get('global'):
1812 1837 samplehgrc = uimod.samplehgrcs['global']
1813 1838 elif opts.get('local'):
1814 1839 samplehgrc = uimod.samplehgrcs['local']
1815 1840 else:
1816 1841 samplehgrc = uimod.samplehgrcs['user']
1817 1842
1818 1843 f = paths[0]
1819 1844 fp = open(f, "wb")
1820 1845 fp.write(util.tonativeeol(samplehgrc))
1821 1846 fp.close()
1822 1847
1823 1848 editor = ui.geteditor()
1824 1849 ui.system("%s \"%s\"" % (editor, f),
1825 1850 onerr=error.Abort, errprefix=_("edit failed"),
1826 1851 blockedtag='config_edit')
1827 1852 return
1828 1853 ui.pager('config')
1829 1854 fm = ui.formatter('config', opts)
1830 1855 for t, f in rcutil.rccomponents():
1831 1856 if t == 'path':
1832 1857 ui.debug('read config from: %s\n' % f)
1833 1858 elif t == 'items':
1834 1859 for section, name, value, source in f:
1835 1860 ui.debug('set config by: %s\n' % source)
1836 1861 else:
1837 1862 raise error.ProgrammingError('unknown rctype: %s' % t)
1838 1863 untrusted = bool(opts.get('untrusted'))
1839 1864
1840 1865 selsections = selentries = []
1841 1866 if values:
1842 1867 selsections = [v for v in values if '.' not in v]
1843 1868 selentries = [v for v in values if '.' in v]
1844 1869 uniquesel = (len(selentries) == 1 and not selsections)
1845 1870 selsections = set(selsections)
1846 1871 selentries = set(selentries)
1847 1872
1848 1873 matched = False
1849 1874 for section, name, value in ui.walkconfig(untrusted=untrusted):
1850 1875 source = ui.configsource(section, name, untrusted)
1851 1876 value = pycompat.bytestr(value)
1852 1877 if fm.isplain():
1853 1878 source = source or 'none'
1854 1879 value = value.replace('\n', '\\n')
1855 1880 entryname = section + '.' + name
1856 1881 if values and not (section in selsections or entryname in selentries):
1857 1882 continue
1858 1883 fm.startitem()
1859 1884 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1860 1885 if uniquesel:
1861 1886 fm.data(name=entryname)
1862 1887 fm.write('value', '%s\n', value)
1863 1888 else:
1864 1889 fm.write('name value', '%s=%s\n', entryname, value)
1865 1890 matched = True
1866 1891 fm.end()
1867 1892 if matched:
1868 1893 return 0
1869 1894 return 1
1870 1895
1871 1896 @command('copy|cp',
1872 1897 [('A', 'after', None, _('record a copy that has already occurred')),
1873 1898 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1874 1899 ] + walkopts + dryrunopts,
1875 1900 _('[OPTION]... SOURCE... DEST'),
1876 1901 helpcategory=command.CATEGORY_FILE_CONTENTS)
1877 1902 def copy(ui, repo, *pats, **opts):
1878 1903 """mark files as copied for the next commit
1879 1904
1880 1905 Mark dest as having copies of source files. If dest is a
1881 1906 directory, copies are put in that directory. If dest is a file,
1882 1907 the source must be a single file.
1883 1908
1884 1909 By default, this command copies the contents of files as they
1885 1910 exist in the working directory. If invoked with -A/--after, the
1886 1911 operation is recorded, but no copying is performed.
1887 1912
1888 1913 This command takes effect with the next commit. To undo a copy
1889 1914 before that, see :hg:`revert`.
1890 1915
1891 1916 Returns 0 on success, 1 if errors are encountered.
1892 1917 """
1893 1918 opts = pycompat.byteskwargs(opts)
1894 1919 with repo.wlock(False):
1895 1920 return cmdutil.copy(ui, repo, pats, opts)
1896 1921
1897 1922 @command(
1898 1923 'debugcommands', [], _('[COMMAND]'),
1899 1924 helpcategory=command.CATEGORY_HELP,
1900 1925 norepo=True)
1901 1926 def debugcommands(ui, cmd='', *args):
1902 1927 """list all available commands and options"""
1903 1928 for cmd, vals in sorted(table.iteritems()):
1904 1929 cmd = cmd.split('|')[0]
1905 1930 opts = ', '.join([i[1] for i in vals[1]])
1906 1931 ui.write('%s: %s\n' % (cmd, opts))
1907 1932
1908 1933 @command('debugcomplete',
1909 1934 [('o', 'options', None, _('show the command options'))],
1910 1935 _('[-o] CMD'),
1911 1936 helpcategory=command.CATEGORY_HELP,
1912 1937 norepo=True)
1913 1938 def debugcomplete(ui, cmd='', **opts):
1914 1939 """returns the completion list associated with the given command"""
1915 1940
1916 1941 if opts.get(r'options'):
1917 1942 options = []
1918 1943 otables = [globalopts]
1919 1944 if cmd:
1920 1945 aliases, entry = cmdutil.findcmd(cmd, table, False)
1921 1946 otables.append(entry[1])
1922 1947 for t in otables:
1923 1948 for o in t:
1924 1949 if "(DEPRECATED)" in o[3]:
1925 1950 continue
1926 1951 if o[0]:
1927 1952 options.append('-%s' % o[0])
1928 1953 options.append('--%s' % o[1])
1929 1954 ui.write("%s\n" % "\n".join(options))
1930 1955 return
1931 1956
1932 1957 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1933 1958 if ui.verbose:
1934 1959 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1935 1960 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1936 1961
1937 1962 @command('diff',
1938 1963 [('r', 'rev', [], _('revision'), _('REV')),
1939 1964 ('c', 'change', '', _('change made by revision'), _('REV'))
1940 1965 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1941 1966 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1942 1967 helpcategory=command.CATEGORY_FILE_CONTENTS,
1943 1968 helpbasic=True, inferrepo=True, intents={INTENT_READONLY})
1944 1969 def diff(ui, repo, *pats, **opts):
1945 1970 """diff repository (or selected files)
1946 1971
1947 1972 Show differences between revisions for the specified files.
1948 1973
1949 1974 Differences between files are shown using the unified diff format.
1950 1975
1951 1976 .. note::
1952 1977
1953 1978 :hg:`diff` may generate unexpected results for merges, as it will
1954 1979 default to comparing against the working directory's first
1955 1980 parent changeset if no revisions are specified.
1956 1981
1957 1982 When two revision arguments are given, then changes are shown
1958 1983 between those revisions. If only one revision is specified then
1959 1984 that revision is compared to the working directory, and, when no
1960 1985 revisions are specified, the working directory files are compared
1961 1986 to its first parent.
1962 1987
1963 1988 Alternatively you can specify -c/--change with a revision to see
1964 1989 the changes in that changeset relative to its first parent.
1965 1990
1966 1991 Without the -a/--text option, diff will avoid generating diffs of
1967 1992 files it detects as binary. With -a, diff will generate a diff
1968 1993 anyway, probably with undesirable results.
1969 1994
1970 1995 Use the -g/--git option to generate diffs in the git extended diff
1971 1996 format. For more information, read :hg:`help diffs`.
1972 1997
1973 1998 .. container:: verbose
1974 1999
1975 2000 Examples:
1976 2001
1977 2002 - compare a file in the current working directory to its parent::
1978 2003
1979 2004 hg diff foo.c
1980 2005
1981 2006 - compare two historical versions of a directory, with rename info::
1982 2007
1983 2008 hg diff --git -r 1.0:1.2 lib/
1984 2009
1985 2010 - get change stats relative to the last change on some date::
1986 2011
1987 2012 hg diff --stat -r "date('may 2')"
1988 2013
1989 2014 - diff all newly-added files that contain a keyword::
1990 2015
1991 2016 hg diff "set:added() and grep(GNU)"
1992 2017
1993 2018 - compare a revision and its parents::
1994 2019
1995 2020 hg diff -c 9353 # compare against first parent
1996 2021 hg diff -r 9353^:9353 # same using revset syntax
1997 2022 hg diff -r 9353^2:9353 # compare against the second parent
1998 2023
1999 2024 Returns 0 on success.
2000 2025 """
2001 2026
2002 2027 opts = pycompat.byteskwargs(opts)
2003 2028 revs = opts.get('rev')
2004 2029 change = opts.get('change')
2005 2030 stat = opts.get('stat')
2006 2031 reverse = opts.get('reverse')
2007 2032
2008 2033 if revs and change:
2009 2034 msg = _('cannot specify --rev and --change at the same time')
2010 2035 raise error.Abort(msg)
2011 2036 elif change:
2012 2037 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
2013 2038 ctx2 = scmutil.revsingle(repo, change, None)
2014 2039 ctx1 = ctx2.p1()
2015 2040 else:
2016 2041 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
2017 2042 ctx1, ctx2 = scmutil.revpair(repo, revs)
2018 2043 node1, node2 = ctx1.node(), ctx2.node()
2019 2044
2020 2045 if reverse:
2021 2046 node1, node2 = node2, node1
2022 2047
2023 2048 diffopts = patch.diffallopts(ui, opts)
2024 2049 m = scmutil.match(ctx2, pats, opts)
2025 2050 m = repo.narrowmatch(m)
2026 2051 ui.pager('diff')
2027 2052 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2028 2053 listsubrepos=opts.get('subrepos'),
2029 2054 root=opts.get('root'))
2030 2055
2031 2056 @command('export',
2032 2057 [('B', 'bookmark', '',
2033 2058 _('export changes only reachable by given bookmark'), _('BOOKMARK')),
2034 2059 ('o', 'output', '',
2035 2060 _('print output to file with formatted name'), _('FORMAT')),
2036 2061 ('', 'switch-parent', None, _('diff against the second parent')),
2037 2062 ('r', 'rev', [], _('revisions to export'), _('REV')),
2038 2063 ] + diffopts + formatteropts,
2039 2064 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2040 2065 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2041 2066 helpbasic=True, intents={INTENT_READONLY})
2042 2067 def export(ui, repo, *changesets, **opts):
2043 2068 """dump the header and diffs for one or more changesets
2044 2069
2045 2070 Print the changeset header and diffs for one or more revisions.
2046 2071 If no revision is given, the parent of the working directory is used.
2047 2072
2048 2073 The information shown in the changeset header is: author, date,
2049 2074 branch name (if non-default), changeset hash, parent(s) and commit
2050 2075 comment.
2051 2076
2052 2077 .. note::
2053 2078
2054 2079 :hg:`export` may generate unexpected diff output for merge
2055 2080 changesets, as it will compare the merge changeset against its
2056 2081 first parent only.
2057 2082
2058 2083 Output may be to a file, in which case the name of the file is
2059 2084 given using a template string. See :hg:`help templates`. In addition
2060 2085 to the common template keywords, the following formatting rules are
2061 2086 supported:
2062 2087
2063 2088 :``%%``: literal "%" character
2064 2089 :``%H``: changeset hash (40 hexadecimal digits)
2065 2090 :``%N``: number of patches being generated
2066 2091 :``%R``: changeset revision number
2067 2092 :``%b``: basename of the exporting repository
2068 2093 :``%h``: short-form changeset hash (12 hexadecimal digits)
2069 2094 :``%m``: first line of the commit message (only alphanumeric characters)
2070 2095 :``%n``: zero-padded sequence number, starting at 1
2071 2096 :``%r``: zero-padded changeset revision number
2072 2097 :``\\``: literal "\\" character
2073 2098
2074 2099 Without the -a/--text option, export will avoid generating diffs
2075 2100 of files it detects as binary. With -a, export will generate a
2076 2101 diff anyway, probably with undesirable results.
2077 2102
2078 2103 With -B/--bookmark changesets reachable by the given bookmark are
2079 2104 selected.
2080 2105
2081 2106 Use the -g/--git option to generate diffs in the git extended diff
2082 2107 format. See :hg:`help diffs` for more information.
2083 2108
2084 2109 With the --switch-parent option, the diff will be against the
2085 2110 second parent. It can be useful to review a merge.
2086 2111
2087 2112 .. container:: verbose
2088 2113
2089 2114 Template:
2090 2115
2091 2116 The following keywords are supported in addition to the common template
2092 2117 keywords and functions. See also :hg:`help templates`.
2093 2118
2094 2119 :diff: String. Diff content.
2095 2120 :parents: List of strings. Parent nodes of the changeset.
2096 2121
2097 2122 Examples:
2098 2123
2099 2124 - use export and import to transplant a bugfix to the current
2100 2125 branch::
2101 2126
2102 2127 hg export -r 9353 | hg import -
2103 2128
2104 2129 - export all the changesets between two revisions to a file with
2105 2130 rename information::
2106 2131
2107 2132 hg export --git -r 123:150 > changes.txt
2108 2133
2109 2134 - split outgoing changes into a series of patches with
2110 2135 descriptive names::
2111 2136
2112 2137 hg export -r "outgoing()" -o "%n-%m.patch"
2113 2138
2114 2139 Returns 0 on success.
2115 2140 """
2116 2141 opts = pycompat.byteskwargs(opts)
2117 2142 bookmark = opts.get('bookmark')
2118 2143 changesets += tuple(opts.get('rev', []))
2119 2144
2120 2145 if bookmark and changesets:
2121 2146 raise error.Abort(_("-r and -B are mutually exclusive"))
2122 2147
2123 2148 if bookmark:
2124 2149 if bookmark not in repo._bookmarks:
2125 2150 raise error.Abort(_("bookmark '%s' not found") % bookmark)
2126 2151
2127 2152 revs = scmutil.bookmarkrevs(repo, bookmark)
2128 2153 else:
2129 2154 if not changesets:
2130 2155 changesets = ['.']
2131 2156
2132 2157 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
2133 2158 revs = scmutil.revrange(repo, changesets)
2134 2159
2135 2160 if not revs:
2136 2161 raise error.Abort(_("export requires at least one changeset"))
2137 2162 if len(revs) > 1:
2138 2163 ui.note(_('exporting patches:\n'))
2139 2164 else:
2140 2165 ui.note(_('exporting patch:\n'))
2141 2166
2142 2167 fntemplate = opts.get('output')
2143 2168 if cmdutil.isstdiofilename(fntemplate):
2144 2169 fntemplate = ''
2145 2170
2146 2171 if fntemplate:
2147 2172 fm = formatter.nullformatter(ui, 'export', opts)
2148 2173 else:
2149 2174 ui.pager('export')
2150 2175 fm = ui.formatter('export', opts)
2151 2176 with fm:
2152 2177 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2153 2178 switch_parent=opts.get('switch_parent'),
2154 2179 opts=patch.diffallopts(ui, opts))
2155 2180
2156 2181 @command('files',
2157 2182 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2158 2183 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2159 2184 ] + walkopts + formatteropts + subrepoopts,
2160 2185 _('[OPTION]... [FILE]...'),
2161 2186 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2162 2187 intents={INTENT_READONLY})
2163 2188 def files(ui, repo, *pats, **opts):
2164 2189 """list tracked files
2165 2190
2166 2191 Print files under Mercurial control in the working directory or
2167 2192 specified revision for given files (excluding removed files).
2168 2193 Files can be specified as filenames or filesets.
2169 2194
2170 2195 If no files are given to match, this command prints the names
2171 2196 of all files under Mercurial control.
2172 2197
2173 2198 .. container:: verbose
2174 2199
2175 2200 Template:
2176 2201
2177 2202 The following keywords are supported in addition to the common template
2178 2203 keywords and functions. See also :hg:`help templates`.
2179 2204
2180 2205 :flags: String. Character denoting file's symlink and executable bits.
2181 2206 :path: String. Repository-absolute path of the file.
2182 2207 :size: Integer. Size of the file in bytes.
2183 2208
2184 2209 Examples:
2185 2210
2186 2211 - list all files under the current directory::
2187 2212
2188 2213 hg files .
2189 2214
2190 2215 - shows sizes and flags for current revision::
2191 2216
2192 2217 hg files -vr .
2193 2218
2194 2219 - list all files named README::
2195 2220
2196 2221 hg files -I "**/README"
2197 2222
2198 2223 - list all binary files::
2199 2224
2200 2225 hg files "set:binary()"
2201 2226
2202 2227 - find files containing a regular expression::
2203 2228
2204 2229 hg files "set:grep('bob')"
2205 2230
2206 2231 - search tracked file contents with xargs and grep::
2207 2232
2208 2233 hg files -0 | xargs -0 grep foo
2209 2234
2210 2235 See :hg:`help patterns` and :hg:`help filesets` for more information
2211 2236 on specifying file patterns.
2212 2237
2213 2238 Returns 0 if a match is found, 1 otherwise.
2214 2239
2215 2240 """
2216 2241
2217 2242 opts = pycompat.byteskwargs(opts)
2218 2243 rev = opts.get('rev')
2219 2244 if rev:
2220 2245 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2221 2246 ctx = scmutil.revsingle(repo, rev, None)
2222 2247
2223 2248 end = '\n'
2224 2249 if opts.get('print0'):
2225 2250 end = '\0'
2226 2251 fmt = '%s' + end
2227 2252
2228 2253 m = scmutil.match(ctx, pats, opts)
2229 2254 ui.pager('files')
2230 2255 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2231 2256 with ui.formatter('files', opts) as fm:
2232 2257 return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt,
2233 2258 opts.get('subrepos'))
2234 2259
2235 2260 @command(
2236 2261 'forget',
2237 2262 [('i', 'interactive', None, _('use interactive mode')),
2238 2263 ] + walkopts + dryrunopts,
2239 2264 _('[OPTION]... FILE...'),
2240 2265 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2241 2266 helpbasic=True, inferrepo=True)
2242 2267 def forget(ui, repo, *pats, **opts):
2243 2268 """forget the specified files on the next commit
2244 2269
2245 2270 Mark the specified files so they will no longer be tracked
2246 2271 after the next commit.
2247 2272
2248 2273 This only removes files from the current branch, not from the
2249 2274 entire project history, and it does not delete them from the
2250 2275 working directory.
2251 2276
2252 2277 To delete the file from the working directory, see :hg:`remove`.
2253 2278
2254 2279 To undo a forget before the next commit, see :hg:`add`.
2255 2280
2256 2281 .. container:: verbose
2257 2282
2258 2283 Examples:
2259 2284
2260 2285 - forget newly-added binary files::
2261 2286
2262 2287 hg forget "set:added() and binary()"
2263 2288
2264 2289 - forget files that would be excluded by .hgignore::
2265 2290
2266 2291 hg forget "set:hgignore()"
2267 2292
2268 2293 Returns 0 on success.
2269 2294 """
2270 2295
2271 2296 opts = pycompat.byteskwargs(opts)
2272 2297 if not pats:
2273 2298 raise error.Abort(_('no files specified'))
2274 2299
2275 2300 m = scmutil.match(repo[None], pats, opts)
2276 2301 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2277 2302 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2278 2303 rejected = cmdutil.forget(ui, repo, m, prefix="", uipathfn=uipathfn,
2279 2304 explicitonly=False, dryrun=dryrun,
2280 2305 interactive=interactive)[0]
2281 2306 return rejected and 1 or 0
2282 2307
2283 2308 @command(
2284 2309 'graft',
2285 2310 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2286 2311 ('', 'base', '',
2287 2312 _('base revision when doing the graft merge (ADVANCED)'), _('REV')),
2288 2313 ('c', 'continue', False, _('resume interrupted graft')),
2289 2314 ('', 'stop', False, _('stop interrupted graft')),
2290 2315 ('', 'abort', False, _('abort interrupted graft')),
2291 2316 ('e', 'edit', False, _('invoke editor on commit messages')),
2292 2317 ('', 'log', None, _('append graft info to log message')),
2293 2318 ('', 'no-commit', None,
2294 2319 _("don't commit, just apply the changes in working directory")),
2295 2320 ('f', 'force', False, _('force graft')),
2296 2321 ('D', 'currentdate', False,
2297 2322 _('record the current date as commit date')),
2298 2323 ('U', 'currentuser', False,
2299 2324 _('record the current user as committer'))]
2300 2325 + commitopts2 + mergetoolopts + dryrunopts,
2301 2326 _('[OPTION]... [-r REV]... REV...'),
2302 2327 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
2303 2328 def graft(ui, repo, *revs, **opts):
2304 2329 '''copy changes from other branches onto the current branch
2305 2330
2306 2331 This command uses Mercurial's merge logic to copy individual
2307 2332 changes from other branches without merging branches in the
2308 2333 history graph. This is sometimes known as 'backporting' or
2309 2334 'cherry-picking'. By default, graft will copy user, date, and
2310 2335 description from the source changesets.
2311 2336
2312 2337 Changesets that are ancestors of the current revision, that have
2313 2338 already been grafted, or that are merges will be skipped.
2314 2339
2315 2340 If --log is specified, log messages will have a comment appended
2316 2341 of the form::
2317 2342
2318 2343 (grafted from CHANGESETHASH)
2319 2344
2320 2345 If --force is specified, revisions will be grafted even if they
2321 2346 are already ancestors of, or have been grafted to, the destination.
2322 2347 This is useful when the revisions have since been backed out.
2323 2348
2324 2349 If a graft merge results in conflicts, the graft process is
2325 2350 interrupted so that the current merge can be manually resolved.
2326 2351 Once all conflicts are addressed, the graft process can be
2327 2352 continued with the -c/--continue option.
2328 2353
2329 2354 The -c/--continue option reapplies all the earlier options.
2330 2355
2331 2356 .. container:: verbose
2332 2357
2333 2358 The --base option exposes more of how graft internally uses merge with a
2334 2359 custom base revision. --base can be used to specify another ancestor than
2335 2360 the first and only parent.
2336 2361
2337 2362 The command::
2338 2363
2339 2364 hg graft -r 345 --base 234
2340 2365
2341 2366 is thus pretty much the same as::
2342 2367
2343 2368 hg diff -r 234 -r 345 | hg import
2344 2369
2345 2370 but using merge to resolve conflicts and track moved files.
2346 2371
2347 2372 The result of a merge can thus be backported as a single commit by
2348 2373 specifying one of the merge parents as base, and thus effectively
2349 2374 grafting the changes from the other side.
2350 2375
2351 2376 It is also possible to collapse multiple changesets and clean up history
2352 2377 by specifying another ancestor as base, much like rebase --collapse
2353 2378 --keep.
2354 2379
2355 2380 The commit message can be tweaked after the fact using commit --amend .
2356 2381
2357 2382 For using non-ancestors as the base to backout changes, see the backout
2358 2383 command and the hidden --parent option.
2359 2384
2360 2385 .. container:: verbose
2361 2386
2362 2387 Examples:
2363 2388
2364 2389 - copy a single change to the stable branch and edit its description::
2365 2390
2366 2391 hg update stable
2367 2392 hg graft --edit 9393
2368 2393
2369 2394 - graft a range of changesets with one exception, updating dates::
2370 2395
2371 2396 hg graft -D "2085::2093 and not 2091"
2372 2397
2373 2398 - continue a graft after resolving conflicts::
2374 2399
2375 2400 hg graft -c
2376 2401
2377 2402 - show the source of a grafted changeset::
2378 2403
2379 2404 hg log --debug -r .
2380 2405
2381 2406 - show revisions sorted by date::
2382 2407
2383 2408 hg log -r "sort(all(), date)"
2384 2409
2385 2410 - backport the result of a merge as a single commit::
2386 2411
2387 2412 hg graft -r 123 --base 123^
2388 2413
2389 2414 - land a feature branch as one changeset::
2390 2415
2391 2416 hg up -cr default
2392 2417 hg graft -r featureX --base "ancestor('featureX', 'default')"
2393 2418
2394 2419 See :hg:`help revisions` for more about specifying revisions.
2395 2420
2396 2421 Returns 0 on successful completion.
2397 2422 '''
2398 2423 with repo.wlock():
2399 2424 return _dograft(ui, repo, *revs, **opts)
2400 2425
2401 2426 def _dograft(ui, repo, *revs, **opts):
2402 2427 opts = pycompat.byteskwargs(opts)
2403 2428 if revs and opts.get('rev'):
2404 2429 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2405 2430 'revision ordering!\n'))
2406 2431
2407 2432 revs = list(revs)
2408 2433 revs.extend(opts.get('rev'))
2409 2434 basectx = None
2410 2435 if opts.get('base'):
2411 2436 basectx = scmutil.revsingle(repo, opts['base'], None)
2412 2437 # a dict of data to be stored in state file
2413 2438 statedata = {}
2414 2439 # list of new nodes created by ongoing graft
2415 2440 statedata['newnodes'] = []
2416 2441
2417 2442 if opts.get('user') and opts.get('currentuser'):
2418 2443 raise error.Abort(_('--user and --currentuser are mutually exclusive'))
2419 2444 if opts.get('date') and opts.get('currentdate'):
2420 2445 raise error.Abort(_('--date and --currentdate are mutually exclusive'))
2421 2446 if not opts.get('user') and opts.get('currentuser'):
2422 2447 opts['user'] = ui.username()
2423 2448 if not opts.get('date') and opts.get('currentdate'):
2424 2449 opts['date'] = "%d %d" % dateutil.makedate()
2425 2450
2426 2451 editor = cmdutil.getcommiteditor(editform='graft',
2427 2452 **pycompat.strkwargs(opts))
2428 2453
2429 2454 cont = False
2430 2455 if opts.get('no_commit'):
2431 2456 if opts.get('edit'):
2432 2457 raise error.Abort(_("cannot specify --no-commit and "
2433 2458 "--edit together"))
2434 2459 if opts.get('currentuser'):
2435 2460 raise error.Abort(_("cannot specify --no-commit and "
2436 2461 "--currentuser together"))
2437 2462 if opts.get('currentdate'):
2438 2463 raise error.Abort(_("cannot specify --no-commit and "
2439 2464 "--currentdate together"))
2440 2465 if opts.get('log'):
2441 2466 raise error.Abort(_("cannot specify --no-commit and "
2442 2467 "--log together"))
2443 2468
2444 2469 graftstate = statemod.cmdstate(repo, 'graftstate')
2445 2470
2446 2471 if opts.get('stop'):
2447 2472 if opts.get('continue'):
2448 2473 raise error.Abort(_("cannot use '--continue' and "
2449 2474 "'--stop' together"))
2450 2475 if opts.get('abort'):
2451 2476 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2452 2477
2453 2478 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2454 2479 opts.get('date'), opts.get('currentdate'),
2455 2480 opts.get('currentuser'), opts.get('rev'))):
2456 2481 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2457 2482 return _stopgraft(ui, repo, graftstate)
2458 2483 elif opts.get('abort'):
2459 2484 if opts.get('continue'):
2460 2485 raise error.Abort(_("cannot use '--continue' and "
2461 2486 "'--abort' together"))
2462 2487 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2463 2488 opts.get('date'), opts.get('currentdate'),
2464 2489 opts.get('currentuser'), opts.get('rev'))):
2465 2490 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2466 2491
2467 2492 return cmdutil.abortgraft(ui, repo, graftstate)
2468 2493 elif opts.get('continue'):
2469 2494 cont = True
2470 2495 if revs:
2471 2496 raise error.Abort(_("can't specify --continue and revisions"))
2472 2497 # read in unfinished revisions
2473 2498 if graftstate.exists():
2474 2499 statedata = cmdutil.readgraftstate(repo, graftstate)
2475 2500 if statedata.get('date'):
2476 2501 opts['date'] = statedata['date']
2477 2502 if statedata.get('user'):
2478 2503 opts['user'] = statedata['user']
2479 2504 if statedata.get('log'):
2480 2505 opts['log'] = True
2481 2506 if statedata.get('no_commit'):
2482 2507 opts['no_commit'] = statedata.get('no_commit')
2483 2508 nodes = statedata['nodes']
2484 2509 revs = [repo[node].rev() for node in nodes]
2485 2510 else:
2486 2511 cmdutil.wrongtooltocontinue(repo, _('graft'))
2487 2512 else:
2488 2513 if not revs:
2489 2514 raise error.Abort(_('no revisions specified'))
2490 2515 cmdutil.checkunfinished(repo)
2491 2516 cmdutil.bailifchanged(repo)
2492 2517 revs = scmutil.revrange(repo, revs)
2493 2518
2494 2519 skipped = set()
2495 2520 if basectx is None:
2496 2521 # check for merges
2497 2522 for rev in repo.revs('%ld and merge()', revs):
2498 2523 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2499 2524 skipped.add(rev)
2500 2525 revs = [r for r in revs if r not in skipped]
2501 2526 if not revs:
2502 2527 return -1
2503 2528 if basectx is not None and len(revs) != 1:
2504 2529 raise error.Abort(_('only one revision allowed with --base '))
2505 2530
2506 2531 # Don't check in the --continue case, in effect retaining --force across
2507 2532 # --continues. That's because without --force, any revisions we decided to
2508 2533 # skip would have been filtered out here, so they wouldn't have made their
2509 2534 # way to the graftstate. With --force, any revisions we would have otherwise
2510 2535 # skipped would not have been filtered out, and if they hadn't been applied
2511 2536 # already, they'd have been in the graftstate.
2512 2537 if not (cont or opts.get('force')) and basectx is None:
2513 2538 # check for ancestors of dest branch
2514 2539 crev = repo['.'].rev()
2515 2540 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2516 2541 # XXX make this lazy in the future
2517 2542 # don't mutate while iterating, create a copy
2518 2543 for rev in list(revs):
2519 2544 if rev in ancestors:
2520 2545 ui.warn(_('skipping ancestor revision %d:%s\n') %
2521 2546 (rev, repo[rev]))
2522 2547 # XXX remove on list is slow
2523 2548 revs.remove(rev)
2524 2549 if not revs:
2525 2550 return -1
2526 2551
2527 2552 # analyze revs for earlier grafts
2528 2553 ids = {}
2529 2554 for ctx in repo.set("%ld", revs):
2530 2555 ids[ctx.hex()] = ctx.rev()
2531 2556 n = ctx.extra().get('source')
2532 2557 if n:
2533 2558 ids[n] = ctx.rev()
2534 2559
2535 2560 # check ancestors for earlier grafts
2536 2561 ui.debug('scanning for duplicate grafts\n')
2537 2562
2538 2563 # The only changesets we can be sure doesn't contain grafts of any
2539 2564 # revs, are the ones that are common ancestors of *all* revs:
2540 2565 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2541 2566 ctx = repo[rev]
2542 2567 n = ctx.extra().get('source')
2543 2568 if n in ids:
2544 2569 try:
2545 2570 r = repo[n].rev()
2546 2571 except error.RepoLookupError:
2547 2572 r = None
2548 2573 if r in revs:
2549 2574 ui.warn(_('skipping revision %d:%s '
2550 2575 '(already grafted to %d:%s)\n')
2551 2576 % (r, repo[r], rev, ctx))
2552 2577 revs.remove(r)
2553 2578 elif ids[n] in revs:
2554 2579 if r is None:
2555 2580 ui.warn(_('skipping already grafted revision %d:%s '
2556 2581 '(%d:%s also has unknown origin %s)\n')
2557 2582 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2558 2583 else:
2559 2584 ui.warn(_('skipping already grafted revision %d:%s '
2560 2585 '(%d:%s also has origin %d:%s)\n')
2561 2586 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2562 2587 revs.remove(ids[n])
2563 2588 elif ctx.hex() in ids:
2564 2589 r = ids[ctx.hex()]
2565 2590 if r in revs:
2566 2591 ui.warn(_('skipping already grafted revision %d:%s '
2567 2592 '(was grafted from %d:%s)\n') %
2568 2593 (r, repo[r], rev, ctx))
2569 2594 revs.remove(r)
2570 2595 if not revs:
2571 2596 return -1
2572 2597
2573 2598 if opts.get('no_commit'):
2574 2599 statedata['no_commit'] = True
2575 2600 for pos, ctx in enumerate(repo.set("%ld", revs)):
2576 2601 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2577 2602 ctx.description().split('\n', 1)[0])
2578 2603 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2579 2604 if names:
2580 2605 desc += ' (%s)' % ' '.join(names)
2581 2606 ui.status(_('grafting %s\n') % desc)
2582 2607 if opts.get('dry_run'):
2583 2608 continue
2584 2609
2585 2610 source = ctx.extra().get('source')
2586 2611 extra = {}
2587 2612 if source:
2588 2613 extra['source'] = source
2589 2614 extra['intermediate-source'] = ctx.hex()
2590 2615 else:
2591 2616 extra['source'] = ctx.hex()
2592 2617 user = ctx.user()
2593 2618 if opts.get('user'):
2594 2619 user = opts['user']
2595 2620 statedata['user'] = user
2596 2621 date = ctx.date()
2597 2622 if opts.get('date'):
2598 2623 date = opts['date']
2599 2624 statedata['date'] = date
2600 2625 message = ctx.description()
2601 2626 if opts.get('log'):
2602 2627 message += '\n(grafted from %s)' % ctx.hex()
2603 2628 statedata['log'] = True
2604 2629
2605 2630 # we don't merge the first commit when continuing
2606 2631 if not cont:
2607 2632 # perform the graft merge with p1(rev) as 'ancestor'
2608 2633 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2609 2634 base = ctx.p1() if basectx is None else basectx
2610 2635 with ui.configoverride(overrides, 'graft'):
2611 2636 stats = mergemod.graft(repo, ctx, base, ['local', 'graft'])
2612 2637 # report any conflicts
2613 2638 if stats.unresolvedcount > 0:
2614 2639 # write out state for --continue
2615 2640 nodes = [repo[rev].hex() for rev in revs[pos:]]
2616 2641 statedata['nodes'] = nodes
2617 2642 stateversion = 1
2618 2643 graftstate.save(stateversion, statedata)
2619 2644 hint = _("use 'hg resolve' and 'hg graft --continue'")
2620 2645 raise error.Abort(
2621 2646 _("unresolved conflicts, can't continue"),
2622 2647 hint=hint)
2623 2648 else:
2624 2649 cont = False
2625 2650
2626 2651 # commit if --no-commit is false
2627 2652 if not opts.get('no_commit'):
2628 2653 node = repo.commit(text=message, user=user, date=date, extra=extra,
2629 2654 editor=editor)
2630 2655 if node is None:
2631 2656 ui.warn(
2632 2657 _('note: graft of %d:%s created no changes to commit\n') %
2633 2658 (ctx.rev(), ctx))
2634 2659 # checking that newnodes exist because old state files won't have it
2635 2660 elif statedata.get('newnodes') is not None:
2636 2661 statedata['newnodes'].append(node)
2637 2662
2638 2663 # remove state when we complete successfully
2639 2664 if not opts.get('dry_run'):
2640 2665 graftstate.delete()
2641 2666
2642 2667 return 0
2643 2668
2644 2669 def _stopgraft(ui, repo, graftstate):
2645 2670 """stop the interrupted graft"""
2646 2671 if not graftstate.exists():
2647 2672 raise error.Abort(_("no interrupted graft found"))
2648 2673 pctx = repo['.']
2649 2674 hg.updaterepo(repo, pctx.node(), overwrite=True)
2650 2675 graftstate.delete()
2651 2676 ui.status(_("stopped the interrupted graft\n"))
2652 2677 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2653 2678 return 0
2654 2679
2655 2680 @command('grep',
2656 2681 [('0', 'print0', None, _('end fields with NUL')),
2657 2682 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2658 2683 ('', 'diff', None, _('print all revisions when the term was introduced '
2659 2684 'or removed')),
2660 2685 ('a', 'text', None, _('treat all files as text')),
2661 2686 ('f', 'follow', None,
2662 2687 _('follow changeset history,'
2663 2688 ' or file history across copies and renames')),
2664 2689 ('i', 'ignore-case', None, _('ignore case when matching')),
2665 2690 ('l', 'files-with-matches', None,
2666 2691 _('print only filenames and revisions that match')),
2667 2692 ('n', 'line-number', None, _('print matching line numbers')),
2668 2693 ('r', 'rev', [],
2669 2694 _('only search files changed within revision range'), _('REV')),
2670 2695 ('', 'all-files', None,
2671 2696 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2672 2697 ('u', 'user', None, _('list the author (long with -v)')),
2673 2698 ('d', 'date', None, _('list the date (short with -q)')),
2674 2699 ] + formatteropts + walkopts,
2675 2700 _('[OPTION]... PATTERN [FILE]...'),
2676 2701 helpcategory=command.CATEGORY_FILE_CONTENTS,
2677 2702 inferrepo=True,
2678 2703 intents={INTENT_READONLY})
2679 2704 def grep(ui, repo, pattern, *pats, **opts):
2680 2705 """search revision history for a pattern in specified files
2681 2706
2682 2707 Search revision history for a regular expression in the specified
2683 2708 files or the entire project.
2684 2709
2685 2710 By default, grep prints the most recent revision number for each
2686 2711 file in which it finds a match. To get it to print every revision
2687 2712 that contains a change in match status ("-" for a match that becomes
2688 2713 a non-match, or "+" for a non-match that becomes a match), use the
2689 2714 --diff flag.
2690 2715
2691 2716 PATTERN can be any Python (roughly Perl-compatible) regular
2692 2717 expression.
2693 2718
2694 2719 If no FILEs are specified (and -f/--follow isn't set), all files in
2695 2720 the repository are searched, including those that don't exist in the
2696 2721 current branch or have been deleted in a prior changeset.
2697 2722
2698 2723 .. container:: verbose
2699 2724
2700 2725 Template:
2701 2726
2702 2727 The following keywords are supported in addition to the common template
2703 2728 keywords and functions. See also :hg:`help templates`.
2704 2729
2705 2730 :change: String. Character denoting insertion ``+`` or removal ``-``.
2706 2731 Available if ``--diff`` is specified.
2707 2732 :lineno: Integer. Line number of the match.
2708 2733 :path: String. Repository-absolute path of the file.
2709 2734 :texts: List of text chunks.
2710 2735
2711 2736 And each entry of ``{texts}`` provides the following sub-keywords.
2712 2737
2713 2738 :matched: Boolean. True if the chunk matches the specified pattern.
2714 2739 :text: String. Chunk content.
2715 2740
2716 2741 See :hg:`help templates.operators` for the list expansion syntax.
2717 2742
2718 2743 Returns 0 if a match is found, 1 otherwise.
2719 2744 """
2720 2745 opts = pycompat.byteskwargs(opts)
2721 2746 diff = opts.get('all') or opts.get('diff')
2722 2747 all_files = opts.get('all_files')
2723 2748 if diff and opts.get('all_files'):
2724 2749 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2725 2750 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2726 2751 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2727 2752 # experimental config: commands.grep.all-files
2728 2753 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2729 2754 plaingrep = opts.get('all_files') and not opts.get('rev')
2730 2755 if plaingrep:
2731 2756 opts['rev'] = ['wdir()']
2732 2757
2733 2758 reflags = re.M
2734 2759 if opts.get('ignore_case'):
2735 2760 reflags |= re.I
2736 2761 try:
2737 2762 regexp = util.re.compile(pattern, reflags)
2738 2763 except re.error as inst:
2739 2764 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2740 2765 return 1
2741 2766 sep, eol = ':', '\n'
2742 2767 if opts.get('print0'):
2743 2768 sep = eol = '\0'
2744 2769
2745 2770 getfile = util.lrucachefunc(repo.file)
2746 2771
2747 2772 def matchlines(body):
2748 2773 begin = 0
2749 2774 linenum = 0
2750 2775 while begin < len(body):
2751 2776 match = regexp.search(body, begin)
2752 2777 if not match:
2753 2778 break
2754 2779 mstart, mend = match.span()
2755 2780 linenum += body.count('\n', begin, mstart) + 1
2756 2781 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2757 2782 begin = body.find('\n', mend) + 1 or len(body) + 1
2758 2783 lend = begin - 1
2759 2784 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2760 2785
2761 2786 class linestate(object):
2762 2787 def __init__(self, line, linenum, colstart, colend):
2763 2788 self.line = line
2764 2789 self.linenum = linenum
2765 2790 self.colstart = colstart
2766 2791 self.colend = colend
2767 2792
2768 2793 def __hash__(self):
2769 2794 return hash((self.linenum, self.line))
2770 2795
2771 2796 def __eq__(self, other):
2772 2797 return self.line == other.line
2773 2798
2774 2799 def findpos(self):
2775 2800 """Iterate all (start, end) indices of matches"""
2776 2801 yield self.colstart, self.colend
2777 2802 p = self.colend
2778 2803 while p < len(self.line):
2779 2804 m = regexp.search(self.line, p)
2780 2805 if not m:
2781 2806 break
2782 2807 yield m.span()
2783 2808 p = m.end()
2784 2809
2785 2810 matches = {}
2786 2811 copies = {}
2787 2812 def grepbody(fn, rev, body):
2788 2813 matches[rev].setdefault(fn, [])
2789 2814 m = matches[rev][fn]
2790 2815 for lnum, cstart, cend, line in matchlines(body):
2791 2816 s = linestate(line, lnum, cstart, cend)
2792 2817 m.append(s)
2793 2818
2794 2819 def difflinestates(a, b):
2795 2820 sm = difflib.SequenceMatcher(None, a, b)
2796 2821 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2797 2822 if tag == r'insert':
2798 2823 for i in pycompat.xrange(blo, bhi):
2799 2824 yield ('+', b[i])
2800 2825 elif tag == r'delete':
2801 2826 for i in pycompat.xrange(alo, ahi):
2802 2827 yield ('-', a[i])
2803 2828 elif tag == r'replace':
2804 2829 for i in pycompat.xrange(alo, ahi):
2805 2830 yield ('-', a[i])
2806 2831 for i in pycompat.xrange(blo, bhi):
2807 2832 yield ('+', b[i])
2808 2833
2809 2834 uipathfn = scmutil.getuipathfn(repo)
2810 2835 def display(fm, fn, ctx, pstates, states):
2811 2836 rev = scmutil.intrev(ctx)
2812 2837 if fm.isplain():
2813 2838 formatuser = ui.shortuser
2814 2839 else:
2815 2840 formatuser = pycompat.bytestr
2816 2841 if ui.quiet:
2817 2842 datefmt = '%Y-%m-%d'
2818 2843 else:
2819 2844 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2820 2845 found = False
2821 2846 @util.cachefunc
2822 2847 def binary():
2823 2848 flog = getfile(fn)
2824 2849 try:
2825 2850 return stringutil.binary(flog.read(ctx.filenode(fn)))
2826 2851 except error.WdirUnsupported:
2827 2852 return ctx[fn].isbinary()
2828 2853
2829 2854 fieldnamemap = {'linenumber': 'lineno'}
2830 2855 if diff:
2831 2856 iter = difflinestates(pstates, states)
2832 2857 else:
2833 2858 iter = [('', l) for l in states]
2834 2859 for change, l in iter:
2835 2860 fm.startitem()
2836 2861 fm.context(ctx=ctx)
2837 2862 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
2838 2863 fm.plain(uipathfn(fn), label='grep.filename')
2839 2864
2840 2865 cols = [
2841 2866 ('rev', '%d', rev, not plaingrep, ''),
2842 2867 ('linenumber', '%d', l.linenum, opts.get('line_number'), ''),
2843 2868 ]
2844 2869 if diff:
2845 2870 cols.append(
2846 2871 ('change', '%s', change, True,
2847 2872 'grep.inserted ' if change == '+' else 'grep.deleted ')
2848 2873 )
2849 2874 cols.extend([
2850 2875 ('user', '%s', formatuser(ctx.user()), opts.get('user'), ''),
2851 2876 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2852 2877 opts.get('date'), ''),
2853 2878 ])
2854 2879 for name, fmt, data, cond, extra_label in cols:
2855 2880 if cond:
2856 2881 fm.plain(sep, label='grep.sep')
2857 2882 field = fieldnamemap.get(name, name)
2858 2883 label = extra_label + ('grep.%s' % name)
2859 2884 fm.condwrite(cond, field, fmt, data, label=label)
2860 2885 if not opts.get('files_with_matches'):
2861 2886 fm.plain(sep, label='grep.sep')
2862 2887 if not opts.get('text') and binary():
2863 2888 fm.plain(_(" Binary file matches"))
2864 2889 else:
2865 2890 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2866 2891 fm.plain(eol)
2867 2892 found = True
2868 2893 if opts.get('files_with_matches'):
2869 2894 break
2870 2895 return found
2871 2896
2872 2897 def displaymatches(fm, l):
2873 2898 p = 0
2874 2899 for s, e in l.findpos():
2875 2900 if p < s:
2876 2901 fm.startitem()
2877 2902 fm.write('text', '%s', l.line[p:s])
2878 2903 fm.data(matched=False)
2879 2904 fm.startitem()
2880 2905 fm.write('text', '%s', l.line[s:e], label='grep.match')
2881 2906 fm.data(matched=True)
2882 2907 p = e
2883 2908 if p < len(l.line):
2884 2909 fm.startitem()
2885 2910 fm.write('text', '%s', l.line[p:])
2886 2911 fm.data(matched=False)
2887 2912 fm.end()
2888 2913
2889 2914 skip = set()
2890 2915 revfiles = {}
2891 2916 match = scmutil.match(repo[None], pats, opts)
2892 2917 found = False
2893 2918 follow = opts.get('follow')
2894 2919
2895 2920 getrenamed = scmutil.getrenamedfn(repo)
2896 2921 def prep(ctx, fns):
2897 2922 rev = ctx.rev()
2898 2923 pctx = ctx.p1()
2899 2924 parent = pctx.rev()
2900 2925 matches.setdefault(rev, {})
2901 2926 matches.setdefault(parent, {})
2902 2927 files = revfiles.setdefault(rev, [])
2903 2928 for fn in fns:
2904 2929 flog = getfile(fn)
2905 2930 try:
2906 2931 fnode = ctx.filenode(fn)
2907 2932 except error.LookupError:
2908 2933 continue
2909 2934
2910 2935 copy = None
2911 2936 if follow:
2912 2937 copy = getrenamed(fn, rev)
2913 2938 if copy:
2914 2939 copies.setdefault(rev, {})[fn] = copy
2915 2940 if fn in skip:
2916 2941 skip.add(copy)
2917 2942 if fn in skip:
2918 2943 continue
2919 2944 files.append(fn)
2920 2945
2921 2946 if fn not in matches[rev]:
2922 2947 try:
2923 2948 content = flog.read(fnode)
2924 2949 except error.WdirUnsupported:
2925 2950 content = ctx[fn].data()
2926 2951 grepbody(fn, rev, content)
2927 2952
2928 2953 pfn = copy or fn
2929 2954 if pfn not in matches[parent]:
2930 2955 try:
2931 2956 fnode = pctx.filenode(pfn)
2932 2957 grepbody(pfn, parent, flog.read(fnode))
2933 2958 except error.LookupError:
2934 2959 pass
2935 2960
2936 2961 ui.pager('grep')
2937 2962 fm = ui.formatter('grep', opts)
2938 2963 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2939 2964 rev = ctx.rev()
2940 2965 parent = ctx.p1().rev()
2941 2966 for fn in sorted(revfiles.get(rev, [])):
2942 2967 states = matches[rev][fn]
2943 2968 copy = copies.get(rev, {}).get(fn)
2944 2969 if fn in skip:
2945 2970 if copy:
2946 2971 skip.add(copy)
2947 2972 continue
2948 2973 pstates = matches.get(parent, {}).get(copy or fn, [])
2949 2974 if pstates or states:
2950 2975 r = display(fm, fn, ctx, pstates, states)
2951 2976 found = found or r
2952 2977 if r and not diff and not all_files:
2953 2978 skip.add(fn)
2954 2979 if copy:
2955 2980 skip.add(copy)
2956 2981 del revfiles[rev]
2957 2982 # We will keep the matches dict for the duration of the window
2958 2983 # clear the matches dict once the window is over
2959 2984 if not revfiles:
2960 2985 matches.clear()
2961 2986 fm.end()
2962 2987
2963 2988 return not found
2964 2989
2965 2990 @command('heads',
2966 2991 [('r', 'rev', '',
2967 2992 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2968 2993 ('t', 'topo', False, _('show topological heads only')),
2969 2994 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2970 2995 ('c', 'closed', False, _('show normal and closed branch heads')),
2971 2996 ] + templateopts,
2972 2997 _('[-ct] [-r STARTREV] [REV]...'),
2973 2998 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
2974 2999 intents={INTENT_READONLY})
2975 3000 def heads(ui, repo, *branchrevs, **opts):
2976 3001 """show branch heads
2977 3002
2978 3003 With no arguments, show all open branch heads in the repository.
2979 3004 Branch heads are changesets that have no descendants on the
2980 3005 same branch. They are where development generally takes place and
2981 3006 are the usual targets for update and merge operations.
2982 3007
2983 3008 If one or more REVs are given, only open branch heads on the
2984 3009 branches associated with the specified changesets are shown. This
2985 3010 means that you can use :hg:`heads .` to see the heads on the
2986 3011 currently checked-out branch.
2987 3012
2988 3013 If -c/--closed is specified, also show branch heads marked closed
2989 3014 (see :hg:`commit --close-branch`).
2990 3015
2991 3016 If STARTREV is specified, only those heads that are descendants of
2992 3017 STARTREV will be displayed.
2993 3018
2994 3019 If -t/--topo is specified, named branch mechanics will be ignored and only
2995 3020 topological heads (changesets with no children) will be shown.
2996 3021
2997 3022 Returns 0 if matching heads are found, 1 if not.
2998 3023 """
2999 3024
3000 3025 opts = pycompat.byteskwargs(opts)
3001 3026 start = None
3002 3027 rev = opts.get('rev')
3003 3028 if rev:
3004 3029 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3005 3030 start = scmutil.revsingle(repo, rev, None).node()
3006 3031
3007 3032 if opts.get('topo'):
3008 3033 heads = [repo[h] for h in repo.heads(start)]
3009 3034 else:
3010 3035 heads = []
3011 3036 for branch in repo.branchmap():
3012 3037 heads += repo.branchheads(branch, start, opts.get('closed'))
3013 3038 heads = [repo[h] for h in heads]
3014 3039
3015 3040 if branchrevs:
3016 3041 branches = set(repo[r].branch()
3017 3042 for r in scmutil.revrange(repo, branchrevs))
3018 3043 heads = [h for h in heads if h.branch() in branches]
3019 3044
3020 3045 if opts.get('active') and branchrevs:
3021 3046 dagheads = repo.heads(start)
3022 3047 heads = [h for h in heads if h.node() in dagheads]
3023 3048
3024 3049 if branchrevs:
3025 3050 haveheads = set(h.branch() for h in heads)
3026 3051 if branches - haveheads:
3027 3052 headless = ', '.join(b for b in branches - haveheads)
3028 3053 msg = _('no open branch heads found on branches %s')
3029 3054 if opts.get('rev'):
3030 3055 msg += _(' (started at %s)') % opts['rev']
3031 3056 ui.warn((msg + '\n') % headless)
3032 3057
3033 3058 if not heads:
3034 3059 return 1
3035 3060
3036 3061 ui.pager('heads')
3037 3062 heads = sorted(heads, key=lambda x: -x.rev())
3038 3063 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3039 3064 for ctx in heads:
3040 3065 displayer.show(ctx)
3041 3066 displayer.close()
3042 3067
3043 3068 @command('help',
3044 3069 [('e', 'extension', None, _('show only help for extensions')),
3045 3070 ('c', 'command', None, _('show only help for commands')),
3046 3071 ('k', 'keyword', None, _('show topics matching keyword')),
3047 3072 ('s', 'system', [],
3048 3073 _('show help for specific platform(s)'), _('PLATFORM')),
3049 3074 ],
3050 3075 _('[-eck] [-s PLATFORM] [TOPIC]'),
3051 3076 helpcategory=command.CATEGORY_HELP,
3052 3077 norepo=True,
3053 3078 intents={INTENT_READONLY})
3054 3079 def help_(ui, name=None, **opts):
3055 3080 """show help for a given topic or a help overview
3056 3081
3057 3082 With no arguments, print a list of commands with short help messages.
3058 3083
3059 3084 Given a topic, extension, or command name, print help for that
3060 3085 topic.
3061 3086
3062 3087 Returns 0 if successful.
3063 3088 """
3064 3089
3065 3090 keep = opts.get(r'system') or []
3066 3091 if len(keep) == 0:
3067 3092 if pycompat.sysplatform.startswith('win'):
3068 3093 keep.append('windows')
3069 3094 elif pycompat.sysplatform == 'OpenVMS':
3070 3095 keep.append('vms')
3071 3096 elif pycompat.sysplatform == 'plan9':
3072 3097 keep.append('plan9')
3073 3098 else:
3074 3099 keep.append('unix')
3075 3100 keep.append(pycompat.sysplatform.lower())
3076 3101 if ui.verbose:
3077 3102 keep.append('verbose')
3078 3103
3079 3104 commands = sys.modules[__name__]
3080 3105 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3081 3106 ui.pager('help')
3082 3107 ui.write(formatted)
3083 3108
3084 3109
3085 3110 @command('identify|id',
3086 3111 [('r', 'rev', '',
3087 3112 _('identify the specified revision'), _('REV')),
3088 3113 ('n', 'num', None, _('show local revision number')),
3089 3114 ('i', 'id', None, _('show global revision id')),
3090 3115 ('b', 'branch', None, _('show branch')),
3091 3116 ('t', 'tags', None, _('show tags')),
3092 3117 ('B', 'bookmarks', None, _('show bookmarks')),
3093 3118 ] + remoteopts + formatteropts,
3094 3119 _('[-nibtB] [-r REV] [SOURCE]'),
3095 3120 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3096 3121 optionalrepo=True,
3097 3122 intents={INTENT_READONLY})
3098 3123 def identify(ui, repo, source=None, rev=None,
3099 3124 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3100 3125 """identify the working directory or specified revision
3101 3126
3102 3127 Print a summary identifying the repository state at REV using one or
3103 3128 two parent hash identifiers, followed by a "+" if the working
3104 3129 directory has uncommitted changes, the branch name (if not default),
3105 3130 a list of tags, and a list of bookmarks.
3106 3131
3107 3132 When REV is not given, print a summary of the current state of the
3108 3133 repository including the working directory. Specify -r. to get information
3109 3134 of the working directory parent without scanning uncommitted changes.
3110 3135
3111 3136 Specifying a path to a repository root or Mercurial bundle will
3112 3137 cause lookup to operate on that repository/bundle.
3113 3138
3114 3139 .. container:: verbose
3115 3140
3116 3141 Template:
3117 3142
3118 3143 The following keywords are supported in addition to the common template
3119 3144 keywords and functions. See also :hg:`help templates`.
3120 3145
3121 3146 :dirty: String. Character ``+`` denoting if the working directory has
3122 3147 uncommitted changes.
3123 3148 :id: String. One or two nodes, optionally followed by ``+``.
3124 3149 :parents: List of strings. Parent nodes of the changeset.
3125 3150
3126 3151 Examples:
3127 3152
3128 3153 - generate a build identifier for the working directory::
3129 3154
3130 3155 hg id --id > build-id.dat
3131 3156
3132 3157 - find the revision corresponding to a tag::
3133 3158
3134 3159 hg id -n -r 1.3
3135 3160
3136 3161 - check the most recent revision of a remote repository::
3137 3162
3138 3163 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3139 3164
3140 3165 See :hg:`log` for generating more information about specific revisions,
3141 3166 including full hash identifiers.
3142 3167
3143 3168 Returns 0 if successful.
3144 3169 """
3145 3170
3146 3171 opts = pycompat.byteskwargs(opts)
3147 3172 if not repo and not source:
3148 3173 raise error.Abort(_("there is no Mercurial repository here "
3149 3174 "(.hg not found)"))
3150 3175
3151 3176 default = not (num or id or branch or tags or bookmarks)
3152 3177 output = []
3153 3178 revs = []
3154 3179
3155 3180 if source:
3156 3181 source, branches = hg.parseurl(ui.expandpath(source))
3157 3182 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3158 3183 repo = peer.local()
3159 3184 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3160 3185
3161 3186 fm = ui.formatter('identify', opts)
3162 3187 fm.startitem()
3163 3188
3164 3189 if not repo:
3165 3190 if num or branch or tags:
3166 3191 raise error.Abort(
3167 3192 _("can't query remote revision number, branch, or tags"))
3168 3193 if not rev and revs:
3169 3194 rev = revs[0]
3170 3195 if not rev:
3171 3196 rev = "tip"
3172 3197
3173 3198 remoterev = peer.lookup(rev)
3174 3199 hexrev = fm.hexfunc(remoterev)
3175 3200 if default or id:
3176 3201 output = [hexrev]
3177 3202 fm.data(id=hexrev)
3178 3203
3179 3204 @util.cachefunc
3180 3205 def getbms():
3181 3206 bms = []
3182 3207
3183 3208 if 'bookmarks' in peer.listkeys('namespaces'):
3184 3209 hexremoterev = hex(remoterev)
3185 3210 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3186 3211 if bmr == hexremoterev]
3187 3212
3188 3213 return sorted(bms)
3189 3214
3190 3215 if fm.isplain():
3191 3216 if bookmarks:
3192 3217 output.extend(getbms())
3193 3218 elif default and not ui.quiet:
3194 3219 # multiple bookmarks for a single parent separated by '/'
3195 3220 bm = '/'.join(getbms())
3196 3221 if bm:
3197 3222 output.append(bm)
3198 3223 else:
3199 3224 fm.data(node=hex(remoterev))
3200 3225 if bookmarks or 'bookmarks' in fm.datahint():
3201 3226 fm.data(bookmarks=fm.formatlist(getbms(), name='bookmark'))
3202 3227 else:
3203 3228 if rev:
3204 3229 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3205 3230 ctx = scmutil.revsingle(repo, rev, None)
3206 3231
3207 3232 if ctx.rev() is None:
3208 3233 ctx = repo[None]
3209 3234 parents = ctx.parents()
3210 3235 taglist = []
3211 3236 for p in parents:
3212 3237 taglist.extend(p.tags())
3213 3238
3214 3239 dirty = ""
3215 3240 if ctx.dirty(missing=True, merge=False, branch=False):
3216 3241 dirty = '+'
3217 3242 fm.data(dirty=dirty)
3218 3243
3219 3244 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3220 3245 if default or id:
3221 3246 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3222 3247 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3223 3248
3224 3249 if num:
3225 3250 numoutput = ["%d" % p.rev() for p in parents]
3226 3251 output.append("%s%s" % ('+'.join(numoutput), dirty))
3227 3252
3228 3253 fm.data(parents=fm.formatlist([fm.hexfunc(p.node())
3229 3254 for p in parents], name='node'))
3230 3255 else:
3231 3256 hexoutput = fm.hexfunc(ctx.node())
3232 3257 if default or id:
3233 3258 output = [hexoutput]
3234 3259 fm.data(id=hexoutput)
3235 3260
3236 3261 if num:
3237 3262 output.append(pycompat.bytestr(ctx.rev()))
3238 3263 taglist = ctx.tags()
3239 3264
3240 3265 if default and not ui.quiet:
3241 3266 b = ctx.branch()
3242 3267 if b != 'default':
3243 3268 output.append("(%s)" % b)
3244 3269
3245 3270 # multiple tags for a single parent separated by '/'
3246 3271 t = '/'.join(taglist)
3247 3272 if t:
3248 3273 output.append(t)
3249 3274
3250 3275 # multiple bookmarks for a single parent separated by '/'
3251 3276 bm = '/'.join(ctx.bookmarks())
3252 3277 if bm:
3253 3278 output.append(bm)
3254 3279 else:
3255 3280 if branch:
3256 3281 output.append(ctx.branch())
3257 3282
3258 3283 if tags:
3259 3284 output.extend(taglist)
3260 3285
3261 3286 if bookmarks:
3262 3287 output.extend(ctx.bookmarks())
3263 3288
3264 3289 fm.data(node=ctx.hex())
3265 3290 fm.data(branch=ctx.branch())
3266 3291 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3267 3292 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3268 3293 fm.context(ctx=ctx)
3269 3294
3270 3295 fm.plain("%s\n" % ' '.join(output))
3271 3296 fm.end()
3272 3297
3273 3298 @command('import|patch',
3274 3299 [('p', 'strip', 1,
3275 3300 _('directory strip option for patch. This has the same '
3276 3301 'meaning as the corresponding patch option'), _('NUM')),
3277 3302 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3278 3303 ('e', 'edit', False, _('invoke editor on commit messages')),
3279 3304 ('f', 'force', None,
3280 3305 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3281 3306 ('', 'no-commit', None,
3282 3307 _("don't commit, just update the working directory")),
3283 3308 ('', 'bypass', None,
3284 3309 _("apply patch without touching the working directory")),
3285 3310 ('', 'partial', None,
3286 3311 _('commit even if some hunks fail')),
3287 3312 ('', 'exact', None,
3288 3313 _('abort if patch would apply lossily')),
3289 3314 ('', 'prefix', '',
3290 3315 _('apply patch to subdirectory'), _('DIR')),
3291 3316 ('', 'import-branch', None,
3292 3317 _('use any branch information in patch (implied by --exact)'))] +
3293 3318 commitopts + commitopts2 + similarityopts,
3294 3319 _('[OPTION]... PATCH...'),
3295 3320 helpcategory=command.CATEGORY_IMPORT_EXPORT)
3296 3321 def import_(ui, repo, patch1=None, *patches, **opts):
3297 3322 """import an ordered set of patches
3298 3323
3299 3324 Import a list of patches and commit them individually (unless
3300 3325 --no-commit is specified).
3301 3326
3302 3327 To read a patch from standard input (stdin), use "-" as the patch
3303 3328 name. If a URL is specified, the patch will be downloaded from
3304 3329 there.
3305 3330
3306 3331 Import first applies changes to the working directory (unless
3307 3332 --bypass is specified), import will abort if there are outstanding
3308 3333 changes.
3309 3334
3310 3335 Use --bypass to apply and commit patches directly to the
3311 3336 repository, without affecting the working directory. Without
3312 3337 --exact, patches will be applied on top of the working directory
3313 3338 parent revision.
3314 3339
3315 3340 You can import a patch straight from a mail message. Even patches
3316 3341 as attachments work (to use the body part, it must have type
3317 3342 text/plain or text/x-patch). From and Subject headers of email
3318 3343 message are used as default committer and commit message. All
3319 3344 text/plain body parts before first diff are added to the commit
3320 3345 message.
3321 3346
3322 3347 If the imported patch was generated by :hg:`export`, user and
3323 3348 description from patch override values from message headers and
3324 3349 body. Values given on command line with -m/--message and -u/--user
3325 3350 override these.
3326 3351
3327 3352 If --exact is specified, import will set the working directory to
3328 3353 the parent of each patch before applying it, and will abort if the
3329 3354 resulting changeset has a different ID than the one recorded in
3330 3355 the patch. This will guard against various ways that portable
3331 3356 patch formats and mail systems might fail to transfer Mercurial
3332 3357 data or metadata. See :hg:`bundle` for lossless transmission.
3333 3358
3334 3359 Use --partial to ensure a changeset will be created from the patch
3335 3360 even if some hunks fail to apply. Hunks that fail to apply will be
3336 3361 written to a <target-file>.rej file. Conflicts can then be resolved
3337 3362 by hand before :hg:`commit --amend` is run to update the created
3338 3363 changeset. This flag exists to let people import patches that
3339 3364 partially apply without losing the associated metadata (author,
3340 3365 date, description, ...).
3341 3366
3342 3367 .. note::
3343 3368
3344 3369 When no hunks apply cleanly, :hg:`import --partial` will create
3345 3370 an empty changeset, importing only the patch metadata.
3346 3371
3347 3372 With -s/--similarity, hg will attempt to discover renames and
3348 3373 copies in the patch in the same way as :hg:`addremove`.
3349 3374
3350 3375 It is possible to use external patch programs to perform the patch
3351 3376 by setting the ``ui.patch`` configuration option. For the default
3352 3377 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3353 3378 See :hg:`help config` for more information about configuration
3354 3379 files and how to use these options.
3355 3380
3356 3381 See :hg:`help dates` for a list of formats valid for -d/--date.
3357 3382
3358 3383 .. container:: verbose
3359 3384
3360 3385 Examples:
3361 3386
3362 3387 - import a traditional patch from a website and detect renames::
3363 3388
3364 3389 hg import -s 80 http://example.com/bugfix.patch
3365 3390
3366 3391 - import a changeset from an hgweb server::
3367 3392
3368 3393 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3369 3394
3370 3395 - import all the patches in an Unix-style mbox::
3371 3396
3372 3397 hg import incoming-patches.mbox
3373 3398
3374 3399 - import patches from stdin::
3375 3400
3376 3401 hg import -
3377 3402
3378 3403 - attempt to exactly restore an exported changeset (not always
3379 3404 possible)::
3380 3405
3381 3406 hg import --exact proposed-fix.patch
3382 3407
3383 3408 - use an external tool to apply a patch which is too fuzzy for
3384 3409 the default internal tool.
3385 3410
3386 3411 hg import --config ui.patch="patch --merge" fuzzy.patch
3387 3412
3388 3413 - change the default fuzzing from 2 to a less strict 7
3389 3414
3390 3415 hg import --config ui.fuzz=7 fuzz.patch
3391 3416
3392 3417 Returns 0 on success, 1 on partial success (see --partial).
3393 3418 """
3394 3419
3395 3420 opts = pycompat.byteskwargs(opts)
3396 3421 if not patch1:
3397 3422 raise error.Abort(_('need at least one patch to import'))
3398 3423
3399 3424 patches = (patch1,) + patches
3400 3425
3401 3426 date = opts.get('date')
3402 3427 if date:
3403 3428 opts['date'] = dateutil.parsedate(date)
3404 3429
3405 3430 exact = opts.get('exact')
3406 3431 update = not opts.get('bypass')
3407 3432 if not update and opts.get('no_commit'):
3408 3433 raise error.Abort(_('cannot use --no-commit with --bypass'))
3409 3434 try:
3410 3435 sim = float(opts.get('similarity') or 0)
3411 3436 except ValueError:
3412 3437 raise error.Abort(_('similarity must be a number'))
3413 3438 if sim < 0 or sim > 100:
3414 3439 raise error.Abort(_('similarity must be between 0 and 100'))
3415 3440 if sim and not update:
3416 3441 raise error.Abort(_('cannot use --similarity with --bypass'))
3417 3442 if exact:
3418 3443 if opts.get('edit'):
3419 3444 raise error.Abort(_('cannot use --exact with --edit'))
3420 3445 if opts.get('prefix'):
3421 3446 raise error.Abort(_('cannot use --exact with --prefix'))
3422 3447
3423 3448 base = opts["base"]
3424 3449 msgs = []
3425 3450 ret = 0
3426 3451
3427 3452 with repo.wlock():
3428 3453 if update:
3429 3454 cmdutil.checkunfinished(repo)
3430 3455 if (exact or not opts.get('force')):
3431 3456 cmdutil.bailifchanged(repo)
3432 3457
3433 3458 if not opts.get('no_commit'):
3434 3459 lock = repo.lock
3435 3460 tr = lambda: repo.transaction('import')
3436 3461 dsguard = util.nullcontextmanager
3437 3462 else:
3438 3463 lock = util.nullcontextmanager
3439 3464 tr = util.nullcontextmanager
3440 3465 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3441 3466 with lock(), tr(), dsguard():
3442 3467 parents = repo[None].parents()
3443 3468 for patchurl in patches:
3444 3469 if patchurl == '-':
3445 3470 ui.status(_('applying patch from stdin\n'))
3446 3471 patchfile = ui.fin
3447 3472 patchurl = 'stdin' # for error message
3448 3473 else:
3449 3474 patchurl = os.path.join(base, patchurl)
3450 3475 ui.status(_('applying %s\n') % patchurl)
3451 3476 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
3452 3477
3453 3478 haspatch = False
3454 3479 for hunk in patch.split(patchfile):
3455 3480 with patch.extract(ui, hunk) as patchdata:
3456 3481 msg, node, rej = cmdutil.tryimportone(ui, repo,
3457 3482 patchdata,
3458 3483 parents, opts,
3459 3484 msgs, hg.clean)
3460 3485 if msg:
3461 3486 haspatch = True
3462 3487 ui.note(msg + '\n')
3463 3488 if update or exact:
3464 3489 parents = repo[None].parents()
3465 3490 else:
3466 3491 parents = [repo[node]]
3467 3492 if rej:
3468 3493 ui.write_err(_("patch applied partially\n"))
3469 3494 ui.write_err(_("(fix the .rej files and run "
3470 3495 "`hg commit --amend`)\n"))
3471 3496 ret = 1
3472 3497 break
3473 3498
3474 3499 if not haspatch:
3475 3500 raise error.Abort(_('%s: no diffs found') % patchurl)
3476 3501
3477 3502 if msgs:
3478 3503 repo.savecommitmessage('\n* * *\n'.join(msgs))
3479 3504 return ret
3480 3505
3481 3506 @command('incoming|in',
3482 3507 [('f', 'force', None,
3483 3508 _('run even if remote repository is unrelated')),
3484 3509 ('n', 'newest-first', None, _('show newest record first')),
3485 3510 ('', 'bundle', '',
3486 3511 _('file to store the bundles into'), _('FILE')),
3487 3512 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3488 3513 ('B', 'bookmarks', False, _("compare bookmarks")),
3489 3514 ('b', 'branch', [],
3490 3515 _('a specific branch you would like to pull'), _('BRANCH')),
3491 3516 ] + logopts + remoteopts + subrepoopts,
3492 3517 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
3493 3518 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
3494 3519 def incoming(ui, repo, source="default", **opts):
3495 3520 """show new changesets found in source
3496 3521
3497 3522 Show new changesets found in the specified path/URL or the default
3498 3523 pull location. These are the changesets that would have been pulled
3499 3524 by :hg:`pull` at the time you issued this command.
3500 3525
3501 3526 See pull for valid source format details.
3502 3527
3503 3528 .. container:: verbose
3504 3529
3505 3530 With -B/--bookmarks, the result of bookmark comparison between
3506 3531 local and remote repositories is displayed. With -v/--verbose,
3507 3532 status is also displayed for each bookmark like below::
3508 3533
3509 3534 BM1 01234567890a added
3510 3535 BM2 1234567890ab advanced
3511 3536 BM3 234567890abc diverged
3512 3537 BM4 34567890abcd changed
3513 3538
3514 3539 The action taken locally when pulling depends on the
3515 3540 status of each bookmark:
3516 3541
3517 3542 :``added``: pull will create it
3518 3543 :``advanced``: pull will update it
3519 3544 :``diverged``: pull will create a divergent bookmark
3520 3545 :``changed``: result depends on remote changesets
3521 3546
3522 3547 From the point of view of pulling behavior, bookmark
3523 3548 existing only in the remote repository are treated as ``added``,
3524 3549 even if it is in fact locally deleted.
3525 3550
3526 3551 .. container:: verbose
3527 3552
3528 3553 For remote repository, using --bundle avoids downloading the
3529 3554 changesets twice if the incoming is followed by a pull.
3530 3555
3531 3556 Examples:
3532 3557
3533 3558 - show incoming changes with patches and full description::
3534 3559
3535 3560 hg incoming -vp
3536 3561
3537 3562 - show incoming changes excluding merges, store a bundle::
3538 3563
3539 3564 hg in -vpM --bundle incoming.hg
3540 3565 hg pull incoming.hg
3541 3566
3542 3567 - briefly list changes inside a bundle::
3543 3568
3544 3569 hg in changes.hg -T "{desc|firstline}\\n"
3545 3570
3546 3571 Returns 0 if there are incoming changes, 1 otherwise.
3547 3572 """
3548 3573 opts = pycompat.byteskwargs(opts)
3549 3574 if opts.get('graph'):
3550 3575 logcmdutil.checkunsupportedgraphflags([], opts)
3551 3576 def display(other, chlist, displayer):
3552 3577 revdag = logcmdutil.graphrevs(other, chlist, opts)
3553 3578 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3554 3579 graphmod.asciiedges)
3555 3580
3556 3581 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3557 3582 return 0
3558 3583
3559 3584 if opts.get('bundle') and opts.get('subrepos'):
3560 3585 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3561 3586
3562 3587 if opts.get('bookmarks'):
3563 3588 source, branches = hg.parseurl(ui.expandpath(source),
3564 3589 opts.get('branch'))
3565 3590 other = hg.peer(repo, opts, source)
3566 3591 if 'bookmarks' not in other.listkeys('namespaces'):
3567 3592 ui.warn(_("remote doesn't support bookmarks\n"))
3568 3593 return 0
3569 3594 ui.pager('incoming')
3570 3595 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3571 3596 return bookmarks.incoming(ui, repo, other)
3572 3597
3573 3598 repo._subtoppath = ui.expandpath(source)
3574 3599 try:
3575 3600 return hg.incoming(ui, repo, source, opts)
3576 3601 finally:
3577 3602 del repo._subtoppath
3578 3603
3579 3604
3580 3605 @command('init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3581 3606 helpcategory=command.CATEGORY_REPO_CREATION,
3582 3607 helpbasic=True, norepo=True)
3583 3608 def init(ui, dest=".", **opts):
3584 3609 """create a new repository in the given directory
3585 3610
3586 3611 Initialize a new repository in the given directory. If the given
3587 3612 directory does not exist, it will be created.
3588 3613
3589 3614 If no directory is given, the current directory is used.
3590 3615
3591 3616 It is possible to specify an ``ssh://`` URL as the destination.
3592 3617 See :hg:`help urls` for more information.
3593 3618
3594 3619 Returns 0 on success.
3595 3620 """
3596 3621 opts = pycompat.byteskwargs(opts)
3597 3622 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3598 3623
3599 3624 @command('locate',
3600 3625 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3601 3626 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3602 3627 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3603 3628 ] + walkopts,
3604 3629 _('[OPTION]... [PATTERN]...'),
3605 3630 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
3606 3631 def locate(ui, repo, *pats, **opts):
3607 3632 """locate files matching specific patterns (DEPRECATED)
3608 3633
3609 3634 Print files under Mercurial control in the working directory whose
3610 3635 names match the given patterns.
3611 3636
3612 3637 By default, this command searches all directories in the working
3613 3638 directory. To search just the current directory and its
3614 3639 subdirectories, use "--include .".
3615 3640
3616 3641 If no patterns are given to match, this command prints the names
3617 3642 of all files under Mercurial control in the working directory.
3618 3643
3619 3644 If you want to feed the output of this command into the "xargs"
3620 3645 command, use the -0 option to both this command and "xargs". This
3621 3646 will avoid the problem of "xargs" treating single filenames that
3622 3647 contain whitespace as multiple filenames.
3623 3648
3624 3649 See :hg:`help files` for a more versatile command.
3625 3650
3626 3651 Returns 0 if a match is found, 1 otherwise.
3627 3652 """
3628 3653 opts = pycompat.byteskwargs(opts)
3629 3654 if opts.get('print0'):
3630 3655 end = '\0'
3631 3656 else:
3632 3657 end = '\n'
3633 3658 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3634 3659
3635 3660 ret = 1
3636 3661 m = scmutil.match(ctx, pats, opts, default='relglob',
3637 3662 badfn=lambda x, y: False)
3638 3663
3639 3664 ui.pager('locate')
3640 3665 if ctx.rev() is None:
3641 3666 # When run on the working copy, "locate" includes removed files, so
3642 3667 # we get the list of files from the dirstate.
3643 3668 filesgen = sorted(repo.dirstate.matches(m))
3644 3669 else:
3645 3670 filesgen = ctx.matches(m)
3646 3671 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
3647 3672 for abs in filesgen:
3648 3673 if opts.get('fullpath'):
3649 3674 ui.write(repo.wjoin(abs), end)
3650 3675 else:
3651 3676 ui.write(uipathfn(abs), end)
3652 3677 ret = 0
3653 3678
3654 3679 return ret
3655 3680
3656 3681 @command('log|history',
3657 3682 [('f', 'follow', None,
3658 3683 _('follow changeset history, or file history across copies and renames')),
3659 3684 ('', 'follow-first', None,
3660 3685 _('only follow the first parent of merge changesets (DEPRECATED)')),
3661 3686 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3662 3687 ('C', 'copies', None, _('show copied files')),
3663 3688 ('k', 'keyword', [],
3664 3689 _('do case-insensitive search for a given text'), _('TEXT')),
3665 3690 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3666 3691 ('L', 'line-range', [],
3667 3692 _('follow line range of specified file (EXPERIMENTAL)'),
3668 3693 _('FILE,RANGE')),
3669 3694 ('', 'removed', None, _('include revisions where files were removed')),
3670 3695 ('m', 'only-merges', None,
3671 3696 _('show only merges (DEPRECATED) (use -r "merge()" instead)')),
3672 3697 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3673 3698 ('', 'only-branch', [],
3674 3699 _('show only changesets within the given named branch (DEPRECATED)'),
3675 3700 _('BRANCH')),
3676 3701 ('b', 'branch', [],
3677 3702 _('show changesets within the given named branch'), _('BRANCH')),
3678 3703 ('P', 'prune', [],
3679 3704 _('do not display revision or any of its ancestors'), _('REV')),
3680 3705 ] + logopts + walkopts,
3681 3706 _('[OPTION]... [FILE]'),
3682 3707 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3683 3708 helpbasic=True, inferrepo=True,
3684 3709 intents={INTENT_READONLY})
3685 3710 def log(ui, repo, *pats, **opts):
3686 3711 """show revision history of entire repository or files
3687 3712
3688 3713 Print the revision history of the specified files or the entire
3689 3714 project.
3690 3715
3691 3716 If no revision range is specified, the default is ``tip:0`` unless
3692 3717 --follow is set, in which case the working directory parent is
3693 3718 used as the starting revision.
3694 3719
3695 3720 File history is shown without following rename or copy history of
3696 3721 files. Use -f/--follow with a filename to follow history across
3697 3722 renames and copies. --follow without a filename will only show
3698 3723 ancestors of the starting revision.
3699 3724
3700 3725 By default this command prints revision number and changeset id,
3701 3726 tags, non-trivial parents, user, date and time, and a summary for
3702 3727 each commit. When the -v/--verbose switch is used, the list of
3703 3728 changed files and full commit message are shown.
3704 3729
3705 3730 With --graph the revisions are shown as an ASCII art DAG with the most
3706 3731 recent changeset at the top.
3707 3732 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3708 3733 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3709 3734 changeset from the lines below is a parent of the 'o' merge on the same
3710 3735 line.
3711 3736 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3712 3737 of a '|' indicates one or more revisions in a path are omitted.
3713 3738
3714 3739 .. container:: verbose
3715 3740
3716 3741 Use -L/--line-range FILE,M:N options to follow the history of lines
3717 3742 from M to N in FILE. With -p/--patch only diff hunks affecting
3718 3743 specified line range will be shown. This option requires --follow;
3719 3744 it can be specified multiple times. Currently, this option is not
3720 3745 compatible with --graph. This option is experimental.
3721 3746
3722 3747 .. note::
3723 3748
3724 3749 :hg:`log --patch` may generate unexpected diff output for merge
3725 3750 changesets, as it will only compare the merge changeset against
3726 3751 its first parent. Also, only files different from BOTH parents
3727 3752 will appear in files:.
3728 3753
3729 3754 .. note::
3730 3755
3731 3756 For performance reasons, :hg:`log FILE` may omit duplicate changes
3732 3757 made on branches and will not show removals or mode changes. To
3733 3758 see all such changes, use the --removed switch.
3734 3759
3735 3760 .. container:: verbose
3736 3761
3737 3762 .. note::
3738 3763
3739 3764 The history resulting from -L/--line-range options depends on diff
3740 3765 options; for instance if white-spaces are ignored, respective changes
3741 3766 with only white-spaces in specified line range will not be listed.
3742 3767
3743 3768 .. container:: verbose
3744 3769
3745 3770 Some examples:
3746 3771
3747 3772 - changesets with full descriptions and file lists::
3748 3773
3749 3774 hg log -v
3750 3775
3751 3776 - changesets ancestral to the working directory::
3752 3777
3753 3778 hg log -f
3754 3779
3755 3780 - last 10 commits on the current branch::
3756 3781
3757 3782 hg log -l 10 -b .
3758 3783
3759 3784 - changesets showing all modifications of a file, including removals::
3760 3785
3761 3786 hg log --removed file.c
3762 3787
3763 3788 - all changesets that touch a directory, with diffs, excluding merges::
3764 3789
3765 3790 hg log -Mp lib/
3766 3791
3767 3792 - all revision numbers that match a keyword::
3768 3793
3769 3794 hg log -k bug --template "{rev}\\n"
3770 3795
3771 3796 - the full hash identifier of the working directory parent::
3772 3797
3773 3798 hg log -r . --template "{node}\\n"
3774 3799
3775 3800 - list available log templates::
3776 3801
3777 3802 hg log -T list
3778 3803
3779 3804 - check if a given changeset is included in a tagged release::
3780 3805
3781 3806 hg log -r "a21ccf and ancestor(1.9)"
3782 3807
3783 3808 - find all changesets by some user in a date range::
3784 3809
3785 3810 hg log -k alice -d "may 2008 to jul 2008"
3786 3811
3787 3812 - summary of all changesets after the last tag::
3788 3813
3789 3814 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3790 3815
3791 3816 - changesets touching lines 13 to 23 for file.c::
3792 3817
3793 3818 hg log -L file.c,13:23
3794 3819
3795 3820 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3796 3821 main.c with patch::
3797 3822
3798 3823 hg log -L file.c,13:23 -L main.c,2:6 -p
3799 3824
3800 3825 See :hg:`help dates` for a list of formats valid for -d/--date.
3801 3826
3802 3827 See :hg:`help revisions` for more about specifying and ordering
3803 3828 revisions.
3804 3829
3805 3830 See :hg:`help templates` for more about pre-packaged styles and
3806 3831 specifying custom templates. The default template used by the log
3807 3832 command can be customized via the ``ui.logtemplate`` configuration
3808 3833 setting.
3809 3834
3810 3835 Returns 0 on success.
3811 3836
3812 3837 """
3813 3838 opts = pycompat.byteskwargs(opts)
3814 3839 linerange = opts.get('line_range')
3815 3840
3816 3841 if linerange and not opts.get('follow'):
3817 3842 raise error.Abort(_('--line-range requires --follow'))
3818 3843
3819 3844 if linerange and pats:
3820 3845 # TODO: take pats as patterns with no line-range filter
3821 3846 raise error.Abort(
3822 3847 _('FILE arguments are not compatible with --line-range option')
3823 3848 )
3824 3849
3825 3850 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3826 3851 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3827 3852 if linerange:
3828 3853 # TODO: should follow file history from logcmdutil._initialrevs(),
3829 3854 # then filter the result by logcmdutil._makerevset() and --limit
3830 3855 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3831 3856
3832 3857 getcopies = None
3833 3858 if opts.get('copies'):
3834 3859 endrev = None
3835 3860 if revs:
3836 3861 endrev = revs.max() + 1
3837 3862 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
3838 3863
3839 3864 ui.pager('log')
3840 3865 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3841 3866 buffered=True)
3842 3867 if opts.get('graph'):
3843 3868 displayfn = logcmdutil.displaygraphrevs
3844 3869 else:
3845 3870 displayfn = logcmdutil.displayrevs
3846 3871 displayfn(ui, repo, revs, displayer, getcopies)
3847 3872
3848 3873 @command('manifest',
3849 3874 [('r', 'rev', '', _('revision to display'), _('REV')),
3850 3875 ('', 'all', False, _("list files from all revisions"))]
3851 3876 + formatteropts,
3852 3877 _('[-r REV]'),
3853 3878 helpcategory=command.CATEGORY_MAINTENANCE,
3854 3879 intents={INTENT_READONLY})
3855 3880 def manifest(ui, repo, node=None, rev=None, **opts):
3856 3881 """output the current or given revision of the project manifest
3857 3882
3858 3883 Print a list of version controlled files for the given revision.
3859 3884 If no revision is given, the first parent of the working directory
3860 3885 is used, or the null revision if no revision is checked out.
3861 3886
3862 3887 With -v, print file permissions, symlink and executable bits.
3863 3888 With --debug, print file revision hashes.
3864 3889
3865 3890 If option --all is specified, the list of all files from all revisions
3866 3891 is printed. This includes deleted and renamed files.
3867 3892
3868 3893 Returns 0 on success.
3869 3894 """
3870 3895 opts = pycompat.byteskwargs(opts)
3871 3896 fm = ui.formatter('manifest', opts)
3872 3897
3873 3898 if opts.get('all'):
3874 3899 if rev or node:
3875 3900 raise error.Abort(_("can't specify a revision with --all"))
3876 3901
3877 3902 res = set()
3878 3903 for rev in repo:
3879 3904 ctx = repo[rev]
3880 3905 res |= set(ctx.files())
3881 3906
3882 3907 ui.pager('manifest')
3883 3908 for f in sorted(res):
3884 3909 fm.startitem()
3885 3910 fm.write("path", '%s\n', f)
3886 3911 fm.end()
3887 3912 return
3888 3913
3889 3914 if rev and node:
3890 3915 raise error.Abort(_("please specify just one revision"))
3891 3916
3892 3917 if not node:
3893 3918 node = rev
3894 3919
3895 3920 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3896 3921 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3897 3922 if node:
3898 3923 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3899 3924 ctx = scmutil.revsingle(repo, node)
3900 3925 mf = ctx.manifest()
3901 3926 ui.pager('manifest')
3902 3927 for f in ctx:
3903 3928 fm.startitem()
3904 3929 fm.context(ctx=ctx)
3905 3930 fl = ctx[f].flags()
3906 3931 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3907 3932 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3908 3933 fm.write('path', '%s\n', f)
3909 3934 fm.end()
3910 3935
3911 3936 @command('merge',
3912 3937 [('f', 'force', None,
3913 3938 _('force a merge including outstanding changes (DEPRECATED)')),
3914 3939 ('r', 'rev', '', _('revision to merge'), _('REV')),
3915 3940 ('P', 'preview', None,
3916 3941 _('review revisions to merge (no merge is performed)')),
3917 3942 ('', 'abort', None, _('abort the ongoing merge')),
3918 3943 ] + mergetoolopts,
3919 3944 _('[-P] [[-r] REV]'),
3920 3945 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True)
3921 3946 def merge(ui, repo, node=None, **opts):
3922 3947 """merge another revision into working directory
3923 3948
3924 3949 The current working directory is updated with all changes made in
3925 3950 the requested revision since the last common predecessor revision.
3926 3951
3927 3952 Files that changed between either parent are marked as changed for
3928 3953 the next commit and a commit must be performed before any further
3929 3954 updates to the repository are allowed. The next commit will have
3930 3955 two parents.
3931 3956
3932 3957 ``--tool`` can be used to specify the merge tool used for file
3933 3958 merges. It overrides the HGMERGE environment variable and your
3934 3959 configuration files. See :hg:`help merge-tools` for options.
3935 3960
3936 3961 If no revision is specified, the working directory's parent is a
3937 3962 head revision, and the current branch contains exactly one other
3938 3963 head, the other head is merged with by default. Otherwise, an
3939 3964 explicit revision with which to merge must be provided.
3940 3965
3941 3966 See :hg:`help resolve` for information on handling file conflicts.
3942 3967
3943 3968 To undo an uncommitted merge, use :hg:`merge --abort` which
3944 3969 will check out a clean copy of the original merge parent, losing
3945 3970 all changes.
3946 3971
3947 3972 Returns 0 on success, 1 if there are unresolved files.
3948 3973 """
3949 3974
3950 3975 opts = pycompat.byteskwargs(opts)
3951 3976 abort = opts.get('abort')
3952 3977 if abort and repo.dirstate.p2() == nullid:
3953 3978 cmdutil.wrongtooltocontinue(repo, _('merge'))
3954 3979 if abort:
3955 3980 state = cmdutil.getunfinishedstate(repo)
3956 3981 if state and state._opname != 'merge':
3957 3982 raise error.Abort(_('cannot abort merge with %s in progress') %
3958 3983 (state._opname), hint=state.hint())
3959 3984 if node:
3960 3985 raise error.Abort(_("cannot specify a node with --abort"))
3961 3986 if opts.get('rev'):
3962 3987 raise error.Abort(_("cannot specify both --rev and --abort"))
3963 3988 if opts.get('preview'):
3964 3989 raise error.Abort(_("cannot specify --preview with --abort"))
3965 3990 if opts.get('rev') and node:
3966 3991 raise error.Abort(_("please specify just one revision"))
3967 3992 if not node:
3968 3993 node = opts.get('rev')
3969 3994
3970 3995 if node:
3971 3996 node = scmutil.revsingle(repo, node).node()
3972 3997
3973 3998 if not node and not abort:
3974 3999 node = repo[destutil.destmerge(repo)].node()
3975 4000
3976 4001 if opts.get('preview'):
3977 4002 # find nodes that are ancestors of p2 but not of p1
3978 4003 p1 = repo.lookup('.')
3979 4004 p2 = node
3980 4005 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3981 4006
3982 4007 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3983 4008 for node in nodes:
3984 4009 displayer.show(repo[node])
3985 4010 displayer.close()
3986 4011 return 0
3987 4012
3988 4013 # ui.forcemerge is an internal variable, do not document
3989 4014 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
3990 4015 with ui.configoverride(overrides, 'merge'):
3991 4016 force = opts.get('force')
3992 4017 labels = ['working copy', 'merge rev']
3993 4018 return hg.merge(repo, node, force=force, mergeforce=force,
3994 4019 labels=labels, abort=abort)
3995 4020
3996 4021 @command('outgoing|out',
3997 4022 [('f', 'force', None, _('run even when the destination is unrelated')),
3998 4023 ('r', 'rev', [],
3999 4024 _('a changeset intended to be included in the destination'), _('REV')),
4000 4025 ('n', 'newest-first', None, _('show newest record first')),
4001 4026 ('B', 'bookmarks', False, _('compare bookmarks')),
4002 4027 ('b', 'branch', [], _('a specific branch you would like to push'),
4003 4028 _('BRANCH')),
4004 4029 ] + logopts + remoteopts + subrepoopts,
4005 4030 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4006 4031 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
4007 4032 def outgoing(ui, repo, dest=None, **opts):
4008 4033 """show changesets not found in the destination
4009 4034
4010 4035 Show changesets not found in the specified destination repository
4011 4036 or the default push location. These are the changesets that would
4012 4037 be pushed if a push was requested.
4013 4038
4014 4039 See pull for details of valid destination formats.
4015 4040
4016 4041 .. container:: verbose
4017 4042
4018 4043 With -B/--bookmarks, the result of bookmark comparison between
4019 4044 local and remote repositories is displayed. With -v/--verbose,
4020 4045 status is also displayed for each bookmark like below::
4021 4046
4022 4047 BM1 01234567890a added
4023 4048 BM2 deleted
4024 4049 BM3 234567890abc advanced
4025 4050 BM4 34567890abcd diverged
4026 4051 BM5 4567890abcde changed
4027 4052
4028 4053 The action taken when pushing depends on the
4029 4054 status of each bookmark:
4030 4055
4031 4056 :``added``: push with ``-B`` will create it
4032 4057 :``deleted``: push with ``-B`` will delete it
4033 4058 :``advanced``: push will update it
4034 4059 :``diverged``: push with ``-B`` will update it
4035 4060 :``changed``: push with ``-B`` will update it
4036 4061
4037 4062 From the point of view of pushing behavior, bookmarks
4038 4063 existing only in the remote repository are treated as
4039 4064 ``deleted``, even if it is in fact added remotely.
4040 4065
4041 4066 Returns 0 if there are outgoing changes, 1 otherwise.
4042 4067 """
4043 4068 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4044 4069 # style URLs, so don't overwrite dest.
4045 4070 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4046 4071 if not path:
4047 4072 raise error.Abort(_('default repository not configured!'),
4048 4073 hint=_("see 'hg help config.paths'"))
4049 4074
4050 4075 opts = pycompat.byteskwargs(opts)
4051 4076 if opts.get('graph'):
4052 4077 logcmdutil.checkunsupportedgraphflags([], opts)
4053 4078 o, other = hg._outgoing(ui, repo, dest, opts)
4054 4079 if not o:
4055 4080 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4056 4081 return
4057 4082
4058 4083 revdag = logcmdutil.graphrevs(repo, o, opts)
4059 4084 ui.pager('outgoing')
4060 4085 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4061 4086 logcmdutil.displaygraph(ui, repo, revdag, displayer,
4062 4087 graphmod.asciiedges)
4063 4088 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4064 4089 return 0
4065 4090
4066 4091 if opts.get('bookmarks'):
4067 4092 dest = path.pushloc or path.loc
4068 4093 other = hg.peer(repo, opts, dest)
4069 4094 if 'bookmarks' not in other.listkeys('namespaces'):
4070 4095 ui.warn(_("remote doesn't support bookmarks\n"))
4071 4096 return 0
4072 4097 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4073 4098 ui.pager('outgoing')
4074 4099 return bookmarks.outgoing(ui, repo, other)
4075 4100
4076 4101 repo._subtoppath = path.pushloc or path.loc
4077 4102 try:
4078 4103 return hg.outgoing(ui, repo, dest, opts)
4079 4104 finally:
4080 4105 del repo._subtoppath
4081 4106
4082 4107 @command('parents',
4083 4108 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4084 4109 ] + templateopts,
4085 4110 _('[-r REV] [FILE]'),
4086 4111 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4087 4112 inferrepo=True)
4088 4113 def parents(ui, repo, file_=None, **opts):
4089 4114 """show the parents of the working directory or revision (DEPRECATED)
4090 4115
4091 4116 Print the working directory's parent revisions. If a revision is
4092 4117 given via -r/--rev, the parent of that revision will be printed.
4093 4118 If a file argument is given, the revision in which the file was
4094 4119 last changed (before the working directory revision or the
4095 4120 argument to --rev if given) is printed.
4096 4121
4097 4122 This command is equivalent to::
4098 4123
4099 4124 hg log -r "p1()+p2()" or
4100 4125 hg log -r "p1(REV)+p2(REV)" or
4101 4126 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4102 4127 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4103 4128
4104 4129 See :hg:`summary` and :hg:`help revsets` for related information.
4105 4130
4106 4131 Returns 0 on success.
4107 4132 """
4108 4133
4109 4134 opts = pycompat.byteskwargs(opts)
4110 4135 rev = opts.get('rev')
4111 4136 if rev:
4112 4137 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4113 4138 ctx = scmutil.revsingle(repo, rev, None)
4114 4139
4115 4140 if file_:
4116 4141 m = scmutil.match(ctx, (file_,), opts)
4117 4142 if m.anypats() or len(m.files()) != 1:
4118 4143 raise error.Abort(_('can only specify an explicit filename'))
4119 4144 file_ = m.files()[0]
4120 4145 filenodes = []
4121 4146 for cp in ctx.parents():
4122 4147 if not cp:
4123 4148 continue
4124 4149 try:
4125 4150 filenodes.append(cp.filenode(file_))
4126 4151 except error.LookupError:
4127 4152 pass
4128 4153 if not filenodes:
4129 4154 raise error.Abort(_("'%s' not found in manifest!") % file_)
4130 4155 p = []
4131 4156 for fn in filenodes:
4132 4157 fctx = repo.filectx(file_, fileid=fn)
4133 4158 p.append(fctx.node())
4134 4159 else:
4135 4160 p = [cp.node() for cp in ctx.parents()]
4136 4161
4137 4162 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4138 4163 for n in p:
4139 4164 if n != nullid:
4140 4165 displayer.show(repo[n])
4141 4166 displayer.close()
4142 4167
4143 4168 @command('paths', formatteropts, _('[NAME]'),
4144 4169 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4145 4170 optionalrepo=True, intents={INTENT_READONLY})
4146 4171 def paths(ui, repo, search=None, **opts):
4147 4172 """show aliases for remote repositories
4148 4173
4149 4174 Show definition of symbolic path name NAME. If no name is given,
4150 4175 show definition of all available names.
4151 4176
4152 4177 Option -q/--quiet suppresses all output when searching for NAME
4153 4178 and shows only the path names when listing all definitions.
4154 4179
4155 4180 Path names are defined in the [paths] section of your
4156 4181 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4157 4182 repository, ``.hg/hgrc`` is used, too.
4158 4183
4159 4184 The path names ``default`` and ``default-push`` have a special
4160 4185 meaning. When performing a push or pull operation, they are used
4161 4186 as fallbacks if no location is specified on the command-line.
4162 4187 When ``default-push`` is set, it will be used for push and
4163 4188 ``default`` will be used for pull; otherwise ``default`` is used
4164 4189 as the fallback for both. When cloning a repository, the clone
4165 4190 source is written as ``default`` in ``.hg/hgrc``.
4166 4191
4167 4192 .. note::
4168 4193
4169 4194 ``default`` and ``default-push`` apply to all inbound (e.g.
4170 4195 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
4171 4196 and :hg:`bundle`) operations.
4172 4197
4173 4198 See :hg:`help urls` for more information.
4174 4199
4175 4200 .. container:: verbose
4176 4201
4177 4202 Template:
4178 4203
4179 4204 The following keywords are supported. See also :hg:`help templates`.
4180 4205
4181 4206 :name: String. Symbolic name of the path alias.
4182 4207 :pushurl: String. URL for push operations.
4183 4208 :url: String. URL or directory path for the other operations.
4184 4209
4185 4210 Returns 0 on success.
4186 4211 """
4187 4212
4188 4213 opts = pycompat.byteskwargs(opts)
4189 4214 ui.pager('paths')
4190 4215 if search:
4191 4216 pathitems = [(name, path) for name, path in ui.paths.iteritems()
4192 4217 if name == search]
4193 4218 else:
4194 4219 pathitems = sorted(ui.paths.iteritems())
4195 4220
4196 4221 fm = ui.formatter('paths', opts)
4197 4222 if fm.isplain():
4198 4223 hidepassword = util.hidepassword
4199 4224 else:
4200 4225 hidepassword = bytes
4201 4226 if ui.quiet:
4202 4227 namefmt = '%s\n'
4203 4228 else:
4204 4229 namefmt = '%s = '
4205 4230 showsubopts = not search and not ui.quiet
4206 4231
4207 4232 for name, path in pathitems:
4208 4233 fm.startitem()
4209 4234 fm.condwrite(not search, 'name', namefmt, name)
4210 4235 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4211 4236 for subopt, value in sorted(path.suboptions.items()):
4212 4237 assert subopt not in ('name', 'url')
4213 4238 if showsubopts:
4214 4239 fm.plain('%s:%s = ' % (name, subopt))
4215 4240 fm.condwrite(showsubopts, subopt, '%s\n', value)
4216 4241
4217 4242 fm.end()
4218 4243
4219 4244 if search and not pathitems:
4220 4245 if not ui.quiet:
4221 4246 ui.warn(_("not found!\n"))
4222 4247 return 1
4223 4248 else:
4224 4249 return 0
4225 4250
4226 4251 @command('phase',
4227 4252 [('p', 'public', False, _('set changeset phase to public')),
4228 4253 ('d', 'draft', False, _('set changeset phase to draft')),
4229 4254 ('s', 'secret', False, _('set changeset phase to secret')),
4230 4255 ('f', 'force', False, _('allow to move boundary backward')),
4231 4256 ('r', 'rev', [], _('target revision'), _('REV')),
4232 4257 ],
4233 4258 _('[-p|-d|-s] [-f] [-r] [REV...]'),
4234 4259 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
4235 4260 def phase(ui, repo, *revs, **opts):
4236 4261 """set or show the current phase name
4237 4262
4238 4263 With no argument, show the phase name of the current revision(s).
4239 4264
4240 4265 With one of -p/--public, -d/--draft or -s/--secret, change the
4241 4266 phase value of the specified revisions.
4242 4267
4243 4268 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4244 4269 lower phase to a higher phase. Phases are ordered as follows::
4245 4270
4246 4271 public < draft < secret
4247 4272
4248 4273 Returns 0 on success, 1 if some phases could not be changed.
4249 4274
4250 4275 (For more information about the phases concept, see :hg:`help phases`.)
4251 4276 """
4252 4277 opts = pycompat.byteskwargs(opts)
4253 4278 # search for a unique phase argument
4254 4279 targetphase = None
4255 4280 for idx, name in enumerate(phases.cmdphasenames):
4256 4281 if opts[name]:
4257 4282 if targetphase is not None:
4258 4283 raise error.Abort(_('only one phase can be specified'))
4259 4284 targetphase = idx
4260 4285
4261 4286 # look for specified revision
4262 4287 revs = list(revs)
4263 4288 revs.extend(opts['rev'])
4264 4289 if not revs:
4265 4290 # display both parents as the second parent phase can influence
4266 4291 # the phase of a merge commit
4267 4292 revs = [c.rev() for c in repo[None].parents()]
4268 4293
4269 4294 revs = scmutil.revrange(repo, revs)
4270 4295
4271 4296 ret = 0
4272 4297 if targetphase is None:
4273 4298 # display
4274 4299 for r in revs:
4275 4300 ctx = repo[r]
4276 4301 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4277 4302 else:
4278 4303 with repo.lock(), repo.transaction("phase") as tr:
4279 4304 # set phase
4280 4305 if not revs:
4281 4306 raise error.Abort(_('empty revision set'))
4282 4307 nodes = [repo[r].node() for r in revs]
4283 4308 # moving revision from public to draft may hide them
4284 4309 # We have to check result on an unfiltered repository
4285 4310 unfi = repo.unfiltered()
4286 4311 getphase = unfi._phasecache.phase
4287 4312 olddata = [getphase(unfi, r) for r in unfi]
4288 4313 phases.advanceboundary(repo, tr, targetphase, nodes)
4289 4314 if opts['force']:
4290 4315 phases.retractboundary(repo, tr, targetphase, nodes)
4291 4316 getphase = unfi._phasecache.phase
4292 4317 newdata = [getphase(unfi, r) for r in unfi]
4293 4318 changes = sum(newdata[r] != olddata[r] for r in unfi)
4294 4319 cl = unfi.changelog
4295 4320 rejected = [n for n in nodes
4296 4321 if newdata[cl.rev(n)] < targetphase]
4297 4322 if rejected:
4298 4323 ui.warn(_('cannot move %i changesets to a higher '
4299 4324 'phase, use --force\n') % len(rejected))
4300 4325 ret = 1
4301 4326 if changes:
4302 4327 msg = _('phase changed for %i changesets\n') % changes
4303 4328 if ret:
4304 4329 ui.status(msg)
4305 4330 else:
4306 4331 ui.note(msg)
4307 4332 else:
4308 4333 ui.warn(_('no phases changed\n'))
4309 4334 return ret
4310 4335
4311 4336 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4312 4337 """Run after a changegroup has been added via pull/unbundle
4313 4338
4314 4339 This takes arguments below:
4315 4340
4316 4341 :modheads: change of heads by pull/unbundle
4317 4342 :optupdate: updating working directory is needed or not
4318 4343 :checkout: update destination revision (or None to default destination)
4319 4344 :brev: a name, which might be a bookmark to be activated after updating
4320 4345 """
4321 4346 if modheads == 0:
4322 4347 return
4323 4348 if optupdate:
4324 4349 try:
4325 4350 return hg.updatetotally(ui, repo, checkout, brev)
4326 4351 except error.UpdateAbort as inst:
4327 4352 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4328 4353 hint = inst.hint
4329 4354 raise error.UpdateAbort(msg, hint=hint)
4330 4355 if modheads is not None and modheads > 1:
4331 4356 currentbranchheads = len(repo.branchheads())
4332 4357 if currentbranchheads == modheads:
4333 4358 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4334 4359 elif currentbranchheads > 1:
4335 4360 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4336 4361 "merge)\n"))
4337 4362 else:
4338 4363 ui.status(_("(run 'hg heads' to see heads)\n"))
4339 4364 elif not ui.configbool('commands', 'update.requiredest'):
4340 4365 ui.status(_("(run 'hg update' to get a working copy)\n"))
4341 4366
4342 4367 @command('pull',
4343 4368 [('u', 'update', None,
4344 4369 _('update to new branch head if new descendants were pulled')),
4345 4370 ('f', 'force', None, _('run even when remote repository is unrelated')),
4346 4371 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4347 4372 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4348 4373 ('b', 'branch', [], _('a specific branch you would like to pull'),
4349 4374 _('BRANCH')),
4350 4375 ] + remoteopts,
4351 4376 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
4352 4377 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4353 4378 helpbasic=True)
4354 4379 def pull(ui, repo, source="default", **opts):
4355 4380 """pull changes from the specified source
4356 4381
4357 4382 Pull changes from a remote repository to a local one.
4358 4383
4359 4384 This finds all changes from the repository at the specified path
4360 4385 or URL and adds them to a local repository (the current one unless
4361 4386 -R is specified). By default, this does not update the copy of the
4362 4387 project in the working directory.
4363 4388
4364 4389 When cloning from servers that support it, Mercurial may fetch
4365 4390 pre-generated data. When this is done, hooks operating on incoming
4366 4391 changesets and changegroups may fire more than once, once for each
4367 4392 pre-generated bundle and as well as for any additional remaining
4368 4393 data. See :hg:`help -e clonebundles` for more.
4369 4394
4370 4395 Use :hg:`incoming` if you want to see what would have been added
4371 4396 by a pull at the time you issued this command. If you then decide
4372 4397 to add those changes to the repository, you should use :hg:`pull
4373 4398 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4374 4399
4375 4400 If SOURCE is omitted, the 'default' path will be used.
4376 4401 See :hg:`help urls` for more information.
4377 4402
4378 4403 Specifying bookmark as ``.`` is equivalent to specifying the active
4379 4404 bookmark's name.
4380 4405
4381 4406 Returns 0 on success, 1 if an update had unresolved files.
4382 4407 """
4383 4408
4384 4409 opts = pycompat.byteskwargs(opts)
4385 4410 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4386 4411 msg = _('update destination required by configuration')
4387 4412 hint = _('use hg pull followed by hg update DEST')
4388 4413 raise error.Abort(msg, hint=hint)
4389 4414
4390 4415 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4391 4416 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4392 4417 other = hg.peer(repo, opts, source)
4393 4418 try:
4394 4419 revs, checkout = hg.addbranchrevs(repo, other, branches,
4395 4420 opts.get('rev'))
4396 4421
4397 4422 pullopargs = {}
4398 4423
4399 4424 nodes = None
4400 4425 if opts.get('bookmark') or revs:
4401 4426 # The list of bookmark used here is the same used to actually update
4402 4427 # the bookmark names, to avoid the race from issue 4689 and we do
4403 4428 # all lookup and bookmark queries in one go so they see the same
4404 4429 # version of the server state (issue 4700).
4405 4430 nodes = []
4406 4431 fnodes = []
4407 4432 revs = revs or []
4408 4433 if revs and not other.capable('lookup'):
4409 4434 err = _("other repository doesn't support revision lookup, "
4410 4435 "so a rev cannot be specified.")
4411 4436 raise error.Abort(err)
4412 4437 with other.commandexecutor() as e:
4413 4438 fremotebookmarks = e.callcommand('listkeys', {
4414 4439 'namespace': 'bookmarks'
4415 4440 })
4416 4441 for r in revs:
4417 4442 fnodes.append(e.callcommand('lookup', {'key': r}))
4418 4443 remotebookmarks = fremotebookmarks.result()
4419 4444 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4420 4445 pullopargs['remotebookmarks'] = remotebookmarks
4421 4446 for b in opts.get('bookmark', []):
4422 4447 b = repo._bookmarks.expandname(b)
4423 4448 if b not in remotebookmarks:
4424 4449 raise error.Abort(_('remote bookmark %s not found!') % b)
4425 4450 nodes.append(remotebookmarks[b])
4426 4451 for i, rev in enumerate(revs):
4427 4452 node = fnodes[i].result()
4428 4453 nodes.append(node)
4429 4454 if rev == checkout:
4430 4455 checkout = node
4431 4456
4432 4457 wlock = util.nullcontextmanager()
4433 4458 if opts.get('update'):
4434 4459 wlock = repo.wlock()
4435 4460 with wlock:
4436 4461 pullopargs.update(opts.get('opargs', {}))
4437 4462 modheads = exchange.pull(repo, other, heads=nodes,
4438 4463 force=opts.get('force'),
4439 4464 bookmarks=opts.get('bookmark', ()),
4440 4465 opargs=pullopargs).cgresult
4441 4466
4442 4467 # brev is a name, which might be a bookmark to be activated at
4443 4468 # the end of the update. In other words, it is an explicit
4444 4469 # destination of the update
4445 4470 brev = None
4446 4471
4447 4472 if checkout:
4448 4473 checkout = repo.unfiltered().changelog.rev(checkout)
4449 4474
4450 4475 # order below depends on implementation of
4451 4476 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4452 4477 # because 'checkout' is determined without it.
4453 4478 if opts.get('rev'):
4454 4479 brev = opts['rev'][0]
4455 4480 elif opts.get('branch'):
4456 4481 brev = opts['branch'][0]
4457 4482 else:
4458 4483 brev = branches[0]
4459 4484 repo._subtoppath = source
4460 4485 try:
4461 4486 ret = postincoming(ui, repo, modheads, opts.get('update'),
4462 4487 checkout, brev)
4463 4488 except error.FilteredRepoLookupError as exc:
4464 4489 msg = _('cannot update to target: %s') % exc.args[0]
4465 4490 exc.args = (msg,) + exc.args[1:]
4466 4491 raise
4467 4492 finally:
4468 4493 del repo._subtoppath
4469 4494
4470 4495 finally:
4471 4496 other.close()
4472 4497 return ret
4473 4498
4474 4499 @command('push',
4475 4500 [('f', 'force', None, _('force push')),
4476 4501 ('r', 'rev', [],
4477 4502 _('a changeset intended to be included in the destination'),
4478 4503 _('REV')),
4479 4504 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4480 4505 ('b', 'branch', [],
4481 4506 _('a specific branch you would like to push'), _('BRANCH')),
4482 4507 ('', 'new-branch', False, _('allow pushing a new branch')),
4483 4508 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4484 4509 ('', 'publish', False, _('push the changeset as public (EXPERIMENTAL)')),
4485 4510 ] + remoteopts,
4486 4511 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
4487 4512 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4488 4513 helpbasic=True)
4489 4514 def push(ui, repo, dest=None, **opts):
4490 4515 """push changes to the specified destination
4491 4516
4492 4517 Push changesets from the local repository to the specified
4493 4518 destination.
4494 4519
4495 4520 This operation is symmetrical to pull: it is identical to a pull
4496 4521 in the destination repository from the current one.
4497 4522
4498 4523 By default, push will not allow creation of new heads at the
4499 4524 destination, since multiple heads would make it unclear which head
4500 4525 to use. In this situation, it is recommended to pull and merge
4501 4526 before pushing.
4502 4527
4503 4528 Use --new-branch if you want to allow push to create a new named
4504 4529 branch that is not present at the destination. This allows you to
4505 4530 only create a new branch without forcing other changes.
4506 4531
4507 4532 .. note::
4508 4533
4509 4534 Extra care should be taken with the -f/--force option,
4510 4535 which will push all new heads on all branches, an action which will
4511 4536 almost always cause confusion for collaborators.
4512 4537
4513 4538 If -r/--rev is used, the specified revision and all its ancestors
4514 4539 will be pushed to the remote repository.
4515 4540
4516 4541 If -B/--bookmark is used, the specified bookmarked revision, its
4517 4542 ancestors, and the bookmark will be pushed to the remote
4518 4543 repository. Specifying ``.`` is equivalent to specifying the active
4519 4544 bookmark's name.
4520 4545
4521 4546 Please see :hg:`help urls` for important details about ``ssh://``
4522 4547 URLs. If DESTINATION is omitted, a default path will be used.
4523 4548
4524 4549 .. container:: verbose
4525 4550
4526 4551 The --pushvars option sends strings to the server that become
4527 4552 environment variables prepended with ``HG_USERVAR_``. For example,
4528 4553 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4529 4554 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4530 4555
4531 4556 pushvars can provide for user-overridable hooks as well as set debug
4532 4557 levels. One example is having a hook that blocks commits containing
4533 4558 conflict markers, but enables the user to override the hook if the file
4534 4559 is using conflict markers for testing purposes or the file format has
4535 4560 strings that look like conflict markers.
4536 4561
4537 4562 By default, servers will ignore `--pushvars`. To enable it add the
4538 4563 following to your configuration file::
4539 4564
4540 4565 [push]
4541 4566 pushvars.server = true
4542 4567
4543 4568 Returns 0 if push was successful, 1 if nothing to push.
4544 4569 """
4545 4570
4546 4571 opts = pycompat.byteskwargs(opts)
4547 4572 if opts.get('bookmark'):
4548 4573 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4549 4574 for b in opts['bookmark']:
4550 4575 # translate -B options to -r so changesets get pushed
4551 4576 b = repo._bookmarks.expandname(b)
4552 4577 if b in repo._bookmarks:
4553 4578 opts.setdefault('rev', []).append(b)
4554 4579 else:
4555 4580 # if we try to push a deleted bookmark, translate it to null
4556 4581 # this lets simultaneous -r, -b options continue working
4557 4582 opts.setdefault('rev', []).append("null")
4558 4583
4559 4584 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4560 4585 if not path:
4561 4586 raise error.Abort(_('default repository not configured!'),
4562 4587 hint=_("see 'hg help config.paths'"))
4563 4588 dest = path.pushloc or path.loc
4564 4589 branches = (path.branch, opts.get('branch') or [])
4565 4590 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4566 4591 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4567 4592 other = hg.peer(repo, opts, dest)
4568 4593
4569 4594 if revs:
4570 4595 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4571 4596 if not revs:
4572 4597 raise error.Abort(_("specified revisions evaluate to an empty set"),
4573 4598 hint=_("use different revision arguments"))
4574 4599 elif path.pushrev:
4575 4600 # It doesn't make any sense to specify ancestor revisions. So limit
4576 4601 # to DAG heads to make discovery simpler.
4577 4602 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4578 4603 revs = scmutil.revrange(repo, [expr])
4579 4604 revs = [repo[rev].node() for rev in revs]
4580 4605 if not revs:
4581 4606 raise error.Abort(_('default push revset for path evaluates to an '
4582 4607 'empty set'))
4583 4608
4584 4609 repo._subtoppath = dest
4585 4610 try:
4586 4611 # push subrepos depth-first for coherent ordering
4587 4612 c = repo['.']
4588 4613 subs = c.substate # only repos that are committed
4589 4614 for s in sorted(subs):
4590 4615 result = c.sub(s).push(opts)
4591 4616 if result == 0:
4592 4617 return not result
4593 4618 finally:
4594 4619 del repo._subtoppath
4595 4620
4596 4621 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4597 4622 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4598 4623
4599 4624 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4600 4625 newbranch=opts.get('new_branch'),
4601 4626 bookmarks=opts.get('bookmark', ()),
4602 4627 publish=opts.get('publish'),
4603 4628 opargs=opargs)
4604 4629
4605 4630 result = not pushop.cgresult
4606 4631
4607 4632 if pushop.bkresult is not None:
4608 4633 if pushop.bkresult == 2:
4609 4634 result = 2
4610 4635 elif not result and pushop.bkresult:
4611 4636 result = 2
4612 4637
4613 4638 return result
4614 4639
4615 4640 @command('recover',
4616 4641 [('','verify', True, "run `hg verify` after succesful recover"),
4617 4642 ],
4618 4643 helpcategory=command.CATEGORY_MAINTENANCE)
4619 4644 def recover(ui, repo, **opts):
4620 4645 """roll back an interrupted transaction
4621 4646
4622 4647 Recover from an interrupted commit or pull.
4623 4648
4624 4649 This command tries to fix the repository status after an
4625 4650 interrupted operation. It should only be necessary when Mercurial
4626 4651 suggests it.
4627 4652
4628 4653 Returns 0 if successful, 1 if nothing to recover or verify fails.
4629 4654 """
4630 4655 ret = repo.recover()
4631 4656 if ret:
4632 4657 if opts[r'verify']:
4633 4658 return hg.verify(repo)
4634 4659 else:
4635 4660 msg = _("(verify step skipped, run `hg verify` to check your "
4636 4661 "repository content)\n")
4637 4662 ui.warn(msg)
4638 4663 return 0
4639 4664 return 1
4640 4665
4641 4666 @command('remove|rm',
4642 4667 [('A', 'after', None, _('record delete for missing files')),
4643 4668 ('f', 'force', None,
4644 4669 _('forget added files, delete modified files')),
4645 4670 ] + subrepoopts + walkopts + dryrunopts,
4646 4671 _('[OPTION]... FILE...'),
4647 4672 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4648 4673 helpbasic=True, inferrepo=True)
4649 4674 def remove(ui, repo, *pats, **opts):
4650 4675 """remove the specified files on the next commit
4651 4676
4652 4677 Schedule the indicated files for removal from the current branch.
4653 4678
4654 4679 This command schedules the files to be removed at the next commit.
4655 4680 To undo a remove before that, see :hg:`revert`. To undo added
4656 4681 files, see :hg:`forget`.
4657 4682
4658 4683 .. container:: verbose
4659 4684
4660 4685 -A/--after can be used to remove only files that have already
4661 4686 been deleted, -f/--force can be used to force deletion, and -Af
4662 4687 can be used to remove files from the next revision without
4663 4688 deleting them from the working directory.
4664 4689
4665 4690 The following table details the behavior of remove for different
4666 4691 file states (columns) and option combinations (rows). The file
4667 4692 states are Added [A], Clean [C], Modified [M] and Missing [!]
4668 4693 (as reported by :hg:`status`). The actions are Warn, Remove
4669 4694 (from branch) and Delete (from disk):
4670 4695
4671 4696 ========= == == == ==
4672 4697 opt/state A C M !
4673 4698 ========= == == == ==
4674 4699 none W RD W R
4675 4700 -f R RD RD R
4676 4701 -A W W W R
4677 4702 -Af R R R R
4678 4703 ========= == == == ==
4679 4704
4680 4705 .. note::
4681 4706
4682 4707 :hg:`remove` never deletes files in Added [A] state from the
4683 4708 working directory, not even if ``--force`` is specified.
4684 4709
4685 4710 Returns 0 on success, 1 if any warnings encountered.
4686 4711 """
4687 4712
4688 4713 opts = pycompat.byteskwargs(opts)
4689 4714 after, force = opts.get('after'), opts.get('force')
4690 4715 dryrun = opts.get('dry_run')
4691 4716 if not pats and not after:
4692 4717 raise error.Abort(_('no files specified'))
4693 4718
4694 4719 m = scmutil.match(repo[None], pats, opts)
4695 4720 subrepos = opts.get('subrepos')
4696 4721 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
4697 4722 return cmdutil.remove(ui, repo, m, "", uipathfn, after, force, subrepos,
4698 4723 dryrun=dryrun)
4699 4724
4700 4725 @command('rename|move|mv',
4701 4726 [('A', 'after', None, _('record a rename that has already occurred')),
4702 4727 ('f', 'force', None, _('forcibly move over an existing managed file')),
4703 4728 ] + walkopts + dryrunopts,
4704 4729 _('[OPTION]... SOURCE... DEST'),
4705 4730 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
4706 4731 def rename(ui, repo, *pats, **opts):
4707 4732 """rename files; equivalent of copy + remove
4708 4733
4709 4734 Mark dest as copies of sources; mark sources for deletion. If dest
4710 4735 is a directory, copies are put in that directory. If dest is a
4711 4736 file, there can only be one source.
4712 4737
4713 4738 By default, this command copies the contents of files as they
4714 4739 exist in the working directory. If invoked with -A/--after, the
4715 4740 operation is recorded, but no copying is performed.
4716 4741
4717 4742 This command takes effect at the next commit. To undo a rename
4718 4743 before that, see :hg:`revert`.
4719 4744
4720 4745 Returns 0 on success, 1 if errors are encountered.
4721 4746 """
4722 4747 opts = pycompat.byteskwargs(opts)
4723 4748 with repo.wlock(False):
4724 4749 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4725 4750
4726 4751 @command('resolve',
4727 4752 [('a', 'all', None, _('select all unresolved files')),
4728 4753 ('l', 'list', None, _('list state of files needing merge')),
4729 4754 ('m', 'mark', None, _('mark files as resolved')),
4730 4755 ('u', 'unmark', None, _('mark files as unresolved')),
4731 4756 ('n', 'no-status', None, _('hide status prefix')),
4732 4757 ('', 're-merge', None, _('re-merge files'))]
4733 4758 + mergetoolopts + walkopts + formatteropts,
4734 4759 _('[OPTION]... [FILE]...'),
4735 4760 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4736 4761 inferrepo=True)
4737 4762 def resolve(ui, repo, *pats, **opts):
4738 4763 """redo merges or set/view the merge status of files
4739 4764
4740 4765 Merges with unresolved conflicts are often the result of
4741 4766 non-interactive merging using the ``internal:merge`` configuration
4742 4767 setting, or a command-line merge tool like ``diff3``. The resolve
4743 4768 command is used to manage the files involved in a merge, after
4744 4769 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4745 4770 working directory must have two parents). See :hg:`help
4746 4771 merge-tools` for information on configuring merge tools.
4747 4772
4748 4773 The resolve command can be used in the following ways:
4749 4774
4750 4775 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4751 4776 the specified files, discarding any previous merge attempts. Re-merging
4752 4777 is not performed for files already marked as resolved. Use ``--all/-a``
4753 4778 to select all unresolved files. ``--tool`` can be used to specify
4754 4779 the merge tool used for the given files. It overrides the HGMERGE
4755 4780 environment variable and your configuration files. Previous file
4756 4781 contents are saved with a ``.orig`` suffix.
4757 4782
4758 4783 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4759 4784 (e.g. after having manually fixed-up the files). The default is
4760 4785 to mark all unresolved files.
4761 4786
4762 4787 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4763 4788 default is to mark all resolved files.
4764 4789
4765 4790 - :hg:`resolve -l`: list files which had or still have conflicts.
4766 4791 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4767 4792 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4768 4793 the list. See :hg:`help filesets` for details.
4769 4794
4770 4795 .. note::
4771 4796
4772 4797 Mercurial will not let you commit files with unresolved merge
4773 4798 conflicts. You must use :hg:`resolve -m ...` before you can
4774 4799 commit after a conflicting merge.
4775 4800
4776 4801 .. container:: verbose
4777 4802
4778 4803 Template:
4779 4804
4780 4805 The following keywords are supported in addition to the common template
4781 4806 keywords and functions. See also :hg:`help templates`.
4782 4807
4783 4808 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
4784 4809 :path: String. Repository-absolute path of the file.
4785 4810
4786 4811 Returns 0 on success, 1 if any files fail a resolve attempt.
4787 4812 """
4788 4813
4789 4814 opts = pycompat.byteskwargs(opts)
4790 4815 confirm = ui.configbool('commands', 'resolve.confirm')
4791 4816 flaglist = 'all mark unmark list no_status re_merge'.split()
4792 4817 all, mark, unmark, show, nostatus, remerge = [
4793 4818 opts.get(o) for o in flaglist]
4794 4819
4795 4820 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4796 4821 if actioncount > 1:
4797 4822 raise error.Abort(_("too many actions specified"))
4798 4823 elif (actioncount == 0
4799 4824 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4800 4825 hint = _('use --mark, --unmark, --list or --re-merge')
4801 4826 raise error.Abort(_('no action specified'), hint=hint)
4802 4827 if pats and all:
4803 4828 raise error.Abort(_("can't specify --all and patterns"))
4804 4829 if not (all or pats or show or mark or unmark):
4805 4830 raise error.Abort(_('no files or directories specified'),
4806 4831 hint=('use --all to re-merge all unresolved files'))
4807 4832
4808 4833 if confirm:
4809 4834 if all:
4810 4835 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4811 4836 b'$$ &Yes $$ &No')):
4812 4837 raise error.Abort(_('user quit'))
4813 4838 if mark and not pats:
4814 4839 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4815 4840 b'$$ &Yes $$ &No')):
4816 4841 raise error.Abort(_('user quit'))
4817 4842 if unmark and not pats:
4818 4843 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4819 4844 b'$$ &Yes $$ &No')):
4820 4845 raise error.Abort(_('user quit'))
4821 4846
4822 4847 uipathfn = scmutil.getuipathfn(repo)
4823 4848
4824 4849 if show:
4825 4850 ui.pager('resolve')
4826 4851 fm = ui.formatter('resolve', opts)
4827 4852 ms = mergemod.mergestate.read(repo)
4828 4853 wctx = repo[None]
4829 4854 m = scmutil.match(wctx, pats, opts)
4830 4855
4831 4856 # Labels and keys based on merge state. Unresolved path conflicts show
4832 4857 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4833 4858 # resolved conflicts.
4834 4859 mergestateinfo = {
4835 4860 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4836 4861 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4837 4862 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4838 4863 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4839 4864 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4840 4865 'D'),
4841 4866 }
4842 4867
4843 4868 for f in ms:
4844 4869 if not m(f):
4845 4870 continue
4846 4871
4847 4872 label, key = mergestateinfo[ms[f]]
4848 4873 fm.startitem()
4849 4874 fm.context(ctx=wctx)
4850 4875 fm.condwrite(not nostatus, 'mergestatus', '%s ', key, label=label)
4851 4876 fm.data(path=f)
4852 4877 fm.plain('%s\n' % uipathfn(f), label=label)
4853 4878 fm.end()
4854 4879 return 0
4855 4880
4856 4881 with repo.wlock():
4857 4882 ms = mergemod.mergestate.read(repo)
4858 4883
4859 4884 if not (ms.active() or repo.dirstate.p2() != nullid):
4860 4885 raise error.Abort(
4861 4886 _('resolve command not applicable when not merging'))
4862 4887
4863 4888 wctx = repo[None]
4864 4889
4865 4890 if (ms.mergedriver
4866 4891 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4867 4892 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4868 4893 ms.commit()
4869 4894 # allow mark and unmark to go through
4870 4895 if not mark and not unmark and not proceed:
4871 4896 return 1
4872 4897
4873 4898 m = scmutil.match(wctx, pats, opts)
4874 4899 ret = 0
4875 4900 didwork = False
4876 4901 runconclude = False
4877 4902
4878 4903 tocomplete = []
4879 4904 hasconflictmarkers = []
4880 4905 if mark:
4881 4906 markcheck = ui.config('commands', 'resolve.mark-check')
4882 4907 if markcheck not in ['warn', 'abort']:
4883 4908 # Treat all invalid / unrecognized values as 'none'.
4884 4909 markcheck = False
4885 4910 for f in ms:
4886 4911 if not m(f):
4887 4912 continue
4888 4913
4889 4914 didwork = True
4890 4915
4891 4916 # don't let driver-resolved files be marked, and run the conclude
4892 4917 # step if asked to resolve
4893 4918 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4894 4919 exact = m.exact(f)
4895 4920 if mark:
4896 4921 if exact:
4897 4922 ui.warn(_('not marking %s as it is driver-resolved\n')
4898 4923 % uipathfn(f))
4899 4924 elif unmark:
4900 4925 if exact:
4901 4926 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4902 4927 % uipathfn(f))
4903 4928 else:
4904 4929 runconclude = True
4905 4930 continue
4906 4931
4907 4932 # path conflicts must be resolved manually
4908 4933 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4909 4934 mergemod.MERGE_RECORD_RESOLVED_PATH):
4910 4935 if mark:
4911 4936 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4912 4937 elif unmark:
4913 4938 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4914 4939 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4915 4940 ui.warn(_('%s: path conflict must be resolved manually\n')
4916 4941 % uipathfn(f))
4917 4942 continue
4918 4943
4919 4944 if mark:
4920 4945 if markcheck:
4921 4946 fdata = repo.wvfs.tryread(f)
4922 4947 if (filemerge.hasconflictmarkers(fdata) and
4923 4948 ms[f] != mergemod.MERGE_RECORD_RESOLVED):
4924 4949 hasconflictmarkers.append(f)
4925 4950 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4926 4951 elif unmark:
4927 4952 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4928 4953 else:
4929 4954 # backup pre-resolve (merge uses .orig for its own purposes)
4930 4955 a = repo.wjoin(f)
4931 4956 try:
4932 4957 util.copyfile(a, a + ".resolve")
4933 4958 except (IOError, OSError) as inst:
4934 4959 if inst.errno != errno.ENOENT:
4935 4960 raise
4936 4961
4937 4962 try:
4938 4963 # preresolve file
4939 4964 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4940 4965 with ui.configoverride(overrides, 'resolve'):
4941 4966 complete, r = ms.preresolve(f, wctx)
4942 4967 if not complete:
4943 4968 tocomplete.append(f)
4944 4969 elif r:
4945 4970 ret = 1
4946 4971 finally:
4947 4972 ms.commit()
4948 4973
4949 4974 # replace filemerge's .orig file with our resolve file, but only
4950 4975 # for merges that are complete
4951 4976 if complete:
4952 4977 try:
4953 4978 util.rename(a + ".resolve",
4954 4979 scmutil.backuppath(ui, repo, f))
4955 4980 except OSError as inst:
4956 4981 if inst.errno != errno.ENOENT:
4957 4982 raise
4958 4983
4959 4984 if hasconflictmarkers:
4960 4985 ui.warn(_('warning: the following files still have conflict '
4961 4986 'markers:\n') + ''.join(' ' + uipathfn(f) + '\n'
4962 4987 for f in hasconflictmarkers))
4963 4988 if markcheck == 'abort' and not all and not pats:
4964 4989 raise error.Abort(_('conflict markers detected'),
4965 4990 hint=_('use --all to mark anyway'))
4966 4991
4967 4992 for f in tocomplete:
4968 4993 try:
4969 4994 # resolve file
4970 4995 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4971 4996 with ui.configoverride(overrides, 'resolve'):
4972 4997 r = ms.resolve(f, wctx)
4973 4998 if r:
4974 4999 ret = 1
4975 5000 finally:
4976 5001 ms.commit()
4977 5002
4978 5003 # replace filemerge's .orig file with our resolve file
4979 5004 a = repo.wjoin(f)
4980 5005 try:
4981 5006 util.rename(a + ".resolve", scmutil.backuppath(ui, repo, f))
4982 5007 except OSError as inst:
4983 5008 if inst.errno != errno.ENOENT:
4984 5009 raise
4985 5010
4986 5011 ms.commit()
4987 5012 ms.recordactions()
4988 5013
4989 5014 if not didwork and pats:
4990 5015 hint = None
4991 5016 if not any([p for p in pats if p.find(':') >= 0]):
4992 5017 pats = ['path:%s' % p for p in pats]
4993 5018 m = scmutil.match(wctx, pats, opts)
4994 5019 for f in ms:
4995 5020 if not m(f):
4996 5021 continue
4997 5022 def flag(o):
4998 5023 if o == 're_merge':
4999 5024 return '--re-merge '
5000 5025 return '-%s ' % o[0:1]
5001 5026 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
5002 5027 hint = _("(try: hg resolve %s%s)\n") % (
5003 5028 flags,
5004 5029 ' '.join(pats))
5005 5030 break
5006 5031 ui.warn(_("arguments do not match paths that need resolving\n"))
5007 5032 if hint:
5008 5033 ui.warn(hint)
5009 5034 elif ms.mergedriver and ms.mdstate() != 's':
5010 5035 # run conclude step when either a driver-resolved file is requested
5011 5036 # or there are no driver-resolved files
5012 5037 # we can't use 'ret' to determine whether any files are unresolved
5013 5038 # because we might not have tried to resolve some
5014 5039 if ((runconclude or not list(ms.driverresolved()))
5015 5040 and not list(ms.unresolved())):
5016 5041 proceed = mergemod.driverconclude(repo, ms, wctx)
5017 5042 ms.commit()
5018 5043 if not proceed:
5019 5044 return 1
5020 5045
5021 5046 # Nudge users into finishing an unfinished operation
5022 5047 unresolvedf = list(ms.unresolved())
5023 5048 driverresolvedf = list(ms.driverresolved())
5024 5049 if not unresolvedf and not driverresolvedf:
5025 5050 ui.status(_('(no more unresolved files)\n'))
5026 5051 cmdutil.checkafterresolved(repo)
5027 5052 elif not unresolvedf:
5028 5053 ui.status(_('(no more unresolved files -- '
5029 5054 'run "hg resolve --all" to conclude)\n'))
5030 5055
5031 5056 return ret
5032 5057
5033 5058 @command('revert',
5034 5059 [('a', 'all', None, _('revert all changes when no arguments given')),
5035 5060 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5036 5061 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5037 5062 ('C', 'no-backup', None, _('do not save backup copies of files')),
5038 5063 ('i', 'interactive', None, _('interactively select the changes')),
5039 5064 ] + walkopts + dryrunopts,
5040 5065 _('[OPTION]... [-r REV] [NAME]...'),
5041 5066 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5042 5067 def revert(ui, repo, *pats, **opts):
5043 5068 """restore files to their checkout state
5044 5069
5045 5070 .. note::
5046 5071
5047 5072 To check out earlier revisions, you should use :hg:`update REV`.
5048 5073 To cancel an uncommitted merge (and lose your changes),
5049 5074 use :hg:`merge --abort`.
5050 5075
5051 5076 With no revision specified, revert the specified files or directories
5052 5077 to the contents they had in the parent of the working directory.
5053 5078 This restores the contents of files to an unmodified
5054 5079 state and unschedules adds, removes, copies, and renames. If the
5055 5080 working directory has two parents, you must explicitly specify a
5056 5081 revision.
5057 5082
5058 5083 Using the -r/--rev or -d/--date options, revert the given files or
5059 5084 directories to their states as of a specific revision. Because
5060 5085 revert does not change the working directory parents, this will
5061 5086 cause these files to appear modified. This can be helpful to "back
5062 5087 out" some or all of an earlier change. See :hg:`backout` for a
5063 5088 related method.
5064 5089
5065 5090 Modified files are saved with a .orig suffix before reverting.
5066 5091 To disable these backups, use --no-backup. It is possible to store
5067 5092 the backup files in a custom directory relative to the root of the
5068 5093 repository by setting the ``ui.origbackuppath`` configuration
5069 5094 option.
5070 5095
5071 5096 See :hg:`help dates` for a list of formats valid for -d/--date.
5072 5097
5073 5098 See :hg:`help backout` for a way to reverse the effect of an
5074 5099 earlier changeset.
5075 5100
5076 5101 Returns 0 on success.
5077 5102 """
5078 5103
5079 5104 opts = pycompat.byteskwargs(opts)
5080 5105 if opts.get("date"):
5081 5106 if opts.get("rev"):
5082 5107 raise error.Abort(_("you can't specify a revision and a date"))
5083 5108 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5084 5109
5085 5110 parent, p2 = repo.dirstate.parents()
5086 5111 if not opts.get('rev') and p2 != nullid:
5087 5112 # revert after merge is a trap for new users (issue2915)
5088 5113 raise error.Abort(_('uncommitted merge with no revision specified'),
5089 5114 hint=_("use 'hg update' or see 'hg help revert'"))
5090 5115
5091 5116 rev = opts.get('rev')
5092 5117 if rev:
5093 5118 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5094 5119 ctx = scmutil.revsingle(repo, rev)
5095 5120
5096 5121 if (not (pats or opts.get('include') or opts.get('exclude') or
5097 5122 opts.get('all') or opts.get('interactive'))):
5098 5123 msg = _("no files or directories specified")
5099 5124 if p2 != nullid:
5100 5125 hint = _("uncommitted merge, use --all to discard all changes,"
5101 5126 " or 'hg update -C .' to abort the merge")
5102 5127 raise error.Abort(msg, hint=hint)
5103 5128 dirty = any(repo.status())
5104 5129 node = ctx.node()
5105 5130 if node != parent:
5106 5131 if dirty:
5107 5132 hint = _("uncommitted changes, use --all to discard all"
5108 5133 " changes, or 'hg update %d' to update") % ctx.rev()
5109 5134 else:
5110 5135 hint = _("use --all to revert all files,"
5111 5136 " or 'hg update %d' to update") % ctx.rev()
5112 5137 elif dirty:
5113 5138 hint = _("uncommitted changes, use --all to discard all changes")
5114 5139 else:
5115 5140 hint = _("use --all to revert all files")
5116 5141 raise error.Abort(msg, hint=hint)
5117 5142
5118 5143 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
5119 5144 **pycompat.strkwargs(opts))
5120 5145
5121 5146 @command(
5122 5147 'rollback',
5123 5148 dryrunopts + [('f', 'force', False, _('ignore safety measures'))],
5124 5149 helpcategory=command.CATEGORY_MAINTENANCE)
5125 5150 def rollback(ui, repo, **opts):
5126 5151 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5127 5152
5128 5153 Please use :hg:`commit --amend` instead of rollback to correct
5129 5154 mistakes in the last commit.
5130 5155
5131 5156 This command should be used with care. There is only one level of
5132 5157 rollback, and there is no way to undo a rollback. It will also
5133 5158 restore the dirstate at the time of the last transaction, losing
5134 5159 any dirstate changes since that time. This command does not alter
5135 5160 the working directory.
5136 5161
5137 5162 Transactions are used to encapsulate the effects of all commands
5138 5163 that create new changesets or propagate existing changesets into a
5139 5164 repository.
5140 5165
5141 5166 .. container:: verbose
5142 5167
5143 5168 For example, the following commands are transactional, and their
5144 5169 effects can be rolled back:
5145 5170
5146 5171 - commit
5147 5172 - import
5148 5173 - pull
5149 5174 - push (with this repository as the destination)
5150 5175 - unbundle
5151 5176
5152 5177 To avoid permanent data loss, rollback will refuse to rollback a
5153 5178 commit transaction if it isn't checked out. Use --force to
5154 5179 override this protection.
5155 5180
5156 5181 The rollback command can be entirely disabled by setting the
5157 5182 ``ui.rollback`` configuration setting to false. If you're here
5158 5183 because you want to use rollback and it's disabled, you can
5159 5184 re-enable the command by setting ``ui.rollback`` to true.
5160 5185
5161 5186 This command is not intended for use on public repositories. Once
5162 5187 changes are visible for pull by other users, rolling a transaction
5163 5188 back locally is ineffective (someone else may already have pulled
5164 5189 the changes). Furthermore, a race is possible with readers of the
5165 5190 repository; for example an in-progress pull from the repository
5166 5191 may fail if a rollback is performed.
5167 5192
5168 5193 Returns 0 on success, 1 if no rollback data is available.
5169 5194 """
5170 5195 if not ui.configbool('ui', 'rollback'):
5171 5196 raise error.Abort(_('rollback is disabled because it is unsafe'),
5172 5197 hint=('see `hg help -v rollback` for information'))
5173 5198 return repo.rollback(dryrun=opts.get(r'dry_run'),
5174 5199 force=opts.get(r'force'))
5175 5200
5176 5201 @command(
5177 5202 'root', [] + formatteropts, intents={INTENT_READONLY},
5178 5203 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5179 5204 def root(ui, repo, **opts):
5180 5205 """print the root (top) of the current working directory
5181 5206
5182 5207 Print the root directory of the current repository.
5183 5208
5184 5209 .. container:: verbose
5185 5210
5186 5211 Template:
5187 5212
5188 5213 The following keywords are supported in addition to the common template
5189 5214 keywords and functions. See also :hg:`help templates`.
5190 5215
5191 5216 :hgpath: String. Path to the .hg directory.
5192 5217 :storepath: String. Path to the directory holding versioned data.
5193 5218
5194 5219 Returns 0 on success.
5195 5220 """
5196 5221 opts = pycompat.byteskwargs(opts)
5197 5222 with ui.formatter('root', opts) as fm:
5198 5223 fm.startitem()
5199 5224 fm.write('reporoot', '%s\n', repo.root)
5200 5225 fm.data(hgpath=repo.path, storepath=repo.spath)
5201 5226
5202 5227 @command('serve',
5203 5228 [('A', 'accesslog', '', _('name of access log file to write to'),
5204 5229 _('FILE')),
5205 5230 ('d', 'daemon', None, _('run server in background')),
5206 5231 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
5207 5232 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5208 5233 # use string type, then we can check if something was passed
5209 5234 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5210 5235 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5211 5236 _('ADDR')),
5212 5237 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5213 5238 _('PREFIX')),
5214 5239 ('n', 'name', '',
5215 5240 _('name to show in web pages (default: working directory)'), _('NAME')),
5216 5241 ('', 'web-conf', '',
5217 5242 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
5218 5243 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5219 5244 _('FILE')),
5220 5245 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5221 5246 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
5222 5247 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
5223 5248 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5224 5249 ('', 'style', '', _('template style to use'), _('STYLE')),
5225 5250 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5226 5251 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
5227 5252 ('', 'print-url', None, _('start and print only the URL'))]
5228 5253 + subrepoopts,
5229 5254 _('[OPTION]...'),
5230 5255 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5231 5256 helpbasic=True, optionalrepo=True)
5232 5257 def serve(ui, repo, **opts):
5233 5258 """start stand-alone webserver
5234 5259
5235 5260 Start a local HTTP repository browser and pull server. You can use
5236 5261 this for ad-hoc sharing and browsing of repositories. It is
5237 5262 recommended to use a real web server to serve a repository for
5238 5263 longer periods of time.
5239 5264
5240 5265 Please note that the server does not implement access control.
5241 5266 This means that, by default, anybody can read from the server and
5242 5267 nobody can write to it by default. Set the ``web.allow-push``
5243 5268 option to ``*`` to allow everybody to push to the server. You
5244 5269 should use a real web server if you need to authenticate users.
5245 5270
5246 5271 By default, the server logs accesses to stdout and errors to
5247 5272 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5248 5273 files.
5249 5274
5250 5275 To have the server choose a free port number to listen on, specify
5251 5276 a port number of 0; in this case, the server will print the port
5252 5277 number it uses.
5253 5278
5254 5279 Returns 0 on success.
5255 5280 """
5256 5281
5257 5282 opts = pycompat.byteskwargs(opts)
5258 5283 if opts["stdio"] and opts["cmdserver"]:
5259 5284 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5260 5285 if opts["print_url"] and ui.verbose:
5261 5286 raise error.Abort(_("cannot use --print-url with --verbose"))
5262 5287
5263 5288 if opts["stdio"]:
5264 5289 if repo is None:
5265 5290 raise error.RepoError(_("there is no Mercurial repository here"
5266 5291 " (.hg not found)"))
5267 5292 s = wireprotoserver.sshserver(ui, repo)
5268 5293 s.serve_forever()
5269 5294
5270 5295 service = server.createservice(ui, repo, opts)
5271 5296 return server.runservice(opts, initfn=service.init, runfn=service.run)
5272 5297
5273 5298 @command('shelve',
5274 5299 [('A', 'addremove', None,
5275 5300 _('mark new/missing files as added/removed before shelving')),
5276 5301 ('u', 'unknown', None,
5277 5302 _('store unknown files in the shelve')),
5278 5303 ('', 'cleanup', None,
5279 5304 _('delete all shelved changes')),
5280 5305 ('', 'date', '',
5281 5306 _('shelve with the specified commit date'), _('DATE')),
5282 5307 ('d', 'delete', None,
5283 5308 _('delete the named shelved change(s)')),
5284 5309 ('e', 'edit', False,
5285 5310 _('invoke editor on commit messages')),
5286 5311 ('k', 'keep', False,
5287 5312 _('shelve, but keep changes in the working directory')),
5288 5313 ('l', 'list', None,
5289 5314 _('list current shelves')),
5290 5315 ('m', 'message', '',
5291 5316 _('use text as shelve message'), _('TEXT')),
5292 5317 ('n', 'name', '',
5293 5318 _('use the given name for the shelved commit'), _('NAME')),
5294 5319 ('p', 'patch', None,
5295 5320 _('output patches for changes (provide the names of the shelved '
5296 5321 'changes as positional arguments)')),
5297 5322 ('i', 'interactive', None,
5298 5323 _('interactive mode, only works while creating a shelve')),
5299 5324 ('', 'stat', None,
5300 5325 _('output diffstat-style summary of changes (provide the names of '
5301 5326 'the shelved changes as positional arguments)')
5302 5327 )] + cmdutil.walkopts,
5303 5328 _('hg shelve [OPTION]... [FILE]...'),
5304 5329 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5305 5330 def shelve(ui, repo, *pats, **opts):
5306 5331 '''save and set aside changes from the working directory
5307 5332
5308 5333 Shelving takes files that "hg status" reports as not clean, saves
5309 5334 the modifications to a bundle (a shelved change), and reverts the
5310 5335 files so that their state in the working directory becomes clean.
5311 5336
5312 5337 To restore these changes to the working directory, using "hg
5313 5338 unshelve"; this will work even if you switch to a different
5314 5339 commit.
5315 5340
5316 5341 When no files are specified, "hg shelve" saves all not-clean
5317 5342 files. If specific files or directories are named, only changes to
5318 5343 those files are shelved.
5319 5344
5320 5345 In bare shelve (when no files are specified, without interactive,
5321 5346 include and exclude option), shelving remembers information if the
5322 5347 working directory was on newly created branch, in other words working
5323 5348 directory was on different branch than its first parent. In this
5324 5349 situation unshelving restores branch information to the working directory.
5325 5350
5326 5351 Each shelved change has a name that makes it easier to find later.
5327 5352 The name of a shelved change defaults to being based on the active
5328 5353 bookmark, or if there is no active bookmark, the current named
5329 5354 branch. To specify a different name, use ``--name``.
5330 5355
5331 5356 To see a list of existing shelved changes, use the ``--list``
5332 5357 option. For each shelved change, this will print its name, age,
5333 5358 and description; use ``--patch`` or ``--stat`` for more details.
5334 5359
5335 5360 To delete specific shelved changes, use ``--delete``. To delete
5336 5361 all shelved changes, use ``--cleanup``.
5337 5362 '''
5338 5363 opts = pycompat.byteskwargs(opts)
5339 5364 allowables = [
5340 5365 ('addremove', {'create'}), # 'create' is pseudo action
5341 5366 ('unknown', {'create'}),
5342 5367 ('cleanup', {'cleanup'}),
5343 5368 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
5344 5369 ('delete', {'delete'}),
5345 5370 ('edit', {'create'}),
5346 5371 ('keep', {'create'}),
5347 5372 ('list', {'list'}),
5348 5373 ('message', {'create'}),
5349 5374 ('name', {'create'}),
5350 5375 ('patch', {'patch', 'list'}),
5351 5376 ('stat', {'stat', 'list'}),
5352 5377 ]
5353 5378 def checkopt(opt):
5354 5379 if opts.get(opt):
5355 5380 for i, allowable in allowables:
5356 5381 if opts[i] and opt not in allowable:
5357 5382 raise error.Abort(_("options '--%s' and '--%s' may not be "
5358 5383 "used together") % (opt, i))
5359 5384 return True
5360 5385 if checkopt('cleanup'):
5361 5386 if pats:
5362 5387 raise error.Abort(_("cannot specify names when using '--cleanup'"))
5363 5388 return shelvemod.cleanupcmd(ui, repo)
5364 5389 elif checkopt('delete'):
5365 5390 return shelvemod.deletecmd(ui, repo, pats)
5366 5391 elif checkopt('list'):
5367 5392 return shelvemod.listcmd(ui, repo, pats, opts)
5368 5393 elif checkopt('patch') or checkopt('stat'):
5369 5394 return shelvemod.patchcmds(ui, repo, pats, opts)
5370 5395 else:
5371 5396 return shelvemod.createcmd(ui, repo, pats, opts)
5372 5397
5373 5398 _NOTTERSE = 'nothing'
5374 5399
5375 5400 @command('status|st',
5376 5401 [('A', 'all', None, _('show status of all files')),
5377 5402 ('m', 'modified', None, _('show only modified files')),
5378 5403 ('a', 'added', None, _('show only added files')),
5379 5404 ('r', 'removed', None, _('show only removed files')),
5380 5405 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5381 5406 ('c', 'clean', None, _('show only files without changes')),
5382 5407 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5383 5408 ('i', 'ignored', None, _('show only ignored files')),
5384 5409 ('n', 'no-status', None, _('hide status prefix')),
5385 5410 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5386 5411 ('C', 'copies', None, _('show source of copied files')),
5387 5412 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5388 5413 ('', 'rev', [], _('show difference from revision'), _('REV')),
5389 5414 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5390 5415 ] + walkopts + subrepoopts + formatteropts,
5391 5416 _('[OPTION]... [FILE]...'),
5392 5417 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5393 5418 helpbasic=True, inferrepo=True,
5394 5419 intents={INTENT_READONLY})
5395 5420 def status(ui, repo, *pats, **opts):
5396 5421 """show changed files in the working directory
5397 5422
5398 5423 Show status of files in the repository. If names are given, only
5399 5424 files that match are shown. Files that are clean or ignored or
5400 5425 the source of a copy/move operation, are not listed unless
5401 5426 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5402 5427 Unless options described with "show only ..." are given, the
5403 5428 options -mardu are used.
5404 5429
5405 5430 Option -q/--quiet hides untracked (unknown and ignored) files
5406 5431 unless explicitly requested with -u/--unknown or -i/--ignored.
5407 5432
5408 5433 .. note::
5409 5434
5410 5435 :hg:`status` may appear to disagree with diff if permissions have
5411 5436 changed or a merge has occurred. The standard diff format does
5412 5437 not report permission changes and diff only reports changes
5413 5438 relative to one merge parent.
5414 5439
5415 5440 If one revision is given, it is used as the base revision.
5416 5441 If two revisions are given, the differences between them are
5417 5442 shown. The --change option can also be used as a shortcut to list
5418 5443 the changed files of a revision from its first parent.
5419 5444
5420 5445 The codes used to show the status of files are::
5421 5446
5422 5447 M = modified
5423 5448 A = added
5424 5449 R = removed
5425 5450 C = clean
5426 5451 ! = missing (deleted by non-hg command, but still tracked)
5427 5452 ? = not tracked
5428 5453 I = ignored
5429 5454 = origin of the previous file (with --copies)
5430 5455
5431 5456 .. container:: verbose
5432 5457
5433 5458 The -t/--terse option abbreviates the output by showing only the directory
5434 5459 name if all the files in it share the same status. The option takes an
5435 5460 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5436 5461 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5437 5462 for 'ignored' and 'c' for clean.
5438 5463
5439 5464 It abbreviates only those statuses which are passed. Note that clean and
5440 5465 ignored files are not displayed with '--terse ic' unless the -c/--clean
5441 5466 and -i/--ignored options are also used.
5442 5467
5443 5468 The -v/--verbose option shows information when the repository is in an
5444 5469 unfinished merge, shelve, rebase state etc. You can have this behavior
5445 5470 turned on by default by enabling the ``commands.status.verbose`` option.
5446 5471
5447 5472 You can skip displaying some of these states by setting
5448 5473 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5449 5474 'histedit', 'merge', 'rebase', or 'unshelve'.
5450 5475
5451 5476 Template:
5452 5477
5453 5478 The following keywords are supported in addition to the common template
5454 5479 keywords and functions. See also :hg:`help templates`.
5455 5480
5456 5481 :path: String. Repository-absolute path of the file.
5457 5482 :source: String. Repository-absolute path of the file originated from.
5458 5483 Available if ``--copies`` is specified.
5459 5484 :status: String. Character denoting file's status.
5460 5485
5461 5486 Examples:
5462 5487
5463 5488 - show changes in the working directory relative to a
5464 5489 changeset::
5465 5490
5466 5491 hg status --rev 9353
5467 5492
5468 5493 - show changes in the working directory relative to the
5469 5494 current directory (see :hg:`help patterns` for more information)::
5470 5495
5471 5496 hg status re:
5472 5497
5473 5498 - show all changes including copies in an existing changeset::
5474 5499
5475 5500 hg status --copies --change 9353
5476 5501
5477 5502 - get a NUL separated list of added files, suitable for xargs::
5478 5503
5479 5504 hg status -an0
5480 5505
5481 5506 - show more information about the repository status, abbreviating
5482 5507 added, removed, modified, deleted, and untracked paths::
5483 5508
5484 5509 hg status -v -t mardu
5485 5510
5486 5511 Returns 0 on success.
5487 5512
5488 5513 """
5489 5514
5490 5515 opts = pycompat.byteskwargs(opts)
5491 5516 revs = opts.get('rev')
5492 5517 change = opts.get('change')
5493 5518 terse = opts.get('terse')
5494 5519 if terse is _NOTTERSE:
5495 5520 if revs:
5496 5521 terse = ''
5497 5522 else:
5498 5523 terse = ui.config('commands', 'status.terse')
5499 5524
5500 5525 if revs and change:
5501 5526 msg = _('cannot specify --rev and --change at the same time')
5502 5527 raise error.Abort(msg)
5503 5528 elif revs and terse:
5504 5529 msg = _('cannot use --terse with --rev')
5505 5530 raise error.Abort(msg)
5506 5531 elif change:
5507 5532 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5508 5533 ctx2 = scmutil.revsingle(repo, change, None)
5509 5534 ctx1 = ctx2.p1()
5510 5535 else:
5511 5536 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5512 5537 ctx1, ctx2 = scmutil.revpair(repo, revs)
5513 5538
5514 5539 forcerelativevalue = None
5515 5540 if ui.hasconfig('commands', 'status.relative'):
5516 5541 forcerelativevalue = ui.configbool('commands', 'status.relative')
5517 5542 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats),
5518 5543 forcerelativevalue=forcerelativevalue)
5519 5544
5520 5545 if opts.get('print0'):
5521 5546 end = '\0'
5522 5547 else:
5523 5548 end = '\n'
5524 5549 copy = {}
5525 5550 states = 'modified added removed deleted unknown ignored clean'.split()
5526 5551 show = [k for k in states if opts.get(k)]
5527 5552 if opts.get('all'):
5528 5553 show += ui.quiet and (states[:4] + ['clean']) or states
5529 5554
5530 5555 if not show:
5531 5556 if ui.quiet:
5532 5557 show = states[:4]
5533 5558 else:
5534 5559 show = states[:5]
5535 5560
5536 5561 m = scmutil.match(ctx2, pats, opts)
5537 5562 if terse:
5538 5563 # we need to compute clean and unknown to terse
5539 5564 stat = repo.status(ctx1.node(), ctx2.node(), m,
5540 5565 'ignored' in show or 'i' in terse,
5541 5566 clean=True, unknown=True,
5542 5567 listsubrepos=opts.get('subrepos'))
5543 5568
5544 5569 stat = cmdutil.tersedir(stat, terse)
5545 5570 else:
5546 5571 stat = repo.status(ctx1.node(), ctx2.node(), m,
5547 5572 'ignored' in show, 'clean' in show,
5548 5573 'unknown' in show, opts.get('subrepos'))
5549 5574
5550 5575 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5551 5576
5552 5577 if (opts.get('all') or opts.get('copies')
5553 5578 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5554 5579 copy = copies.pathcopies(ctx1, ctx2, m)
5555 5580
5556 5581 ui.pager('status')
5557 5582 fm = ui.formatter('status', opts)
5558 5583 fmt = '%s' + end
5559 5584 showchar = not opts.get('no_status')
5560 5585
5561 5586 for state, char, files in changestates:
5562 5587 if state in show:
5563 5588 label = 'status.' + state
5564 5589 for f in files:
5565 5590 fm.startitem()
5566 5591 fm.context(ctx=ctx2)
5567 5592 fm.data(path=f)
5568 5593 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5569 5594 fm.plain(fmt % uipathfn(f), label=label)
5570 5595 if f in copy:
5571 5596 fm.data(source=copy[f])
5572 5597 fm.plain((' %s' + end) % uipathfn(copy[f]),
5573 5598 label='status.copied')
5574 5599
5575 5600 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5576 5601 and not ui.plain()):
5577 5602 cmdutil.morestatus(repo, fm)
5578 5603 fm.end()
5579 5604
5580 5605 @command('summary|sum',
5581 5606 [('', 'remote', None, _('check for push and pull'))],
5582 5607 '[--remote]',
5583 5608 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5584 5609 helpbasic=True,
5585 5610 intents={INTENT_READONLY})
5586 5611 def summary(ui, repo, **opts):
5587 5612 """summarize working directory state
5588 5613
5589 5614 This generates a brief summary of the working directory state,
5590 5615 including parents, branch, commit status, phase and available updates.
5591 5616
5592 5617 With the --remote option, this will check the default paths for
5593 5618 incoming and outgoing changes. This can be time-consuming.
5594 5619
5595 5620 Returns 0 on success.
5596 5621 """
5597 5622
5598 5623 opts = pycompat.byteskwargs(opts)
5599 5624 ui.pager('summary')
5600 5625 ctx = repo[None]
5601 5626 parents = ctx.parents()
5602 5627 pnode = parents[0].node()
5603 5628 marks = []
5604 5629
5605 5630 try:
5606 5631 ms = mergemod.mergestate.read(repo)
5607 5632 except error.UnsupportedMergeRecords as e:
5608 5633 s = ' '.join(e.recordtypes)
5609 5634 ui.warn(
5610 5635 _('warning: merge state has unsupported record types: %s\n') % s)
5611 5636 unresolved = []
5612 5637 else:
5613 5638 unresolved = list(ms.unresolved())
5614 5639
5615 5640 for p in parents:
5616 5641 # label with log.changeset (instead of log.parent) since this
5617 5642 # shows a working directory parent *changeset*:
5618 5643 # i18n: column positioning for "hg summary"
5619 5644 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5620 5645 label=logcmdutil.changesetlabels(p))
5621 5646 ui.write(' '.join(p.tags()), label='log.tag')
5622 5647 if p.bookmarks():
5623 5648 marks.extend(p.bookmarks())
5624 5649 if p.rev() == -1:
5625 5650 if not len(repo):
5626 5651 ui.write(_(' (empty repository)'))
5627 5652 else:
5628 5653 ui.write(_(' (no revision checked out)'))
5629 5654 if p.obsolete():
5630 5655 ui.write(_(' (obsolete)'))
5631 5656 if p.isunstable():
5632 5657 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5633 5658 for instability in p.instabilities())
5634 5659 ui.write(' ('
5635 5660 + ', '.join(instabilities)
5636 5661 + ')')
5637 5662 ui.write('\n')
5638 5663 if p.description():
5639 5664 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5640 5665 label='log.summary')
5641 5666
5642 5667 branch = ctx.branch()
5643 5668 bheads = repo.branchheads(branch)
5644 5669 # i18n: column positioning for "hg summary"
5645 5670 m = _('branch: %s\n') % branch
5646 5671 if branch != 'default':
5647 5672 ui.write(m, label='log.branch')
5648 5673 else:
5649 5674 ui.status(m, label='log.branch')
5650 5675
5651 5676 if marks:
5652 5677 active = repo._activebookmark
5653 5678 # i18n: column positioning for "hg summary"
5654 5679 ui.write(_('bookmarks:'), label='log.bookmark')
5655 5680 if active is not None:
5656 5681 if active in marks:
5657 5682 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5658 5683 marks.remove(active)
5659 5684 else:
5660 5685 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5661 5686 for m in marks:
5662 5687 ui.write(' ' + m, label='log.bookmark')
5663 5688 ui.write('\n', label='log.bookmark')
5664 5689
5665 5690 status = repo.status(unknown=True)
5666 5691
5667 5692 c = repo.dirstate.copies()
5668 5693 copied, renamed = [], []
5669 5694 for d, s in c.iteritems():
5670 5695 if s in status.removed:
5671 5696 status.removed.remove(s)
5672 5697 renamed.append(d)
5673 5698 else:
5674 5699 copied.append(d)
5675 5700 if d in status.added:
5676 5701 status.added.remove(d)
5677 5702
5678 5703 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5679 5704
5680 5705 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5681 5706 (ui.label(_('%d added'), 'status.added'), status.added),
5682 5707 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5683 5708 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5684 5709 (ui.label(_('%d copied'), 'status.copied'), copied),
5685 5710 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5686 5711 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5687 5712 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5688 5713 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5689 5714 t = []
5690 5715 for l, s in labels:
5691 5716 if s:
5692 5717 t.append(l % len(s))
5693 5718
5694 5719 t = ', '.join(t)
5695 5720 cleanworkdir = False
5696 5721
5697 5722 if repo.vfs.exists('graftstate'):
5698 5723 t += _(' (graft in progress)')
5699 5724 if repo.vfs.exists('updatestate'):
5700 5725 t += _(' (interrupted update)')
5701 5726 elif len(parents) > 1:
5702 5727 t += _(' (merge)')
5703 5728 elif branch != parents[0].branch():
5704 5729 t += _(' (new branch)')
5705 5730 elif (parents[0].closesbranch() and
5706 5731 pnode in repo.branchheads(branch, closed=True)):
5707 5732 t += _(' (head closed)')
5708 5733 elif not (status.modified or status.added or status.removed or renamed or
5709 5734 copied or subs):
5710 5735 t += _(' (clean)')
5711 5736 cleanworkdir = True
5712 5737 elif pnode not in bheads:
5713 5738 t += _(' (new branch head)')
5714 5739
5715 5740 if parents:
5716 5741 pendingphase = max(p.phase() for p in parents)
5717 5742 else:
5718 5743 pendingphase = phases.public
5719 5744
5720 5745 if pendingphase > phases.newcommitphase(ui):
5721 5746 t += ' (%s)' % phases.phasenames[pendingphase]
5722 5747
5723 5748 if cleanworkdir:
5724 5749 # i18n: column positioning for "hg summary"
5725 5750 ui.status(_('commit: %s\n') % t.strip())
5726 5751 else:
5727 5752 # i18n: column positioning for "hg summary"
5728 5753 ui.write(_('commit: %s\n') % t.strip())
5729 5754
5730 5755 # all ancestors of branch heads - all ancestors of parent = new csets
5731 5756 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5732 5757 bheads))
5733 5758
5734 5759 if new == 0:
5735 5760 # i18n: column positioning for "hg summary"
5736 5761 ui.status(_('update: (current)\n'))
5737 5762 elif pnode not in bheads:
5738 5763 # i18n: column positioning for "hg summary"
5739 5764 ui.write(_('update: %d new changesets (update)\n') % new)
5740 5765 else:
5741 5766 # i18n: column positioning for "hg summary"
5742 5767 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5743 5768 (new, len(bheads)))
5744 5769
5745 5770 t = []
5746 5771 draft = len(repo.revs('draft()'))
5747 5772 if draft:
5748 5773 t.append(_('%d draft') % draft)
5749 5774 secret = len(repo.revs('secret()'))
5750 5775 if secret:
5751 5776 t.append(_('%d secret') % secret)
5752 5777
5753 5778 if draft or secret:
5754 5779 ui.status(_('phases: %s\n') % ', '.join(t))
5755 5780
5756 5781 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5757 5782 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5758 5783 numtrouble = len(repo.revs(trouble + "()"))
5759 5784 # We write all the possibilities to ease translation
5760 5785 troublemsg = {
5761 5786 "orphan": _("orphan: %d changesets"),
5762 5787 "contentdivergent": _("content-divergent: %d changesets"),
5763 5788 "phasedivergent": _("phase-divergent: %d changesets"),
5764 5789 }
5765 5790 if numtrouble > 0:
5766 5791 ui.status(troublemsg[trouble] % numtrouble + "\n")
5767 5792
5768 5793 cmdutil.summaryhooks(ui, repo)
5769 5794
5770 5795 if opts.get('remote'):
5771 5796 needsincoming, needsoutgoing = True, True
5772 5797 else:
5773 5798 needsincoming, needsoutgoing = False, False
5774 5799 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5775 5800 if i:
5776 5801 needsincoming = True
5777 5802 if o:
5778 5803 needsoutgoing = True
5779 5804 if not needsincoming and not needsoutgoing:
5780 5805 return
5781 5806
5782 5807 def getincoming():
5783 5808 source, branches = hg.parseurl(ui.expandpath('default'))
5784 5809 sbranch = branches[0]
5785 5810 try:
5786 5811 other = hg.peer(repo, {}, source)
5787 5812 except error.RepoError:
5788 5813 if opts.get('remote'):
5789 5814 raise
5790 5815 return source, sbranch, None, None, None
5791 5816 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5792 5817 if revs:
5793 5818 revs = [other.lookup(rev) for rev in revs]
5794 5819 ui.debug('comparing with %s\n' % util.hidepassword(source))
5795 5820 repo.ui.pushbuffer()
5796 5821 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5797 5822 repo.ui.popbuffer()
5798 5823 return source, sbranch, other, commoninc, commoninc[1]
5799 5824
5800 5825 if needsincoming:
5801 5826 source, sbranch, sother, commoninc, incoming = getincoming()
5802 5827 else:
5803 5828 source = sbranch = sother = commoninc = incoming = None
5804 5829
5805 5830 def getoutgoing():
5806 5831 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5807 5832 dbranch = branches[0]
5808 5833 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5809 5834 if source != dest:
5810 5835 try:
5811 5836 dother = hg.peer(repo, {}, dest)
5812 5837 except error.RepoError:
5813 5838 if opts.get('remote'):
5814 5839 raise
5815 5840 return dest, dbranch, None, None
5816 5841 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5817 5842 elif sother is None:
5818 5843 # there is no explicit destination peer, but source one is invalid
5819 5844 return dest, dbranch, None, None
5820 5845 else:
5821 5846 dother = sother
5822 5847 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5823 5848 common = None
5824 5849 else:
5825 5850 common = commoninc
5826 5851 if revs:
5827 5852 revs = [repo.lookup(rev) for rev in revs]
5828 5853 repo.ui.pushbuffer()
5829 5854 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5830 5855 commoninc=common)
5831 5856 repo.ui.popbuffer()
5832 5857 return dest, dbranch, dother, outgoing
5833 5858
5834 5859 if needsoutgoing:
5835 5860 dest, dbranch, dother, outgoing = getoutgoing()
5836 5861 else:
5837 5862 dest = dbranch = dother = outgoing = None
5838 5863
5839 5864 if opts.get('remote'):
5840 5865 t = []
5841 5866 if incoming:
5842 5867 t.append(_('1 or more incoming'))
5843 5868 o = outgoing.missing
5844 5869 if o:
5845 5870 t.append(_('%d outgoing') % len(o))
5846 5871 other = dother or sother
5847 5872 if 'bookmarks' in other.listkeys('namespaces'):
5848 5873 counts = bookmarks.summary(repo, other)
5849 5874 if counts[0] > 0:
5850 5875 t.append(_('%d incoming bookmarks') % counts[0])
5851 5876 if counts[1] > 0:
5852 5877 t.append(_('%d outgoing bookmarks') % counts[1])
5853 5878
5854 5879 if t:
5855 5880 # i18n: column positioning for "hg summary"
5856 5881 ui.write(_('remote: %s\n') % (', '.join(t)))
5857 5882 else:
5858 5883 # i18n: column positioning for "hg summary"
5859 5884 ui.status(_('remote: (synced)\n'))
5860 5885
5861 5886 cmdutil.summaryremotehooks(ui, repo, opts,
5862 5887 ((source, sbranch, sother, commoninc),
5863 5888 (dest, dbranch, dother, outgoing)))
5864 5889
5865 5890 @command('tag',
5866 5891 [('f', 'force', None, _('force tag')),
5867 5892 ('l', 'local', None, _('make the tag local')),
5868 5893 ('r', 'rev', '', _('revision to tag'), _('REV')),
5869 5894 ('', 'remove', None, _('remove a tag')),
5870 5895 # -l/--local is already there, commitopts cannot be used
5871 5896 ('e', 'edit', None, _('invoke editor on commit messages')),
5872 5897 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5873 5898 ] + commitopts2,
5874 5899 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
5875 5900 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
5876 5901 def tag(ui, repo, name1, *names, **opts):
5877 5902 """add one or more tags for the current or given revision
5878 5903
5879 5904 Name a particular revision using <name>.
5880 5905
5881 5906 Tags are used to name particular revisions of the repository and are
5882 5907 very useful to compare different revisions, to go back to significant
5883 5908 earlier versions or to mark branch points as releases, etc. Changing
5884 5909 an existing tag is normally disallowed; use -f/--force to override.
5885 5910
5886 5911 If no revision is given, the parent of the working directory is
5887 5912 used.
5888 5913
5889 5914 To facilitate version control, distribution, and merging of tags,
5890 5915 they are stored as a file named ".hgtags" which is managed similarly
5891 5916 to other project files and can be hand-edited if necessary. This
5892 5917 also means that tagging creates a new commit. The file
5893 5918 ".hg/localtags" is used for local tags (not shared among
5894 5919 repositories).
5895 5920
5896 5921 Tag commits are usually made at the head of a branch. If the parent
5897 5922 of the working directory is not a branch head, :hg:`tag` aborts; use
5898 5923 -f/--force to force the tag commit to be based on a non-head
5899 5924 changeset.
5900 5925
5901 5926 See :hg:`help dates` for a list of formats valid for -d/--date.
5902 5927
5903 5928 Since tag names have priority over branch names during revision
5904 5929 lookup, using an existing branch name as a tag name is discouraged.
5905 5930
5906 5931 Returns 0 on success.
5907 5932 """
5908 5933 opts = pycompat.byteskwargs(opts)
5909 5934 with repo.wlock(), repo.lock():
5910 5935 rev_ = "."
5911 5936 names = [t.strip() for t in (name1,) + names]
5912 5937 if len(names) != len(set(names)):
5913 5938 raise error.Abort(_('tag names must be unique'))
5914 5939 for n in names:
5915 5940 scmutil.checknewlabel(repo, n, 'tag')
5916 5941 if not n:
5917 5942 raise error.Abort(_('tag names cannot consist entirely of '
5918 5943 'whitespace'))
5919 5944 if opts.get('rev') and opts.get('remove'):
5920 5945 raise error.Abort(_("--rev and --remove are incompatible"))
5921 5946 if opts.get('rev'):
5922 5947 rev_ = opts['rev']
5923 5948 message = opts.get('message')
5924 5949 if opts.get('remove'):
5925 5950 if opts.get('local'):
5926 5951 expectedtype = 'local'
5927 5952 else:
5928 5953 expectedtype = 'global'
5929 5954
5930 5955 for n in names:
5931 5956 if repo.tagtype(n) == 'global':
5932 5957 alltags = tagsmod.findglobaltags(ui, repo)
5933 5958 if alltags[n][0] == nullid:
5934 5959 raise error.Abort(_("tag '%s' is already removed") % n)
5935 5960 if not repo.tagtype(n):
5936 5961 raise error.Abort(_("tag '%s' does not exist") % n)
5937 5962 if repo.tagtype(n) != expectedtype:
5938 5963 if expectedtype == 'global':
5939 5964 raise error.Abort(_("tag '%s' is not a global tag") % n)
5940 5965 else:
5941 5966 raise error.Abort(_("tag '%s' is not a local tag") % n)
5942 5967 rev_ = 'null'
5943 5968 if not message:
5944 5969 # we don't translate commit messages
5945 5970 message = 'Removed tag %s' % ', '.join(names)
5946 5971 elif not opts.get('force'):
5947 5972 for n in names:
5948 5973 if n in repo.tags():
5949 5974 raise error.Abort(_("tag '%s' already exists "
5950 5975 "(use -f to force)") % n)
5951 5976 if not opts.get('local'):
5952 5977 p1, p2 = repo.dirstate.parents()
5953 5978 if p2 != nullid:
5954 5979 raise error.Abort(_('uncommitted merge'))
5955 5980 bheads = repo.branchheads()
5956 5981 if not opts.get('force') and bheads and p1 not in bheads:
5957 5982 raise error.Abort(_('working directory is not at a branch head '
5958 5983 '(use -f to force)'))
5959 5984 node = scmutil.revsingle(repo, rev_).node()
5960 5985
5961 5986 if not message:
5962 5987 # we don't translate commit messages
5963 5988 message = ('Added tag %s for changeset %s' %
5964 5989 (', '.join(names), short(node)))
5965 5990
5966 5991 date = opts.get('date')
5967 5992 if date:
5968 5993 date = dateutil.parsedate(date)
5969 5994
5970 5995 if opts.get('remove'):
5971 5996 editform = 'tag.remove'
5972 5997 else:
5973 5998 editform = 'tag.add'
5974 5999 editor = cmdutil.getcommiteditor(editform=editform,
5975 6000 **pycompat.strkwargs(opts))
5976 6001
5977 6002 # don't allow tagging the null rev
5978 6003 if (not opts.get('remove') and
5979 6004 scmutil.revsingle(repo, rev_).rev() == nullrev):
5980 6005 raise error.Abort(_("cannot tag null revision"))
5981 6006
5982 6007 tagsmod.tag(repo, names, node, message, opts.get('local'),
5983 6008 opts.get('user'), date, editor=editor)
5984 6009
5985 6010 @command(
5986 6011 'tags', formatteropts, '',
5987 6012 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5988 6013 intents={INTENT_READONLY})
5989 6014 def tags(ui, repo, **opts):
5990 6015 """list repository tags
5991 6016
5992 6017 This lists both regular and local tags. When the -v/--verbose
5993 6018 switch is used, a third column "local" is printed for local tags.
5994 6019 When the -q/--quiet switch is used, only the tag name is printed.
5995 6020
5996 6021 .. container:: verbose
5997 6022
5998 6023 Template:
5999 6024
6000 6025 The following keywords are supported in addition to the common template
6001 6026 keywords and functions such as ``{tag}``. See also
6002 6027 :hg:`help templates`.
6003 6028
6004 6029 :type: String. ``local`` for local tags.
6005 6030
6006 6031 Returns 0 on success.
6007 6032 """
6008 6033
6009 6034 opts = pycompat.byteskwargs(opts)
6010 6035 ui.pager('tags')
6011 6036 fm = ui.formatter('tags', opts)
6012 6037 hexfunc = fm.hexfunc
6013 6038
6014 6039 for t, n in reversed(repo.tagslist()):
6015 6040 hn = hexfunc(n)
6016 6041 label = 'tags.normal'
6017 6042 tagtype = ''
6018 6043 if repo.tagtype(t) == 'local':
6019 6044 label = 'tags.local'
6020 6045 tagtype = 'local'
6021 6046
6022 6047 fm.startitem()
6023 6048 fm.context(repo=repo)
6024 6049 fm.write('tag', '%s', t, label=label)
6025 6050 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6026 6051 fm.condwrite(not ui.quiet, 'rev node', fmt,
6027 6052 repo.changelog.rev(n), hn, label=label)
6028 6053 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6029 6054 tagtype, label=label)
6030 6055 fm.plain('\n')
6031 6056 fm.end()
6032 6057
6033 6058 @command('tip',
6034 6059 [('p', 'patch', None, _('show patch')),
6035 6060 ('g', 'git', None, _('use git extended diff format')),
6036 6061 ] + templateopts,
6037 6062 _('[-p] [-g]'),
6038 6063 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
6039 6064 def tip(ui, repo, **opts):
6040 6065 """show the tip revision (DEPRECATED)
6041 6066
6042 6067 The tip revision (usually just called the tip) is the changeset
6043 6068 most recently added to the repository (and therefore the most
6044 6069 recently changed head).
6045 6070
6046 6071 If you have just made a commit, that commit will be the tip. If
6047 6072 you have just pulled changes from another repository, the tip of
6048 6073 that repository becomes the current tip. The "tip" tag is special
6049 6074 and cannot be renamed or assigned to a different changeset.
6050 6075
6051 6076 This command is deprecated, please use :hg:`heads` instead.
6052 6077
6053 6078 Returns 0 on success.
6054 6079 """
6055 6080 opts = pycompat.byteskwargs(opts)
6056 6081 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
6057 6082 displayer.show(repo['tip'])
6058 6083 displayer.close()
6059 6084
6060 6085 @command('unbundle',
6061 6086 [('u', 'update', None,
6062 6087 _('update to new branch head if changesets were unbundled'))],
6063 6088 _('[-u] FILE...'),
6064 6089 helpcategory=command.CATEGORY_IMPORT_EXPORT)
6065 6090 def unbundle(ui, repo, fname1, *fnames, **opts):
6066 6091 """apply one or more bundle files
6067 6092
6068 6093 Apply one or more bundle files generated by :hg:`bundle`.
6069 6094
6070 6095 Returns 0 on success, 1 if an update has unresolved files.
6071 6096 """
6072 6097 fnames = (fname1,) + fnames
6073 6098
6074 6099 with repo.lock():
6075 6100 for fname in fnames:
6076 6101 f = hg.openpath(ui, fname)
6077 6102 gen = exchange.readbundle(ui, f, fname)
6078 6103 if isinstance(gen, streamclone.streamcloneapplier):
6079 6104 raise error.Abort(
6080 6105 _('packed bundles cannot be applied with '
6081 6106 '"hg unbundle"'),
6082 6107 hint=_('use "hg debugapplystreamclonebundle"'))
6083 6108 url = 'bundle:' + fname
6084 6109 try:
6085 6110 txnname = 'unbundle'
6086 6111 if not isinstance(gen, bundle2.unbundle20):
6087 6112 txnname = 'unbundle\n%s' % util.hidepassword(url)
6088 6113 with repo.transaction(txnname) as tr:
6089 6114 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6090 6115 url=url)
6091 6116 except error.BundleUnknownFeatureError as exc:
6092 6117 raise error.Abort(
6093 6118 _('%s: unknown bundle feature, %s') % (fname, exc),
6094 6119 hint=_("see https://mercurial-scm.org/"
6095 6120 "wiki/BundleFeature for more "
6096 6121 "information"))
6097 6122 modheads = bundle2.combinechangegroupresults(op)
6098 6123
6099 6124 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
6100 6125
6101 6126 @command('unshelve',
6102 6127 [('a', 'abort', None,
6103 6128 _('abort an incomplete unshelve operation')),
6104 6129 ('c', 'continue', None,
6105 6130 _('continue an incomplete unshelve operation')),
6106 6131 ('k', 'keep', None,
6107 6132 _('keep shelve after unshelving')),
6108 6133 ('n', 'name', '',
6109 6134 _('restore shelved change with given name'), _('NAME')),
6110 6135 ('t', 'tool', '', _('specify merge tool')),
6111 6136 ('', 'date', '',
6112 6137 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
6113 6138 _('hg unshelve [[-n] SHELVED]'),
6114 6139 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
6115 6140 def unshelve(ui, repo, *shelved, **opts):
6116 6141 """restore a shelved change to the working directory
6117 6142
6118 6143 This command accepts an optional name of a shelved change to
6119 6144 restore. If none is given, the most recent shelved change is used.
6120 6145
6121 6146 If a shelved change is applied successfully, the bundle that
6122 6147 contains the shelved changes is moved to a backup location
6123 6148 (.hg/shelve-backup).
6124 6149
6125 6150 Since you can restore a shelved change on top of an arbitrary
6126 6151 commit, it is possible that unshelving will result in a conflict
6127 6152 between your changes and the commits you are unshelving onto. If
6128 6153 this occurs, you must resolve the conflict, then use
6129 6154 ``--continue`` to complete the unshelve operation. (The bundle
6130 6155 will not be moved until you successfully complete the unshelve.)
6131 6156
6132 6157 (Alternatively, you can use ``--abort`` to abandon an unshelve
6133 6158 that causes a conflict. This reverts the unshelved changes, and
6134 6159 leaves the bundle in place.)
6135 6160
6136 6161 If bare shelved change (when no files are specified, without interactive,
6137 6162 include and exclude option) was done on newly created branch it would
6138 6163 restore branch information to the working directory.
6139 6164
6140 6165 After a successful unshelve, the shelved changes are stored in a
6141 6166 backup directory. Only the N most recent backups are kept. N
6142 6167 defaults to 10 but can be overridden using the ``shelve.maxbackups``
6143 6168 configuration option.
6144 6169
6145 6170 .. container:: verbose
6146 6171
6147 6172 Timestamp in seconds is used to decide order of backups. More
6148 6173 than ``maxbackups`` backups are kept, if same timestamp
6149 6174 prevents from deciding exact order of them, for safety.
6150 6175 """
6151 6176 with repo.wlock():
6152 6177 return shelvemod.dounshelve(ui, repo, *shelved, **opts)
6153 6178
6154 6179 @command('update|up|checkout|co',
6155 6180 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6156 6181 ('c', 'check', None, _('require clean working directory')),
6157 6182 ('m', 'merge', None, _('merge uncommitted changes')),
6158 6183 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6159 6184 ('r', 'rev', '', _('revision'), _('REV'))
6160 6185 ] + mergetoolopts,
6161 6186 _('[-C|-c|-m] [-d DATE] [[-r] REV]'),
6162 6187 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6163 6188 helpbasic=True)
6164 6189 def update(ui, repo, node=None, **opts):
6165 6190 """update working directory (or switch revisions)
6166 6191
6167 6192 Update the repository's working directory to the specified
6168 6193 changeset. If no changeset is specified, update to the tip of the
6169 6194 current named branch and move the active bookmark (see :hg:`help
6170 6195 bookmarks`).
6171 6196
6172 6197 Update sets the working directory's parent revision to the specified
6173 6198 changeset (see :hg:`help parents`).
6174 6199
6175 6200 If the changeset is not a descendant or ancestor of the working
6176 6201 directory's parent and there are uncommitted changes, the update is
6177 6202 aborted. With the -c/--check option, the working directory is checked
6178 6203 for uncommitted changes; if none are found, the working directory is
6179 6204 updated to the specified changeset.
6180 6205
6181 6206 .. container:: verbose
6182 6207
6183 6208 The -C/--clean, -c/--check, and -m/--merge options control what
6184 6209 happens if the working directory contains uncommitted changes.
6185 6210 At most of one of them can be specified.
6186 6211
6187 6212 1. If no option is specified, and if
6188 6213 the requested changeset is an ancestor or descendant of
6189 6214 the working directory's parent, the uncommitted changes
6190 6215 are merged into the requested changeset and the merged
6191 6216 result is left uncommitted. If the requested changeset is
6192 6217 not an ancestor or descendant (that is, it is on another
6193 6218 branch), the update is aborted and the uncommitted changes
6194 6219 are preserved.
6195 6220
6196 6221 2. With the -m/--merge option, the update is allowed even if the
6197 6222 requested changeset is not an ancestor or descendant of
6198 6223 the working directory's parent.
6199 6224
6200 6225 3. With the -c/--check option, the update is aborted and the
6201 6226 uncommitted changes are preserved.
6202 6227
6203 6228 4. With the -C/--clean option, uncommitted changes are discarded and
6204 6229 the working directory is updated to the requested changeset.
6205 6230
6206 6231 To cancel an uncommitted merge (and lose your changes), use
6207 6232 :hg:`merge --abort`.
6208 6233
6209 6234 Use null as the changeset to remove the working directory (like
6210 6235 :hg:`clone -U`).
6211 6236
6212 6237 If you want to revert just one file to an older revision, use
6213 6238 :hg:`revert [-r REV] NAME`.
6214 6239
6215 6240 See :hg:`help dates` for a list of formats valid for -d/--date.
6216 6241
6217 6242 Returns 0 on success, 1 if there are unresolved files.
6218 6243 """
6219 6244 rev = opts.get(r'rev')
6220 6245 date = opts.get(r'date')
6221 6246 clean = opts.get(r'clean')
6222 6247 check = opts.get(r'check')
6223 6248 merge = opts.get(r'merge')
6224 6249 if rev and node:
6225 6250 raise error.Abort(_("please specify just one revision"))
6226 6251
6227 6252 if ui.configbool('commands', 'update.requiredest'):
6228 6253 if not node and not rev and not date:
6229 6254 raise error.Abort(_('you must specify a destination'),
6230 6255 hint=_('for example: hg update ".::"'))
6231 6256
6232 6257 if rev is None or rev == '':
6233 6258 rev = node
6234 6259
6235 6260 if date and rev is not None:
6236 6261 raise error.Abort(_("you can't specify a revision and a date"))
6237 6262
6238 6263 if len([x for x in (clean, check, merge) if x]) > 1:
6239 6264 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
6240 6265 "or -m/--merge"))
6241 6266
6242 6267 updatecheck = None
6243 6268 if check:
6244 6269 updatecheck = 'abort'
6245 6270 elif merge:
6246 6271 updatecheck = 'none'
6247 6272
6248 6273 with repo.wlock():
6249 6274 cmdutil.clearunfinished(repo)
6250 6275 if date:
6251 6276 rev = cmdutil.finddate(ui, repo, date)
6252 6277
6253 6278 # if we defined a bookmark, we have to remember the original name
6254 6279 brev = rev
6255 6280 if rev:
6256 6281 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
6257 6282 ctx = scmutil.revsingle(repo, rev, default=None)
6258 6283 rev = ctx.rev()
6259 6284 hidden = ctx.hidden()
6260 6285 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
6261 6286 with ui.configoverride(overrides, 'update'):
6262 6287 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
6263 6288 updatecheck=updatecheck)
6264 6289 if hidden:
6265 6290 ctxstr = ctx.hex()[:12]
6266 6291 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
6267 6292
6268 6293 if ctx.obsolete():
6269 6294 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
6270 6295 ui.warn("(%s)\n" % obsfatemsg)
6271 6296 return ret
6272 6297
6273 6298 @command('verify',
6274 6299 [('', 'full', False, 'perform more checks (EXPERIMENTAL)')],
6275 6300 helpcategory=command.CATEGORY_MAINTENANCE)
6276 6301 def verify(ui, repo, **opts):
6277 6302 """verify the integrity of the repository
6278 6303
6279 6304 Verify the integrity of the current repository.
6280 6305
6281 6306 This will perform an extensive check of the repository's
6282 6307 integrity, validating the hashes and checksums of each entry in
6283 6308 the changelog, manifest, and tracked files, as well as the
6284 6309 integrity of their crosslinks and indices.
6285 6310
6286 6311 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6287 6312 for more information about recovery from corruption of the
6288 6313 repository.
6289 6314
6290 6315 Returns 0 on success, 1 if errors are encountered.
6291 6316 """
6292 6317 opts = pycompat.byteskwargs(opts)
6293 6318
6294 6319 level = None
6295 6320 if opts['full']:
6296 6321 level = verifymod.VERIFY_FULL
6297 6322 return hg.verify(repo, level)
6298 6323
6299 6324 @command(
6300 6325 'version', [] + formatteropts, helpcategory=command.CATEGORY_HELP,
6301 6326 norepo=True, intents={INTENT_READONLY})
6302 6327 def version_(ui, **opts):
6303 6328 """output version and copyright information
6304 6329
6305 6330 .. container:: verbose
6306 6331
6307 6332 Template:
6308 6333
6309 6334 The following keywords are supported. See also :hg:`help templates`.
6310 6335
6311 6336 :extensions: List of extensions.
6312 6337 :ver: String. Version number.
6313 6338
6314 6339 And each entry of ``{extensions}`` provides the following sub-keywords
6315 6340 in addition to ``{ver}``.
6316 6341
6317 6342 :bundled: Boolean. True if included in the release.
6318 6343 :name: String. Extension name.
6319 6344 """
6320 6345 opts = pycompat.byteskwargs(opts)
6321 6346 if ui.verbose:
6322 6347 ui.pager('version')
6323 6348 fm = ui.formatter("version", opts)
6324 6349 fm.startitem()
6325 6350 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6326 6351 util.version())
6327 6352 license = _(
6328 6353 "(see https://mercurial-scm.org for more information)\n"
6329 6354 "\nCopyright (C) 2005-2019 Matt Mackall and others\n"
6330 6355 "This is free software; see the source for copying conditions. "
6331 6356 "There is NO\nwarranty; "
6332 6357 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6333 6358 )
6334 6359 if not ui.quiet:
6335 6360 fm.plain(license)
6336 6361
6337 6362 if ui.verbose:
6338 6363 fm.plain(_("\nEnabled extensions:\n\n"))
6339 6364 # format names and versions into columns
6340 6365 names = []
6341 6366 vers = []
6342 6367 isinternals = []
6343 6368 for name, module in extensions.extensions():
6344 6369 names.append(name)
6345 6370 vers.append(extensions.moduleversion(module) or None)
6346 6371 isinternals.append(extensions.ismoduleinternal(module))
6347 6372 fn = fm.nested("extensions", tmpl='{name}\n')
6348 6373 if names:
6349 6374 namefmt = " %%-%ds " % max(len(n) for n in names)
6350 6375 places = [_("external"), _("internal")]
6351 6376 for n, v, p in zip(names, vers, isinternals):
6352 6377 fn.startitem()
6353 6378 fn.condwrite(ui.verbose, "name", namefmt, n)
6354 6379 if ui.verbose:
6355 6380 fn.plain("%s " % places[p])
6356 6381 fn.data(bundled=p)
6357 6382 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6358 6383 if ui.verbose:
6359 6384 fn.plain("\n")
6360 6385 fn.end()
6361 6386 fm.end()
6362 6387
6363 6388 def loadcmdtable(ui, name, cmdtable):
6364 6389 """Load command functions from specified cmdtable
6365 6390 """
6366 6391 overrides = [cmd for cmd in cmdtable if cmd in table]
6367 6392 if overrides:
6368 6393 ui.warn(_("extension '%s' overrides commands: %s\n")
6369 6394 % (name, " ".join(overrides)))
6370 6395 table.update(cmdtable)
@@ -1,229 +1,232 b''
1 1 # state.py - writing and reading state files in Mercurial
2 2 #
3 3 # Copyright 2018 Pulkit Goyal <pulkitmgoyal@gmail.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 """
9 9 This file contains class to wrap the state for commands and other
10 10 related logic.
11 11
12 12 All the data related to the command state is stored as dictionary in the object.
13 13 The class has methods using which the data can be stored to disk in a file under
14 14 .hg/ directory.
15 15
16 16 We store the data on disk in cbor, for which we use the CBOR format to encode
17 17 the data.
18 18 """
19 19
20 20 from __future__ import absolute_import
21 21
22 22 from .i18n import _
23 23
24 24 from . import (
25 25 error,
26 26 util,
27 27 )
28 28 from .utils import (
29 29 cborutil,
30 30 )
31 31
32 32 class cmdstate(object):
33 33 """a wrapper class to store the state of commands like `rebase`, `graft`,
34 34 `histedit`, `shelve` etc. Extensions can also use this to write state files.
35 35
36 36 All the data for the state is stored in the form of key-value pairs in a
37 37 dictionary.
38 38
39 39 The class object can write all the data to a file in .hg/ directory and
40 40 can populate the object data reading that file.
41 41
42 42 Uses cbor to serialize and deserialize data while writing and reading from
43 43 disk.
44 44 """
45 45
46 46 def __init__(self, repo, fname):
47 47 """ repo is the repo object
48 48 fname is the file name in which data should be stored in .hg directory
49 49 """
50 50 self._repo = repo
51 51 self.fname = fname
52 52
53 53 def read(self):
54 54 """read the existing state file and return a dict of data stored"""
55 55 return self._read()
56 56
57 57 def save(self, version, data):
58 58 """write all the state data stored to .hg/<filename> file
59 59
60 60 we use third-party library cbor to serialize data to write in the file.
61 61 """
62 62 if not isinstance(version, int):
63 63 raise error.ProgrammingError("version of state file should be"
64 64 " an integer")
65 65
66 66 with self._repo.vfs(self.fname, 'wb', atomictemp=True) as fp:
67 67 fp.write('%d\n' % version)
68 68 for chunk in cborutil.streamencode(data):
69 69 fp.write(chunk)
70 70
71 71 def _read(self):
72 72 """reads the state file and returns a dictionary which contain
73 73 data in the same format as it was before storing"""
74 74 with self._repo.vfs(self.fname, 'rb') as fp:
75 75 try:
76 76 int(fp.readline())
77 77 except ValueError:
78 78 raise error.CorruptedState("unknown version of state file"
79 79 " found")
80 80
81 81 return cborutil.decodeall(fp.read())[0]
82 82
83 83 def delete(self):
84 84 """drop the state file if exists"""
85 85 util.unlinkpath(self._repo.vfs.join(self.fname), ignoremissing=True)
86 86
87 87 def exists(self):
88 88 """check whether the state file exists or not"""
89 89 return self._repo.vfs.exists(self.fname)
90 90
91 91 class _statecheck(object):
92 92 """a utility class that deals with multistep operations like graft,
93 93 histedit, bisect, update etc and check whether such commands
94 94 are in an unfinished conditition or not and return appropriate message
95 95 and hint.
96 96 It also has the ability to register and determine the states of any new
97 97 multistep operation or multistep command extension.
98 98 """
99 99
100 100 def __init__(self, opname, fname, clearable, allowcommit, reportonly,
101 continueflag, stopflag, cmdmsg, cmdhint, statushint):
101 continueflag, stopflag, cmdmsg, cmdhint, statushint,
102 abortfunc):
102 103 self._opname = opname
103 104 self._fname = fname
104 105 self._clearable = clearable
105 106 self._allowcommit = allowcommit
106 107 self._reportonly = reportonly
107 108 self._continueflag = continueflag
108 109 self._stopflag = stopflag
109 110 self._cmdmsg = cmdmsg
110 111 self._cmdhint = cmdhint
111 112 self._statushint = statushint
113 self.abortfunc = abortfunc
112 114
113 115 def statusmsg(self):
114 116 """returns the hint message corresponding to the command for
115 117 hg status --verbose
116 118 """
117 119 if not self._statushint:
118 120 hint = (_('To continue: hg %s --continue\n'
119 121 'To abort: hg %s --abort') % (self._opname,
120 122 self._opname))
121 123 if self._stopflag:
122 124 hint = hint + (_('\nTo stop: hg %s --stop') %
123 125 (self._opname))
124 126 return hint
125 127 return self._statushint
126 128
127 129 def hint(self):
128 130 """returns the hint message corresponding to an interrupted
129 131 operation
130 132 """
131 133 if not self._cmdhint:
132 134 return (_("use 'hg %s --continue' or 'hg %s --abort'") %
133 135 (self._opname, self._opname))
134 136 return self._cmdhint
135 137
136 138 def msg(self):
137 139 """returns the status message corresponding to the command"""
138 140 if not self._cmdmsg:
139 141 return _('%s in progress') % (self._opname)
140 142 return self._cmdmsg
141 143
142 144 def continuemsg(self):
143 145 """ returns appropriate continue message corresponding to command"""
144 146 return _('hg %s --continue') % (self._opname)
145 147
146 148 def isunfinished(self, repo):
147 149 """determines whether a multi-step operation is in progress
148 150 or not
149 151 """
150 152 if self._opname == 'merge':
151 153 return len(repo[None].parents()) > 1
152 154 else:
153 155 return repo.vfs.exists(self._fname)
154 156
155 157 # A list of statecheck objects for multistep operations like graft.
156 158 _unfinishedstates = []
157 159
158 160 def addunfinished(opname, fname, clearable=False, allowcommit=False,
159 161 reportonly=False, continueflag=False, stopflag=False,
160 cmdmsg="", cmdhint="", statushint=""):
162 cmdmsg="", cmdhint="", statushint="", abortfunc=None):
161 163 """this registers a new command or operation to unfinishedstates
162 164 opname is the name the command or operation
163 165 fname is the file name in which data should be stored in .hg directory.
164 166 It is None for merge command.
165 167 clearable boolean determines whether or not interrupted states can be
166 168 cleared by running `hg update -C .` which in turn deletes the
167 169 state file.
168 170 allowcommit boolean decides whether commit is allowed during interrupted
169 171 state or not.
170 172 reportonly flag is used for operations like bisect where we just
171 173 need to detect the operation using 'hg status --verbose'
172 174 continueflag is a boolean determines whether or not a command supports
173 175 `--continue` option or not.
174 176 stopflag is a boolean that determines whether or not a command supports
175 177 --stop flag
176 178 cmdmsg is used to pass a different status message in case standard
177 179 message of the format "abort: cmdname in progress" is not desired.
178 180 cmdhint is used to pass a different hint message in case standard
179 181 message of the format "To continue: hg cmdname --continue
180 182 To abort: hg cmdname --abort" is not desired.
181 183 statushint is used to pass a different status message in case standard
182 184 message of the format ('To continue: hg cmdname --continue'
183 185 'To abort: hg cmdname --abort') is not desired
186 abortfunc stores the function required to abort an unfinished state.
184 187 """
185 188 statecheckobj = _statecheck(opname, fname, clearable, allowcommit,
186 189 reportonly, continueflag, stopflag, cmdmsg,
187 cmdhint, statushint)
190 cmdhint, statushint, abortfunc)
188 191 if opname == 'merge':
189 192 _unfinishedstates.append(statecheckobj)
190 193 else:
191 194 _unfinishedstates.insert(0, statecheckobj)
192 195
193 196 addunfinished(
194 197 'graft', fname='graftstate', clearable=True, stopflag=True,
195 198 continueflag=True,
196 199 cmdhint=_("use 'hg graft --continue' or 'hg graft --stop' to stop")
197 200 )
198 201 addunfinished(
199 202 'unshelve', fname='shelvedstate', continueflag=True,
200 203 cmdmsg=_('unshelve already in progress')
201 204 )
202 205 addunfinished(
203 206 'update', fname='updatestate', clearable=True,
204 207 cmdmsg=_('last update was interrupted'),
205 208 cmdhint=_("use 'hg update' to get a consistent checkout"),
206 209 statushint=_("To continue: hg update")
207 210 )
208 211 addunfinished(
209 212 'bisect', fname='bisect.state', allowcommit=True, reportonly=True,
210 213 statushint=_('To mark the changeset good: hg bisect --good\n'
211 214 'To mark the changeset bad: hg bisect --bad\n'
212 215 'To abort: hg bisect --reset\n')
213 216 )
214 217 addunfinished(
215 218 'merge', fname=None, clearable=True, allowcommit=True,
216 219 cmdmsg=_('outstanding uncommitted merge'),
217 220 statushint=_('To continue: hg commit\n'
218 221 'To abort: hg merge --abort'),
219 222 cmdhint=_("use 'hg commit' or 'hg merge --abort'")
220 223 )
221 224
222 225 def getrepostate(repo):
223 226 # experimental config: commands.status.skipstates
224 227 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
225 228 for state in _unfinishedstates:
226 229 if state._opname in skip:
227 230 continue
228 231 if state.isunfinished(repo):
229 232 return (state._opname, state.statusmsg())
@@ -1,484 +1,484 b''
1 1 setup
2 2
3 3 $ cat > myextension.py <<EOF
4 4 > from mercurial import error, registrar
5 5 > cmdtable = {}
6 6 > command = registrar.command(cmdtable)
7 7 > @command(b'crash', [], b'hg crash')
8 8 > def crash(ui, *args, **kwargs):
9 9 > raise Exception("oops")
10 > @command(b'abort', [], b'hg abort')
10 > @command(b'abortcmd', [], b'hg abortcmd')
11 11 > def abort(ui, *args, **kwargs):
12 12 > raise error.Abort(b"oops")
13 13 > EOF
14 14 $ abspath=`pwd`/myextension.py
15 15
16 16 $ cat >> $HGRCPATH <<EOF
17 17 > [extensions]
18 18 > blackbox=
19 19 > mock=$TESTDIR/mockblackbox.py
20 20 > mq=
21 21 > myextension=$TESTTMP/myextension.py
22 22 > [alias]
23 23 > confuse = log --limit 3
24 24 > so-confusing = confuse --style compact
25 25 > [blackbox]
26 26 > track = backupbundle, branchcache, command, commandalias, commandexception,
27 27 > commandfinish, debug, exthook, incoming, pythonhook, tagscache
28 28 > EOF
29 29
30 30 $ hg init blackboxtest
31 31 $ cd blackboxtest
32 32
33 33 command, exit codes, and duration
34 34
35 35 $ echo a > a
36 36 $ hg add a
37 37 $ hg blackbox --config blackbox.dirty=True
38 38 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> init blackboxtest exited 0 after * seconds (glob)
39 39 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> add a
40 40 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> add a exited 0 after * seconds (glob)
41 41 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000+ (5000)> blackbox --config *blackbox.dirty=True* (glob)
42 42
43 43 failure exit code
44 44 $ rm ./.hg/blackbox.log
45 45 $ hg add non-existent
46 46 non-existent: $ENOENT$
47 47 [1]
48 48 $ hg blackbox
49 49 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> add non-existent
50 50 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> add non-existent exited 1 after * seconds (glob)
51 51 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
52 52
53 53 abort exit code
54 54 $ rm ./.hg/blackbox.log
55 $ hg abort 2> /dev/null
55 $ hg abortcmd 2> /dev/null
56 56 [255]
57 57 $ hg blackbox -l 2
58 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> abort exited 255 after * seconds (glob)
58 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> abortcmd exited 255 after * seconds (glob)
59 59 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox -l 2
60 60
61 61 unhandled exception
62 62 $ rm ./.hg/blackbox.log
63 63 $ hg crash 2> /dev/null
64 64 [1]
65 65 $ hg blackbox -l 2
66 66 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> crash exited 1 after * seconds (glob)
67 67 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox -l 2
68 68
69 69 alias expansion is logged
70 70 $ rm ./.hg/blackbox.log
71 71 $ hg confuse
72 72 $ hg blackbox
73 73 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> confuse
74 74 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> alias 'confuse' expands to 'log --limit 3'
75 75 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> confuse exited 0 after * seconds (glob)
76 76 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
77 77
78 78 recursive aliases work correctly
79 79 $ rm ./.hg/blackbox.log
80 80 $ hg so-confusing
81 81 $ hg blackbox
82 82 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> so-confusing
83 83 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> alias 'so-confusing' expands to 'confuse --style compact'
84 84 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> alias 'confuse' expands to 'log --limit 3'
85 85 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> so-confusing exited 0 after * seconds (glob)
86 86 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
87 87
88 88 custom date format
89 89 $ rm ./.hg/blackbox.log
90 90 $ hg --config blackbox.date-format='%Y-%m-%d @ %H:%M:%S' \
91 91 > --config devel.default-date='1334347993 0' --traceback status
92 92 A a
93 93 $ hg blackbox
94 94 2012-04-13 @ 20:13:13 bob @0000000000000000000000000000000000000000 (5000)> --config *blackbox.date-format=%Y-%m-%d @ %H:%M:%S* --config *devel.default-date=1334347993 0* --traceback status (glob)
95 95 2012-04-13 @ 20:13:13 bob @0000000000000000000000000000000000000000 (5000)> --config *blackbox.date-format=%Y-%m-%d @ %H:%M:%S* --config *devel.default-date=1334347993 0* --traceback status exited 0 after * seconds (glob)
96 96 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
97 97
98 98 incoming change tracking
99 99
100 100 create two heads to verify that we only see one change in the log later
101 101 $ hg commit -ma
102 102 $ hg up null
103 103 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
104 104 $ echo b > b
105 105 $ hg commit -Amb
106 106 adding b
107 107 created new head
108 108
109 109 clone, commit, pull
110 110 $ hg clone . ../blackboxtest2
111 111 updating to branch default
112 112 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 113 $ echo c > c
114 114 $ hg commit -Amc
115 115 adding c
116 116 $ cd ../blackboxtest2
117 117 $ hg pull
118 118 pulling from $TESTTMP/blackboxtest
119 119 searching for changes
120 120 adding changesets
121 121 adding manifests
122 122 adding file changes
123 123 added 1 changesets with 1 changes to 1 files
124 124 new changesets d02f48003e62
125 125 (run 'hg update' to get a working copy)
126 126 $ hg blackbox -l 6
127 127 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> pull
128 128 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> updated served branch cache in * seconds (glob)
129 129 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> wrote served branch cache with 1 labels and 2 nodes
130 130 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> 1 incoming changes - new heads: d02f48003e62
131 131 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> pull exited 0 after * seconds (glob)
132 132 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> blackbox -l 6
133 133
134 134 we must not cause a failure if we cannot write to the log
135 135
136 136 $ hg rollback
137 137 repository tip rolled back to revision 1 (undo pull)
138 138
139 139 $ mv .hg/blackbox.log .hg/blackbox.log-
140 140 $ mkdir .hg/blackbox.log
141 141 $ hg --debug incoming
142 142 warning: cannot write to blackbox.log: * (glob)
143 143 comparing with $TESTTMP/blackboxtest
144 144 query 1; heads
145 145 searching for changes
146 146 all local heads known remotely
147 147 changeset: 2:d02f48003e62c24e2659d97d30f2a83abe5d5d51
148 148 tag: tip
149 149 phase: draft
150 150 parent: 1:6563da9dcf87b1949716e38ff3e3dfaa3198eb06
151 151 parent: -1:0000000000000000000000000000000000000000
152 152 manifest: 2:ab9d46b053ebf45b7996f2922b9893ff4b63d892
153 153 user: test
154 154 date: Thu Jan 01 00:00:00 1970 +0000
155 155 files+: c
156 156 extra: branch=default
157 157 description:
158 158 c
159 159
160 160
161 161 $ hg pull
162 162 pulling from $TESTTMP/blackboxtest
163 163 searching for changes
164 164 adding changesets
165 165 adding manifests
166 166 adding file changes
167 167 added 1 changesets with 1 changes to 1 files
168 168 new changesets d02f48003e62
169 169 (run 'hg update' to get a working copy)
170 170
171 171 a failure reading from the log is fatal
172 172
173 173 $ hg blackbox -l 3
174 174 abort: *$TESTTMP/blackboxtest2/.hg/blackbox.log* (glob)
175 175 [255]
176 176
177 177 $ rmdir .hg/blackbox.log
178 178 $ mv .hg/blackbox.log- .hg/blackbox.log
179 179
180 180 backup bundles get logged
181 181
182 182 $ touch d
183 183 $ hg commit -Amd
184 184 adding d
185 185 created new head
186 186 $ hg strip tip
187 187 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
188 188 saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
189 189 $ hg blackbox -l 6
190 190 1970/01/01 00:00:00 bob @73f6ee326b27d820b0472f1a825e3a50f3dc489b (5000)> strip tip
191 191 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/73f6ee326b27-7612e004-backup.hg
192 192 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> updated base branch cache in * seconds (glob)
193 193 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> wrote base branch cache with 1 labels and 2 nodes
194 194 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> strip tip exited 0 after * seconds (glob)
195 195 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> blackbox -l 6
196 196
197 197 extension and python hooks - use the eol extension for a pythonhook
198 198
199 199 $ echo '[extensions]' >> .hg/hgrc
200 200 $ echo 'eol=' >> .hg/hgrc
201 201 $ echo '[hooks]' >> .hg/hgrc
202 202 $ echo 'update = echo hooked' >> .hg/hgrc
203 203 $ hg update
204 204 The fsmonitor extension is incompatible with the eol extension and has been disabled. (fsmonitor !)
205 205 hooked
206 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 207 updated to "d02f48003e62: c"
208 208 1 other heads for branch "default"
209 209 $ cat >> .hg/hgrc <<EOF
210 210 > [extensions]
211 211 > # disable eol, because it is not needed for subsequent tests
212 212 > # (in addition, keeping it requires extra care for fsmonitor)
213 213 > eol=!
214 214 > EOF
215 215 $ hg blackbox -l 5
216 216 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> update (no-chg !)
217 217 1970/01/01 00:00:00 bob @6563da9dcf87b1949716e38ff3e3dfaa3198eb06 (5000)> pythonhook-preupdate: hgext.eol.preupdate finished in * seconds (glob)
218 218 1970/01/01 00:00:00 bob @d02f48003e62c24e2659d97d30f2a83abe5d5d51 (5000)> exthook-update: echo hooked finished in * seconds (glob)
219 219 1970/01/01 00:00:00 bob @d02f48003e62c24e2659d97d30f2a83abe5d5d51 (5000)> update exited 0 after * seconds (glob)
220 220 1970/01/01 00:00:00 bob @d02f48003e62c24e2659d97d30f2a83abe5d5d51 (5000)> serve --cmdserver chgunix --address $TESTTMP.chgsock/server.* --daemon-postexec 'chdir:/' (glob) (chg !)
221 221 1970/01/01 00:00:00 bob @d02f48003e62c24e2659d97d30f2a83abe5d5d51 (5000)> blackbox -l 5
222 222
223 223 log rotation
224 224
225 225 $ echo '[blackbox]' >> .hg/hgrc
226 226 $ echo 'maxsize = 20 b' >> .hg/hgrc
227 227 $ echo 'maxfiles = 3' >> .hg/hgrc
228 228 $ hg status
229 229 $ hg status
230 230 $ hg status
231 231 $ hg tip -q
232 232 2:d02f48003e62
233 233 $ ls .hg/blackbox.log*
234 234 .hg/blackbox.log
235 235 .hg/blackbox.log.1
236 236 .hg/blackbox.log.2
237 237 $ cd ..
238 238
239 239 $ hg init blackboxtest3
240 240 $ cd blackboxtest3
241 241 $ hg blackbox
242 242 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> init blackboxtest3 exited 0 after * seconds (glob)
243 243 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
244 244 $ mv .hg/blackbox.log .hg/blackbox.log-
245 245 $ mkdir .hg/blackbox.log
246 246 $ sed -e 's/\(.*test1.*\)/#\1/; s#\(.*commit2.*\)#os.rmdir(".hg/blackbox.log")\
247 247 > os.rename(".hg/blackbox.log-", ".hg/blackbox.log")\
248 248 > \1#' $TESTDIR/test-dispatch.py > ../test-dispatch.py
249 249 $ "$PYTHON" $TESTDIR/blackbox-readonly-dispatch.py
250 250 running: --debug add foo
251 251 warning: cannot write to blackbox.log: Is a directory (no-windows !)
252 252 warning: cannot write to blackbox.log: $TESTTMP/blackboxtest3/.hg/blackbox.log: Access is denied (windows !)
253 253 adding foo
254 254 result: 0
255 255 running: --debug commit -m commit1 -d 2000-01-01 foo
256 256 warning: cannot write to blackbox.log: Is a directory (no-windows !)
257 257 warning: cannot write to blackbox.log: $TESTTMP/blackboxtest3/.hg/blackbox.log: Access is denied (windows !)
258 258 committing files:
259 259 foo
260 260 committing manifest
261 261 committing changelog
262 262 updating the branch cache
263 263 committed changeset 0:0e46349438790c460c5c9f7546bfcd39b267bbd2
264 264 result: 0
265 265 running: --debug commit -m commit2 -d 2000-01-02 foo
266 266 committing files:
267 267 foo
268 268 committing manifest
269 269 committing changelog
270 270 updating the branch cache
271 271 committed changeset 1:45589e459b2edfbf3dbde7e01f611d2c1e7453d7
272 272 result: 0
273 273 running: --debug log -r 0
274 274 changeset: 0:0e46349438790c460c5c9f7546bfcd39b267bbd2
275 275 phase: draft
276 276 parent: -1:0000000000000000000000000000000000000000
277 277 parent: -1:0000000000000000000000000000000000000000
278 278 manifest: 0:9091aa5df980aea60860a2e39c95182e68d1ddec
279 279 user: test
280 280 date: Sat Jan 01 00:00:00 2000 +0000
281 281 files+: foo
282 282 extra: branch=default
283 283 description:
284 284 commit1
285 285
286 286
287 287 result: 0
288 288 running: --debug log -r tip
289 289 changeset: 1:45589e459b2edfbf3dbde7e01f611d2c1e7453d7
290 290 tag: tip
291 291 phase: draft
292 292 parent: 0:0e46349438790c460c5c9f7546bfcd39b267bbd2
293 293 parent: -1:0000000000000000000000000000000000000000
294 294 manifest: 1:895aa9b7886f89dd017a6d62524e1f9180b04df9
295 295 user: test
296 296 date: Sun Jan 02 00:00:00 2000 +0000
297 297 files: foo
298 298 extra: branch=default
299 299 description:
300 300 commit2
301 301
302 302
303 303 result: 0
304 304 $ hg blackbox
305 305 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> updating the branch cache
306 306 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> updated served branch cache in * seconds (glob)
307 307 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> wrote served branch cache with 1 labels and 1 nodes
308 308 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> --debug commit -m commit2 -d 2000-01-02 foo exited 0 after *.?? seconds (glob)
309 309 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> --debug log -r 0
310 310 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> writing .hg/cache/tags2-visible with 0 tags
311 311 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> --debug log -r 0 exited 0 after *.?? seconds (glob)
312 312 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> --debug log -r tip
313 313 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> --debug log -r tip exited 0 after *.?? seconds (glob)
314 314 1970/01/01 00:00:00 bob @45589e459b2edfbf3dbde7e01f611d2c1e7453d7 (5000)> blackbox
315 315
316 316 Test log recursion from dirty status check
317 317
318 318 $ cat > ../r.py <<EOF
319 319 > from mercurial import context, error, extensions
320 320 > x=[False]
321 321 > def status(orig, *args, **opts):
322 322 > args[0].repo().ui.log(b"broken", b"recursion?")
323 323 > return orig(*args, **opts)
324 324 > def reposetup(ui, repo):
325 325 > extensions.wrapfunction(context.basectx, 'status', status)
326 326 > EOF
327 327 $ hg id --config extensions.x=../r.py --config blackbox.dirty=True
328 328 45589e459b2e tip
329 329
330 330 cleanup
331 331 $ cd ..
332 332
333 333 Test missing log directory, which shouldn't be created automatically
334 334
335 335 $ cat <<'EOF' > closeremove.py
336 336 > def reposetup(ui, repo):
337 337 > class rmrepo(repo.__class__):
338 338 > def close(self):
339 339 > super(rmrepo, self).close()
340 340 > self.ui.debug(b'removing %s\n' % self.vfs.base)
341 341 > self.vfs.rmtree()
342 342 > repo.__class__ = rmrepo
343 343 > EOF
344 344
345 345 $ hg init gone
346 346 $ cd gone
347 347 $ cat <<'EOF' > .hg/hgrc
348 348 > [extensions]
349 349 > closeremove = ../closeremove.py
350 350 > EOF
351 351 $ hg log --debug
352 352 removing $TESTTMP/gone/.hg
353 353 warning: cannot write to blackbox.log: $ENOENT$ (no-windows !)
354 354 warning: cannot write to blackbox.log: $TESTTMP/gone/.hg/blackbox.log: $ENOTDIR$ (windows !)
355 355 $ cd ..
356 356
357 357 blackbox should disable itself if track is empty
358 358
359 359 $ hg --config blackbox.track= init nothing_tracked
360 360 $ cd nothing_tracked
361 361 $ cat >> .hg/hgrc << EOF
362 362 > [blackbox]
363 363 > track =
364 364 > EOF
365 365 $ hg blackbox
366 366 $ cd $TESTTMP
367 367
368 368 a '*' entry in blackbox.track is interpreted as log everything
369 369
370 370 $ hg --config blackbox.track='*' \
371 371 > --config blackbox.logsource=True \
372 372 > init track_star
373 373 $ cd track_star
374 374 $ cat >> .hg/hgrc << EOF
375 375 > [blackbox]
376 376 > logsource = True
377 377 > track = *
378 378 > EOF
379 379 (only look for entries with specific logged sources, otherwise this test is
380 380 pretty brittle)
381 381 $ hg blackbox | egrep '\[command(finish)?\]'
382 382 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000) [commandfinish]> --config *blackbox.track=* --config *blackbox.logsource=True* init track_star exited 0 after * seconds (glob)
383 383 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000) [command]> blackbox
384 384 $ cd $TESTTMP
385 385
386 386 #if chg
387 387
388 388 when using chg, blackbox.log should get rotated correctly
389 389
390 390 $ cat > $TESTTMP/noop.py << EOF
391 391 > from __future__ import absolute_import
392 392 > import time
393 393 > from mercurial import registrar, scmutil
394 394 > cmdtable = {}
395 395 > command = registrar.command(cmdtable)
396 396 > @command('noop')
397 397 > def noop(ui, repo):
398 398 > pass
399 399 > EOF
400 400
401 401 $ hg init blackbox-chg
402 402 $ cd blackbox-chg
403 403
404 404 $ cat > .hg/hgrc << EOF
405 405 > [blackbox]
406 406 > maxsize = 500B
407 407 > [extensions]
408 408 > # extension change forces chg to restart
409 409 > noop=$TESTTMP/noop.py
410 410 > EOF
411 411
412 412 $ "$PYTHON" -c 'print("a" * 400)' > .hg/blackbox.log
413 413 $ chg noop
414 414 $ chg noop
415 415 $ chg noop
416 416 $ chg noop
417 417 $ chg noop
418 418
419 419 $ cat > showsize.py << 'EOF'
420 420 > import os
421 421 > import sys
422 422 > limit = 500
423 423 > for p in sys.argv[1:]:
424 424 > size = os.stat(p).st_size
425 425 > if size >= limit:
426 426 > desc = '>='
427 427 > else:
428 428 > desc = '<'
429 429 > print('%s: %s %d' % (p, desc, limit))
430 430 > EOF
431 431
432 432 $ "$PYTHON" showsize.py .hg/blackbox*
433 433 .hg/blackbox.log: < 500
434 434 .hg/blackbox.log.1: >= 500
435 435 .hg/blackbox.log.2: >= 500
436 436
437 437 $ cd ..
438 438
439 439 With chg, blackbox should not create the log file if the repo is gone
440 440
441 441 $ hg init repo1
442 442 $ hg --config extensions.a=! -R repo1 log
443 443 $ rm -rf $TESTTMP/repo1
444 444 $ hg --config extensions.a=! init repo1
445 445
446 446 #endif
447 447
448 448 blackbox should work if repo.ui.log is not called (issue5518)
449 449
450 450 $ cat > $TESTTMP/raise.py << EOF
451 451 > from __future__ import absolute_import
452 452 > from mercurial import registrar, scmutil
453 453 > cmdtable = {}
454 454 > command = registrar.command(cmdtable)
455 455 > @command(b'raise')
456 456 > def raisecmd(*args):
457 457 > raise RuntimeError('raise')
458 458 > EOF
459 459
460 460 $ cat >> $HGRCPATH << EOF
461 461 > [blackbox]
462 462 > track = commandexception
463 463 > [extensions]
464 464 > raise=$TESTTMP/raise.py
465 465 > EOF
466 466
467 467 $ hg init $TESTTMP/blackbox-exception-only
468 468 $ cd $TESTTMP/blackbox-exception-only
469 469
470 470 #if chg
471 471 (chg exits 255 because it fails to receive an exit code)
472 472 $ hg raise 2>/dev/null
473 473 [255]
474 474 #else
475 475 (hg exits 1 because Python default exit code for uncaught exception is 1)
476 476 $ hg raise 2>/dev/null
477 477 [1]
478 478 #endif
479 479
480 480 $ head -1 .hg/blackbox.log
481 481 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> ** Unknown exception encountered with possibly-broken third-party extension mock
482 482 $ tail -2 .hg/blackbox.log
483 483 RuntimeError: raise
484 484
@@ -1,418 +1,421 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 abort
3 4 add
4 5 addremove
5 6 annotate
6 7 archive
7 8 backout
8 9 bisect
9 10 bookmarks
10 11 branch
11 12 branches
12 13 bundle
13 14 cat
14 15 clone
15 16 commit
16 17 config
17 18 copy
18 19 diff
19 20 export
20 21 files
21 22 forget
22 23 graft
23 24 grep
24 25 heads
25 26 help
26 27 identify
27 28 import
28 29 incoming
29 30 init
30 31 locate
31 32 log
32 33 manifest
33 34 merge
34 35 outgoing
35 36 parents
36 37 paths
37 38 phase
38 39 pull
39 40 push
40 41 recover
41 42 remove
42 43 rename
43 44 resolve
44 45 revert
45 46 rollback
46 47 root
47 48 serve
48 49 shelve
49 50 status
50 51 summary
51 52 tag
52 53 tags
53 54 tip
54 55 unbundle
55 56 unshelve
56 57 update
57 58 verify
58 59 version
59 60
60 61 Show all commands that start with "a"
61 62 $ hg debugcomplete a
63 abort
62 64 add
63 65 addremove
64 66 annotate
65 67 archive
66 68
67 69 Do not show debug commands if there are other candidates
68 70 $ hg debugcomplete d
69 71 diff
70 72
71 73 Show debug commands if there are no other candidates
72 74 $ hg debugcomplete debug
73 75 debugancestor
74 76 debugapplystreamclonebundle
75 77 debugbuilddag
76 78 debugbundle
77 79 debugcapabilities
78 80 debugcheckstate
79 81 debugcolor
80 82 debugcommands
81 83 debugcomplete
82 84 debugconfig
83 85 debugcreatestreamclonebundle
84 86 debugdag
85 87 debugdata
86 88 debugdate
87 89 debugdeltachain
88 90 debugdirstate
89 91 debugdiscovery
90 92 debugdownload
91 93 debugextensions
92 94 debugfileset
93 95 debugformat
94 96 debugfsinfo
95 97 debuggetbundle
96 98 debugignore
97 99 debugindex
98 100 debugindexdot
99 101 debugindexstats
100 102 debuginstall
101 103 debugknown
102 104 debuglabelcomplete
103 105 debuglocks
104 106 debugmanifestfulltextcache
105 107 debugmergestate
106 108 debugnamecomplete
107 109 debugobsolete
108 110 debugp1copies
109 111 debugp2copies
110 112 debugpathcomplete
111 113 debugpathcopies
112 114 debugpeer
113 115 debugpickmergetool
114 116 debugpushkey
115 117 debugpvec
116 118 debugrebuilddirstate
117 119 debugrebuildfncache
118 120 debugrename
119 121 debugrevlog
120 122 debugrevlogindex
121 123 debugrevspec
122 124 debugserve
123 125 debugsetparents
124 126 debugssl
125 127 debugsub
126 128 debugsuccessorssets
127 129 debugtemplate
128 130 debuguigetpass
129 131 debuguiprompt
130 132 debugupdatecaches
131 133 debugupgraderepo
132 134 debugwalk
133 135 debugwhyunstable
134 136 debugwireargs
135 137 debugwireproto
136 138
137 139 Do not show the alias of a debug command if there are other candidates
138 140 (this should hide rawcommit)
139 141 $ hg debugcomplete r
140 142 recover
141 143 remove
142 144 rename
143 145 resolve
144 146 revert
145 147 rollback
146 148 root
147 149 Show the alias of a debug command if there are no other candidates
148 150 $ hg debugcomplete rawc
149 151
150 152
151 153 Show the global options
152 154 $ hg debugcomplete --options | sort
153 155 --color
154 156 --config
155 157 --cwd
156 158 --debug
157 159 --debugger
158 160 --encoding
159 161 --encodingmode
160 162 --help
161 163 --hidden
162 164 --noninteractive
163 165 --pager
164 166 --profile
165 167 --quiet
166 168 --repository
167 169 --time
168 170 --traceback
169 171 --verbose
170 172 --version
171 173 -R
172 174 -h
173 175 -q
174 176 -v
175 177 -y
176 178
177 179 Show the options for the "serve" command
178 180 $ hg debugcomplete --options serve | sort
179 181 --accesslog
180 182 --address
181 183 --certificate
182 184 --cmdserver
183 185 --color
184 186 --config
185 187 --cwd
186 188 --daemon
187 189 --daemon-postexec
188 190 --debug
189 191 --debugger
190 192 --encoding
191 193 --encodingmode
192 194 --errorlog
193 195 --help
194 196 --hidden
195 197 --ipv6
196 198 --name
197 199 --noninteractive
198 200 --pager
199 201 --pid-file
200 202 --port
201 203 --prefix
202 204 --print-url
203 205 --profile
204 206 --quiet
205 207 --repository
206 208 --stdio
207 209 --style
208 210 --subrepos
209 211 --templates
210 212 --time
211 213 --traceback
212 214 --verbose
213 215 --version
214 216 --web-conf
215 217 -6
216 218 -A
217 219 -E
218 220 -R
219 221 -S
220 222 -a
221 223 -d
222 224 -h
223 225 -n
224 226 -p
225 227 -q
226 228 -t
227 229 -v
228 230 -y
229 231
230 232 Show an error if we use --options with an ambiguous abbreviation
231 233 $ hg debugcomplete --options s
232 234 hg: command 's' is ambiguous:
233 235 serve shelve showconfig status summary
234 236 [255]
235 237
236 238 Show all commands + options
237 239 $ hg debugcommands
240 abort: dry-run
238 241 add: include, exclude, subrepos, dry-run
239 242 addremove: similarity, subrepos, include, exclude, dry-run
240 243 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
241 244 archive: no-decode, prefix, rev, type, subrepos, include, exclude
242 245 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
243 246 bisect: reset, good, bad, skip, extend, command, noupdate
244 247 bookmarks: force, rev, delete, rename, inactive, list, template
245 248 branch: force, clean, rev
246 249 branches: active, closed, rev, template
247 250 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
248 251 cat: output, rev, decode, include, exclude, template
249 252 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
250 253 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
251 254 config: untrusted, edit, local, global, template
252 255 copy: after, force, include, exclude, dry-run
253 256 debugancestor:
254 257 debugapplystreamclonebundle:
255 258 debugbuilddag: mergeable-file, overwritten-file, new-file
256 259 debugbundle: all, part-type, spec
257 260 debugcapabilities:
258 261 debugcheckstate:
259 262 debugcolor: style
260 263 debugcommands:
261 264 debugcomplete: options
262 265 debugcreatestreamclonebundle:
263 266 debugdag: tags, branches, dots, spaces
264 267 debugdata: changelog, manifest, dir
265 268 debugdate: extended
266 269 debugdeltachain: changelog, manifest, dir, template
267 270 debugdirstate: nodates, dates, datesort
268 271 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
269 272 debugdownload: output
270 273 debugextensions: template
271 274 debugfileset: rev, all-files, show-matcher, show-stage
272 275 debugformat: template
273 276 debugfsinfo:
274 277 debuggetbundle: head, common, type
275 278 debugignore:
276 279 debugindex: changelog, manifest, dir, template
277 280 debugindexdot: changelog, manifest, dir
278 281 debugindexstats:
279 282 debuginstall: template
280 283 debugknown:
281 284 debuglabelcomplete:
282 285 debuglocks: force-lock, force-wlock, set-lock, set-wlock
283 286 debugmanifestfulltextcache: clear, add
284 287 debugmergestate:
285 288 debugnamecomplete:
286 289 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
287 290 debugp1copies: rev
288 291 debugp2copies: rev
289 292 debugpathcomplete: full, normal, added, removed
290 293 debugpathcopies: include, exclude
291 294 debugpeer:
292 295 debugpickmergetool: rev, changedelete, include, exclude, tool
293 296 debugpushkey:
294 297 debugpvec:
295 298 debugrebuilddirstate: rev, minimal
296 299 debugrebuildfncache:
297 300 debugrename: rev
298 301 debugrevlog: changelog, manifest, dir, dump
299 302 debugrevlogindex: changelog, manifest, dir, format
300 303 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
301 304 debugserve: sshstdio, logiofd, logiofile
302 305 debugsetparents:
303 306 debugssl:
304 307 debugsub: rev
305 308 debugsuccessorssets: closest
306 309 debugtemplate: rev, define
307 310 debuguigetpass: prompt
308 311 debuguiprompt: prompt
309 312 debugupdatecaches:
310 313 debugupgraderepo: optimize, run, backup
311 314 debugwalk: include, exclude
312 315 debugwhyunstable:
313 316 debugwireargs: three, four, five, ssh, remotecmd, insecure
314 317 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
315 318 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
316 319 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
317 320 files: rev, print0, include, exclude, template, subrepos
318 321 forget: interactive, include, exclude, dry-run
319 322 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
320 323 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
321 324 heads: rev, topo, active, closed, style, template
322 325 help: extension, command, keyword, system
323 326 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
324 327 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
325 328 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
326 329 init: ssh, remotecmd, insecure
327 330 locate: rev, print0, fullpath, include, exclude
328 331 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
329 332 manifest: rev, all, template
330 333 merge: force, rev, preview, abort, tool
331 334 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
332 335 parents: rev, style, template
333 336 paths: template
334 337 phase: public, draft, secret, force, rev
335 338 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
336 339 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
337 340 recover: verify
338 341 remove: after, force, subrepos, include, exclude, dry-run
339 342 rename: after, force, include, exclude, dry-run
340 343 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
341 344 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
342 345 rollback: dry-run, force
343 346 root: template
344 347 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
345 348 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
346 349 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
347 350 summary: remote
348 351 tag: force, local, rev, remove, edit, message, date, user
349 352 tags: template
350 353 tip: patch, git, style, template
351 354 unbundle: update
352 355 unshelve: abort, continue, keep, name, tool, date
353 356 update: clean, check, merge, date, rev, tool
354 357 verify: full
355 358 version: template
356 359
357 360 $ hg init a
358 361 $ cd a
359 362 $ echo fee > fee
360 363 $ hg ci -q -Amfee
361 364 $ hg tag fee
362 365 $ mkdir fie
363 366 $ echo dead > fie/dead
364 367 $ echo live > fie/live
365 368 $ hg bookmark fo
366 369 $ hg branch -q fie
367 370 $ hg ci -q -Amfie
368 371 $ echo fo > fo
369 372 $ hg branch -qf default
370 373 $ hg ci -q -Amfo
371 374 $ echo Fum > Fum
372 375 $ hg ci -q -AmFum
373 376 $ hg bookmark Fum
374 377
375 378 Test debugpathcomplete
376 379
377 380 $ hg debugpathcomplete f
378 381 fee
379 382 fie
380 383 fo
381 384 $ hg debugpathcomplete -f f
382 385 fee
383 386 fie/dead
384 387 fie/live
385 388 fo
386 389
387 390 $ hg rm Fum
388 391 $ hg debugpathcomplete -r F
389 392 Fum
390 393
391 394 Test debugnamecomplete
392 395
393 396 $ hg debugnamecomplete
394 397 Fum
395 398 default
396 399 fee
397 400 fie
398 401 fo
399 402 tip
400 403 $ hg debugnamecomplete f
401 404 fee
402 405 fie
403 406 fo
404 407
405 408 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
406 409 used for completions in some shells.
407 410
408 411 $ hg debuglabelcomplete
409 412 Fum
410 413 default
411 414 fee
412 415 fie
413 416 fo
414 417 tip
415 418 $ hg debuglabelcomplete f
416 419 fee
417 420 fie
418 421 fo
@@ -1,3875 +1,3883 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 shelve save and set aside changes from the working directory
116 116 status show changed files in the working directory
117 117 summary summarize working directory state
118 118 unshelve restore a shelved change to the working directory
119 119 update update working directory (or switch revisions)
120 120
121 121 Change import/export:
122 122
123 123 archive create an unversioned archive of a repository revision
124 124 bundle create a bundle file
125 125 export dump the header and diffs for one or more changesets
126 126 import import an ordered set of patches
127 127 unbundle apply one or more bundle files
128 128
129 129 Repository maintenance:
130 130
131 131 manifest output the current or given revision of the project manifest
132 132 recover roll back an interrupted transaction
133 133 verify verify the integrity of the repository
134 134
135 135 Help:
136 136
137 137 config show combined config settings from all hgrc files
138 138 help show help for a given topic or a help overview
139 139 version output version and copyright information
140 140
141 141 additional help topics:
142 142
143 143 Mercurial identifiers:
144 144
145 145 filesets Specifying File Sets
146 146 hgignore Syntax for Mercurial Ignore Files
147 147 patterns File Name Patterns
148 148 revisions Specifying Revisions
149 149 urls URL Paths
150 150
151 151 Mercurial output:
152 152
153 153 color Colorizing Outputs
154 154 dates Date Formats
155 155 diffs Diff Formats
156 156 templating Template Usage
157 157
158 158 Mercurial configuration:
159 159
160 160 config Configuration Files
161 161 environment Environment Variables
162 162 extensions Using Additional Features
163 163 flags Command-line flags
164 164 hgweb Configuring hgweb
165 165 merge-tools Merge Tools
166 166 pager Pager Support
167 167
168 168 Concepts:
169 169
170 170 bundlespec Bundle File Formats
171 171 glossary Glossary
172 172 phases Working with Phases
173 173 subrepos Subrepositories
174 174
175 175 Miscellaneous:
176 176
177 177 deprecated Deprecated Features
178 178 internals Technical implementation topics
179 179 scripting Using Mercurial from scripts and automation
180 180
181 181 (use 'hg help -v' to show built-in aliases and global options)
182 182
183 183 $ hg -q help
184 184 Repository creation:
185 185
186 186 clone make a copy of an existing repository
187 187 init create a new repository in the given directory
188 188
189 189 Remote repository management:
190 190
191 191 incoming show new changesets found in source
192 192 outgoing show changesets not found in the destination
193 193 paths show aliases for remote repositories
194 194 pull pull changes from the specified source
195 195 push push changes to the specified destination
196 196 serve start stand-alone webserver
197 197
198 198 Change creation:
199 199
200 200 commit commit the specified files or all outstanding changes
201 201
202 202 Change manipulation:
203 203
204 204 backout reverse effect of earlier changeset
205 205 graft copy changes from other branches onto the current branch
206 206 merge merge another revision into working directory
207 207
208 208 Change organization:
209 209
210 210 bookmarks create a new bookmark or list existing bookmarks
211 211 branch set or show the current branch name
212 212 branches list repository named branches
213 213 phase set or show the current phase name
214 214 tag add one or more tags for the current or given revision
215 215 tags list repository tags
216 216
217 217 File content management:
218 218
219 219 annotate show changeset information by line for each file
220 220 cat output the current or given revision of files
221 221 copy mark files as copied for the next commit
222 222 diff diff repository (or selected files)
223 223 grep search revision history for a pattern in specified files
224 224
225 225 Change navigation:
226 226
227 227 bisect subdivision search of changesets
228 228 heads show branch heads
229 229 identify identify the working directory or specified revision
230 230 log show revision history of entire repository or files
231 231
232 232 Working directory management:
233 233
234 234 add add the specified files on the next commit
235 235 addremove add all new files, delete all missing files
236 236 files list tracked files
237 237 forget forget the specified files on the next commit
238 238 remove remove the specified files on the next commit
239 239 rename rename files; equivalent of copy + remove
240 240 resolve redo merges or set/view the merge status of files
241 241 revert restore files to their checkout state
242 242 root print the root (top) of the current working directory
243 243 shelve save and set aside changes from the working directory
244 244 status show changed files in the working directory
245 245 summary summarize working directory state
246 246 unshelve restore a shelved change to the working directory
247 247 update update working directory (or switch revisions)
248 248
249 249 Change import/export:
250 250
251 251 archive create an unversioned archive of a repository revision
252 252 bundle create a bundle file
253 253 export dump the header and diffs for one or more changesets
254 254 import import an ordered set of patches
255 255 unbundle apply one or more bundle files
256 256
257 257 Repository maintenance:
258 258
259 259 manifest output the current or given revision of the project manifest
260 260 recover roll back an interrupted transaction
261 261 verify verify the integrity of the repository
262 262
263 263 Help:
264 264
265 265 config show combined config settings from all hgrc files
266 266 help show help for a given topic or a help overview
267 267 version output version and copyright information
268 268
269 269 additional help topics:
270 270
271 271 Mercurial identifiers:
272 272
273 273 filesets Specifying File Sets
274 274 hgignore Syntax for Mercurial Ignore Files
275 275 patterns File Name Patterns
276 276 revisions Specifying Revisions
277 277 urls URL Paths
278 278
279 279 Mercurial output:
280 280
281 281 color Colorizing Outputs
282 282 dates Date Formats
283 283 diffs Diff Formats
284 284 templating Template Usage
285 285
286 286 Mercurial configuration:
287 287
288 288 config Configuration Files
289 289 environment Environment Variables
290 290 extensions Using Additional Features
291 291 flags Command-line flags
292 292 hgweb Configuring hgweb
293 293 merge-tools Merge Tools
294 294 pager Pager Support
295 295
296 296 Concepts:
297 297
298 298 bundlespec Bundle File Formats
299 299 glossary Glossary
300 300 phases Working with Phases
301 301 subrepos Subrepositories
302 302
303 303 Miscellaneous:
304 304
305 305 deprecated Deprecated Features
306 306 internals Technical implementation topics
307 307 scripting Using Mercurial from scripts and automation
308 308
309 309 Test extension help:
310 310 $ hg help extensions --config extensions.rebase= --config extensions.children=
311 311 Using Additional Features
312 312 """""""""""""""""""""""""
313 313
314 314 Mercurial has the ability to add new features through the use of
315 315 extensions. Extensions may add new commands, add options to existing
316 316 commands, change the default behavior of commands, or implement hooks.
317 317
318 318 To enable the "foo" extension, either shipped with Mercurial or in the
319 319 Python search path, create an entry for it in your configuration file,
320 320 like this:
321 321
322 322 [extensions]
323 323 foo =
324 324
325 325 You may also specify the full path to an extension:
326 326
327 327 [extensions]
328 328 myfeature = ~/.hgext/myfeature.py
329 329
330 330 See 'hg help config' for more information on configuration files.
331 331
332 332 Extensions are not loaded by default for a variety of reasons: they can
333 333 increase startup overhead; they may be meant for advanced usage only; they
334 334 may provide potentially dangerous abilities (such as letting you destroy
335 335 or modify history); they might not be ready for prime time; or they may
336 336 alter some usual behaviors of stock Mercurial. It is thus up to the user
337 337 to activate extensions as needed.
338 338
339 339 To explicitly disable an extension enabled in a configuration file of
340 340 broader scope, prepend its path with !:
341 341
342 342 [extensions]
343 343 # disabling extension bar residing in /path/to/extension/bar.py
344 344 bar = !/path/to/extension/bar.py
345 345 # ditto, but no path was supplied for extension baz
346 346 baz = !
347 347
348 348 enabled extensions:
349 349
350 350 children command to display child changesets (DEPRECATED)
351 351 rebase command to move sets of revisions to a different ancestor
352 352
353 353 disabled extensions:
354 354
355 355 acl hooks for controlling repository access
356 356 blackbox log repository events to a blackbox for debugging
357 357 bugzilla hooks for integrating with the Bugzilla bug tracker
358 358 censor erase file content at a given revision
359 359 churn command to display statistics about repository history
360 360 clonebundles advertise pre-generated bundles to seed clones
361 361 closehead close arbitrary heads without checking them out first
362 362 convert import revisions from foreign VCS repositories into
363 363 Mercurial
364 364 eol automatically manage newlines in repository files
365 365 extdiff command to allow external programs to compare revisions
366 366 factotum http authentication with factotum
367 367 githelp try mapping git commands to Mercurial commands
368 368 gpg commands to sign and verify changesets
369 369 hgk browse the repository in a graphical way
370 370 highlight syntax highlighting for hgweb (requires Pygments)
371 371 histedit interactive history editing
372 372 keyword expand keywords in tracked files
373 373 largefiles track large binary files
374 374 mq manage a stack of patches
375 375 notify hooks for sending email push notifications
376 376 patchbomb command to send changesets as (a series of) patch emails
377 377 purge command to delete untracked files from the working
378 378 directory
379 379 relink recreates hardlinks between repository clones
380 380 schemes extend schemes with shortcuts to repository swarms
381 381 share share a common history between several working directories
382 382 strip strip changesets and their descendants from history
383 383 transplant command to transplant changesets from another branch
384 384 win32mbcs allow the use of MBCS paths with problematic encodings
385 385 zeroconf discover and advertise repositories on the local network
386 386
387 387 #endif
388 388
389 389 Verify that deprecated extensions are included if --verbose:
390 390
391 391 $ hg -v help extensions | grep children
392 392 children command to display child changesets (DEPRECATED)
393 393
394 394 Verify that extension keywords appear in help templates
395 395
396 396 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
397 397
398 398 Test short command list with verbose option
399 399
400 400 $ hg -v help shortlist
401 401 Mercurial Distributed SCM
402 402
403 403 basic commands:
404 404
405 abort abort an unfinished operation (EXPERIMENTAL)
405 406 add add the specified files on the next commit
406 407 annotate, blame
407 408 show changeset information by line for each file
408 409 clone make a copy of an existing repository
409 410 commit, ci commit the specified files or all outstanding changes
410 411 diff diff repository (or selected files)
411 412 export dump the header and diffs for one or more changesets
412 413 forget forget the specified files on the next commit
413 414 init create a new repository in the given directory
414 415 log, history show revision history of entire repository or files
415 416 merge merge another revision into working directory
416 417 pull pull changes from the specified source
417 418 push push changes to the specified destination
418 419 remove, rm remove the specified files on the next commit
419 420 serve start stand-alone webserver
420 421 status, st show changed files in the working directory
421 422 summary, sum summarize working directory state
422 423 update, up, checkout, co
423 424 update working directory (or switch revisions)
424 425
425 426 global options ([+] can be repeated):
426 427
427 428 -R --repository REPO repository root directory or name of overlay bundle
428 429 file
429 430 --cwd DIR change working directory
430 431 -y --noninteractive do not prompt, automatically pick the first choice for
431 432 all prompts
432 433 -q --quiet suppress output
433 434 -v --verbose enable additional output
434 435 --color TYPE when to colorize (boolean, always, auto, never, or
435 436 debug)
436 437 --config CONFIG [+] set/override config option (use 'section.name=value')
437 438 --debug enable debugging output
438 439 --debugger start debugger
439 440 --encoding ENCODE set the charset encoding (default: ascii)
440 441 --encodingmode MODE set the charset encoding mode (default: strict)
441 442 --traceback always print a traceback on exception
442 443 --time time how long the command takes
443 444 --profile print command execution profile
444 445 --version output version information and exit
445 446 -h --help display help and exit
446 447 --hidden consider hidden changesets
447 448 --pager TYPE when to paginate (boolean, always, auto, or never)
448 449 (default: auto)
449 450
450 451 (use 'hg help' for the full list of commands)
451 452
452 453 $ hg add -h
453 454 hg add [OPTION]... [FILE]...
454 455
455 456 add the specified files on the next commit
456 457
457 458 Schedule files to be version controlled and added to the repository.
458 459
459 460 The files will be added to the repository at the next commit. To undo an
460 461 add before that, see 'hg forget'.
461 462
462 463 If no names are given, add all files to the repository (except files
463 464 matching ".hgignore").
464 465
465 466 Returns 0 if all files are successfully added.
466 467
467 468 options ([+] can be repeated):
468 469
469 470 -I --include PATTERN [+] include names matching the given patterns
470 471 -X --exclude PATTERN [+] exclude names matching the given patterns
471 472 -S --subrepos recurse into subrepositories
472 473 -n --dry-run do not perform actions, just print output
473 474
474 475 (some details hidden, use --verbose to show complete help)
475 476
476 477 Verbose help for add
477 478
478 479 $ hg add -hv
479 480 hg add [OPTION]... [FILE]...
480 481
481 482 add the specified files on the next commit
482 483
483 484 Schedule files to be version controlled and added to the repository.
484 485
485 486 The files will be added to the repository at the next commit. To undo an
486 487 add before that, see 'hg forget'.
487 488
488 489 If no names are given, add all files to the repository (except files
489 490 matching ".hgignore").
490 491
491 492 Examples:
492 493
493 494 - New (unknown) files are added automatically by 'hg add':
494 495
495 496 $ ls
496 497 foo.c
497 498 $ hg status
498 499 ? foo.c
499 500 $ hg add
500 501 adding foo.c
501 502 $ hg status
502 503 A foo.c
503 504
504 505 - Specific files to be added can be specified:
505 506
506 507 $ ls
507 508 bar.c foo.c
508 509 $ hg status
509 510 ? bar.c
510 511 ? foo.c
511 512 $ hg add bar.c
512 513 $ hg status
513 514 A bar.c
514 515 ? foo.c
515 516
516 517 Returns 0 if all files are successfully added.
517 518
518 519 options ([+] can be repeated):
519 520
520 521 -I --include PATTERN [+] include names matching the given patterns
521 522 -X --exclude PATTERN [+] exclude names matching the given patterns
522 523 -S --subrepos recurse into subrepositories
523 524 -n --dry-run do not perform actions, just print output
524 525
525 526 global options ([+] can be repeated):
526 527
527 528 -R --repository REPO repository root directory or name of overlay bundle
528 529 file
529 530 --cwd DIR change working directory
530 531 -y --noninteractive do not prompt, automatically pick the first choice for
531 532 all prompts
532 533 -q --quiet suppress output
533 534 -v --verbose enable additional output
534 535 --color TYPE when to colorize (boolean, always, auto, never, or
535 536 debug)
536 537 --config CONFIG [+] set/override config option (use 'section.name=value')
537 538 --debug enable debugging output
538 539 --debugger start debugger
539 540 --encoding ENCODE set the charset encoding (default: ascii)
540 541 --encodingmode MODE set the charset encoding mode (default: strict)
541 542 --traceback always print a traceback on exception
542 543 --time time how long the command takes
543 544 --profile print command execution profile
544 545 --version output version information and exit
545 546 -h --help display help and exit
546 547 --hidden consider hidden changesets
547 548 --pager TYPE when to paginate (boolean, always, auto, or never)
548 549 (default: auto)
549 550
550 551 Test the textwidth config option
551 552
552 553 $ hg root -h --config ui.textwidth=50
553 554 hg root
554 555
555 556 print the root (top) of the current working
556 557 directory
557 558
558 559 Print the root directory of the current
559 560 repository.
560 561
561 562 Returns 0 on success.
562 563
563 564 options:
564 565
565 566 -T --template TEMPLATE display with template
566 567
567 568 (some details hidden, use --verbose to show
568 569 complete help)
569 570
570 571 Test help option with version option
571 572
572 573 $ hg add -h --version
573 574 Mercurial Distributed SCM (version *) (glob)
574 575 (see https://mercurial-scm.org for more information)
575 576
576 577 Copyright (C) 2005-* Matt Mackall and others (glob)
577 578 This is free software; see the source for copying conditions. There is NO
578 579 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
579 580
580 581 $ hg add --skjdfks
581 582 hg add: option --skjdfks not recognized
582 583 hg add [OPTION]... [FILE]...
583 584
584 585 add the specified files on the next commit
585 586
586 587 options ([+] can be repeated):
587 588
588 589 -I --include PATTERN [+] include names matching the given patterns
589 590 -X --exclude PATTERN [+] exclude names matching the given patterns
590 591 -S --subrepos recurse into subrepositories
591 592 -n --dry-run do not perform actions, just print output
592 593
593 594 (use 'hg add -h' to show more help)
594 595 [255]
595 596
596 597 Test ambiguous command help
597 598
598 599 $ hg help ad
599 600 list of commands:
600 601
601 602 add add the specified files on the next commit
602 603 addremove add all new files, delete all missing files
603 604
604 605 (use 'hg help -v ad' to show built-in aliases and global options)
605 606
606 607 Test command without options
607 608
608 609 $ hg help verify
609 610 hg verify
610 611
611 612 verify the integrity of the repository
612 613
613 614 Verify the integrity of the current repository.
614 615
615 616 This will perform an extensive check of the repository's integrity,
616 617 validating the hashes and checksums of each entry in the changelog,
617 618 manifest, and tracked files, as well as the integrity of their crosslinks
618 619 and indices.
619 620
620 621 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
621 622 information about recovery from corruption of the repository.
622 623
623 624 Returns 0 on success, 1 if errors are encountered.
624 625
625 626 options:
626 627
627 628 (some details hidden, use --verbose to show complete help)
628 629
629 630 $ hg help diff
630 631 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
631 632
632 633 diff repository (or selected files)
633 634
634 635 Show differences between revisions for the specified files.
635 636
636 637 Differences between files are shown using the unified diff format.
637 638
638 639 Note:
639 640 'hg diff' may generate unexpected results for merges, as it will
640 641 default to comparing against the working directory's first parent
641 642 changeset if no revisions are specified.
642 643
643 644 When two revision arguments are given, then changes are shown between
644 645 those revisions. If only one revision is specified then that revision is
645 646 compared to the working directory, and, when no revisions are specified,
646 647 the working directory files are compared to its first parent.
647 648
648 649 Alternatively you can specify -c/--change with a revision to see the
649 650 changes in that changeset relative to its first parent.
650 651
651 652 Without the -a/--text option, diff will avoid generating diffs of files it
652 653 detects as binary. With -a, diff will generate a diff anyway, probably
653 654 with undesirable results.
654 655
655 656 Use the -g/--git option to generate diffs in the git extended diff format.
656 657 For more information, read 'hg help diffs'.
657 658
658 659 Returns 0 on success.
659 660
660 661 options ([+] can be repeated):
661 662
662 663 -r --rev REV [+] revision
663 664 -c --change REV change made by revision
664 665 -a --text treat all files as text
665 666 -g --git use git extended diff format
666 667 --binary generate binary diffs in git mode (default)
667 668 --nodates omit dates from diff headers
668 669 --noprefix omit a/ and b/ prefixes from filenames
669 670 -p --show-function show which function each change is in
670 671 --reverse produce a diff that undoes the changes
671 672 -w --ignore-all-space ignore white space when comparing lines
672 673 -b --ignore-space-change ignore changes in the amount of white space
673 674 -B --ignore-blank-lines ignore changes whose lines are all blank
674 675 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
675 676 -U --unified NUM number of lines of context to show
676 677 --stat output diffstat-style summary of changes
677 678 --root DIR produce diffs relative to subdirectory
678 679 -I --include PATTERN [+] include names matching the given patterns
679 680 -X --exclude PATTERN [+] exclude names matching the given patterns
680 681 -S --subrepos recurse into subrepositories
681 682
682 683 (some details hidden, use --verbose to show complete help)
683 684
684 685 $ hg help status
685 686 hg status [OPTION]... [FILE]...
686 687
687 688 aliases: st
688 689
689 690 show changed files in the working directory
690 691
691 692 Show status of files in the repository. If names are given, only files
692 693 that match are shown. Files that are clean or ignored or the source of a
693 694 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
694 695 -C/--copies or -A/--all are given. Unless options described with "show
695 696 only ..." are given, the options -mardu are used.
696 697
697 698 Option -q/--quiet hides untracked (unknown and ignored) files unless
698 699 explicitly requested with -u/--unknown or -i/--ignored.
699 700
700 701 Note:
701 702 'hg status' may appear to disagree with diff if permissions have
702 703 changed or a merge has occurred. The standard diff format does not
703 704 report permission changes and diff only reports changes relative to one
704 705 merge parent.
705 706
706 707 If one revision is given, it is used as the base revision. If two
707 708 revisions are given, the differences between them are shown. The --change
708 709 option can also be used as a shortcut to list the changed files of a
709 710 revision from its first parent.
710 711
711 712 The codes used to show the status of files are:
712 713
713 714 M = modified
714 715 A = added
715 716 R = removed
716 717 C = clean
717 718 ! = missing (deleted by non-hg command, but still tracked)
718 719 ? = not tracked
719 720 I = ignored
720 721 = origin of the previous file (with --copies)
721 722
722 723 Returns 0 on success.
723 724
724 725 options ([+] can be repeated):
725 726
726 727 -A --all show status of all files
727 728 -m --modified show only modified files
728 729 -a --added show only added files
729 730 -r --removed show only removed files
730 731 -d --deleted show only deleted (but tracked) files
731 732 -c --clean show only files without changes
732 733 -u --unknown show only unknown (not tracked) files
733 734 -i --ignored show only ignored files
734 735 -n --no-status hide status prefix
735 736 -C --copies show source of copied files
736 737 -0 --print0 end filenames with NUL, for use with xargs
737 738 --rev REV [+] show difference from revision
738 739 --change REV list the changed files of a revision
739 740 -I --include PATTERN [+] include names matching the given patterns
740 741 -X --exclude PATTERN [+] exclude names matching the given patterns
741 742 -S --subrepos recurse into subrepositories
742 743 -T --template TEMPLATE display with template
743 744
744 745 (some details hidden, use --verbose to show complete help)
745 746
746 747 $ hg -q help status
747 748 hg status [OPTION]... [FILE]...
748 749
749 750 show changed files in the working directory
750 751
751 752 $ hg help foo
752 753 abort: no such help topic: foo
753 754 (try 'hg help --keyword foo')
754 755 [255]
755 756
756 757 $ hg skjdfks
757 758 hg: unknown command 'skjdfks'
758 759 (use 'hg help' for a list of commands)
759 760 [255]
760 761
761 762 Typoed command gives suggestion
762 763 $ hg puls
763 764 hg: unknown command 'puls'
764 765 (did you mean one of pull, push?)
765 766 [255]
766 767
767 768 Not enabled extension gets suggested
768 769
769 770 $ hg rebase
770 771 hg: unknown command 'rebase'
771 772 'rebase' is provided by the following extension:
772 773
773 774 rebase command to move sets of revisions to a different ancestor
774 775
775 776 (use 'hg help extensions' for information on enabling extensions)
776 777 [255]
777 778
778 779 Disabled extension gets suggested
779 780 $ hg --config extensions.rebase=! rebase
780 781 hg: unknown command 'rebase'
781 782 'rebase' is provided by the following extension:
782 783
783 784 rebase command to move sets of revisions to a different ancestor
784 785
785 786 (use 'hg help extensions' for information on enabling extensions)
786 787 [255]
787 788
788 789 Make sure that we don't run afoul of the help system thinking that
789 790 this is a section and erroring out weirdly.
790 791
791 792 $ hg .log
792 793 hg: unknown command '.log'
793 794 (did you mean log?)
794 795 [255]
795 796
796 797 $ hg log.
797 798 hg: unknown command 'log.'
798 799 (did you mean log?)
799 800 [255]
800 801 $ hg pu.lh
801 802 hg: unknown command 'pu.lh'
802 803 (did you mean one of pull, push?)
803 804 [255]
804 805
805 806 $ cat > helpext.py <<EOF
806 807 > import os
807 808 > from mercurial import commands, fancyopts, registrar
808 809 >
809 810 > def func(arg):
810 811 > return '%sfoo' % arg
811 812 > class customopt(fancyopts.customopt):
812 813 > def newstate(self, oldstate, newparam, abort):
813 814 > return '%sbar' % oldstate
814 815 > cmdtable = {}
815 816 > command = registrar.command(cmdtable)
816 817 >
817 818 > @command(b'nohelp',
818 819 > [(b'', b'longdesc', 3, b'x'*67),
819 820 > (b'n', b'', None, b'normal desc'),
820 821 > (b'', b'newline', b'', b'line1\nline2'),
821 822 > (b'', b'default-off', False, b'enable X'),
822 823 > (b'', b'default-on', True, b'enable Y'),
823 824 > (b'', b'callableopt', func, b'adds foo'),
824 825 > (b'', b'customopt', customopt(''), b'adds bar'),
825 826 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
826 827 > b'hg nohelp',
827 828 > norepo=True)
828 829 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
829 830 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
830 831 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
831 832 > def nohelp(ui, *args, **kwargs):
832 833 > pass
833 834 >
834 835 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
835 836 > def hashelp(ui, *args, **kwargs):
836 837 > """Extension command's help"""
837 838 >
838 839 > def uisetup(ui):
839 840 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
840 841 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
841 842 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
842 843 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
843 844 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
844 845 >
845 846 > EOF
846 847 $ echo '[extensions]' >> $HGRCPATH
847 848 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
848 849
849 850 Test for aliases
850 851
851 852 $ hg help | grep hgalias
852 853 hgalias My doc
853 854
854 855 $ hg help hgalias
855 856 hg hgalias [--remote]
856 857
857 858 alias for: hg summary
858 859
859 860 My doc
860 861
861 862 defined by: helpext
862 863
863 864 options:
864 865
865 866 --remote check for push and pull
866 867
867 868 (some details hidden, use --verbose to show complete help)
868 869 $ hg help hgaliasnodoc
869 870 hg hgaliasnodoc [--remote]
870 871
871 872 alias for: hg summary
872 873
873 874 summarize working directory state
874 875
875 876 This generates a brief summary of the working directory state, including
876 877 parents, branch, commit status, phase and available updates.
877 878
878 879 With the --remote option, this will check the default paths for incoming
879 880 and outgoing changes. This can be time-consuming.
880 881
881 882 Returns 0 on success.
882 883
883 884 defined by: helpext
884 885
885 886 options:
886 887
887 888 --remote check for push and pull
888 889
889 890 (some details hidden, use --verbose to show complete help)
890 891
891 892 $ hg help shellalias
892 893 hg shellalias
893 894
894 895 shell alias for: echo hi
895 896
896 897 (no help text available)
897 898
898 899 defined by: helpext
899 900
900 901 (some details hidden, use --verbose to show complete help)
901 902
902 903 Test command with no help text
903 904
904 905 $ hg help nohelp
905 906 hg nohelp
906 907
907 908 (no help text available)
908 909
909 910 options:
910 911
911 912 --longdesc VALUE
912 913 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
913 914 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
914 915 -n -- normal desc
915 916 --newline VALUE line1 line2
916 917 --default-off enable X
917 918 --[no-]default-on enable Y (default: on)
918 919 --callableopt VALUE adds foo
919 920 --customopt VALUE adds bar
920 921 --customopt-withdefault VALUE adds bar (default: foo)
921 922
922 923 (some details hidden, use --verbose to show complete help)
923 924
924 925 Test that default list of commands includes extension commands that have help,
925 926 but not those that don't, except in verbose mode, when a keyword is passed, or
926 927 when help about the extension is requested.
927 928
928 929 #if no-extraextensions
929 930
930 931 $ hg help | grep hashelp
931 932 hashelp Extension command's help
932 933 $ hg help | grep nohelp
933 934 [1]
934 935 $ hg help -v | grep nohelp
935 936 nohelp (no help text available)
936 937
937 938 $ hg help -k nohelp
938 939 Commands:
939 940
940 941 nohelp hg nohelp
941 942
942 943 Extension Commands:
943 944
944 945 nohelp (no help text available)
945 946
946 947 $ hg help helpext
947 948 helpext extension - no help text available
948 949
949 950 list of commands:
950 951
951 952 hashelp Extension command's help
952 953 nohelp (no help text available)
953 954
954 955 (use 'hg help -v helpext' to show built-in aliases and global options)
955 956
956 957 #endif
957 958
958 959 Test list of internal help commands
959 960
960 961 $ hg help debug
961 962 debug commands (internal and unsupported):
962 963
963 964 debugancestor
964 965 find the ancestor revision of two revisions in a given index
965 966 debugapplystreamclonebundle
966 967 apply a stream clone bundle file
967 968 debugbuilddag
968 969 builds a repo with a given DAG from scratch in the current
969 970 empty repo
970 971 debugbundle lists the contents of a bundle
971 972 debugcapabilities
972 973 lists the capabilities of a remote peer
973 974 debugcheckstate
974 975 validate the correctness of the current dirstate
975 976 debugcolor show available color, effects or style
976 977 debugcommands
977 978 list all available commands and options
978 979 debugcomplete
979 980 returns the completion list associated with the given command
980 981 debugcreatestreamclonebundle
981 982 create a stream clone bundle file
982 983 debugdag format the changelog or an index DAG as a concise textual
983 984 description
984 985 debugdata dump the contents of a data file revision
985 986 debugdate parse and display a date
986 987 debugdeltachain
987 988 dump information about delta chains in a revlog
988 989 debugdirstate
989 990 show the contents of the current dirstate
990 991 debugdiscovery
991 992 runs the changeset discovery protocol in isolation
992 993 debugdownload
993 994 download a resource using Mercurial logic and config
994 995 debugextensions
995 996 show information about active extensions
996 997 debugfileset parse and apply a fileset specification
997 998 debugformat display format information about the current repository
998 999 debugfsinfo show information detected about current filesystem
999 1000 debuggetbundle
1000 1001 retrieves a bundle from a repo
1001 1002 debugignore display the combined ignore pattern and information about
1002 1003 ignored files
1003 1004 debugindex dump index data for a storage primitive
1004 1005 debugindexdot
1005 1006 dump an index DAG as a graphviz dot file
1006 1007 debugindexstats
1007 1008 show stats related to the changelog index
1008 1009 debuginstall test Mercurial installation
1009 1010 debugknown test whether node ids are known to a repo
1010 1011 debuglocks show or modify state of locks
1011 1012 debugmanifestfulltextcache
1012 1013 show, clear or amend the contents of the manifest fulltext
1013 1014 cache
1014 1015 debugmergestate
1015 1016 print merge state
1016 1017 debugnamecomplete
1017 1018 complete "names" - tags, open branch names, bookmark names
1018 1019 debugobsolete
1019 1020 create arbitrary obsolete marker
1020 1021 debugoptADV (no help text available)
1021 1022 debugoptDEP (no help text available)
1022 1023 debugoptEXP (no help text available)
1023 1024 debugp1copies
1024 1025 dump copy information compared to p1
1025 1026 debugp2copies
1026 1027 dump copy information compared to p2
1027 1028 debugpathcomplete
1028 1029 complete part or all of a tracked path
1029 1030 debugpathcopies
1030 1031 show copies between two revisions
1031 1032 debugpeer establish a connection to a peer repository
1032 1033 debugpickmergetool
1033 1034 examine which merge tool is chosen for specified file
1034 1035 debugpushkey access the pushkey key/value protocol
1035 1036 debugpvec (no help text available)
1036 1037 debugrebuilddirstate
1037 1038 rebuild the dirstate as it would look like for the given
1038 1039 revision
1039 1040 debugrebuildfncache
1040 1041 rebuild the fncache file
1041 1042 debugrename dump rename information
1042 1043 debugrevlog show data and statistics about a revlog
1043 1044 debugrevlogindex
1044 1045 dump the contents of a revlog index
1045 1046 debugrevspec parse and apply a revision specification
1046 1047 debugserve run a server with advanced settings
1047 1048 debugsetparents
1048 1049 manually set the parents of the current working directory
1049 1050 debugssl test a secure connection to a server
1050 1051 debugsub (no help text available)
1051 1052 debugsuccessorssets
1052 1053 show set of successors for revision
1053 1054 debugtemplate
1054 1055 parse and apply a template
1055 1056 debuguigetpass
1056 1057 show prompt to type password
1057 1058 debuguiprompt
1058 1059 show plain prompt
1059 1060 debugupdatecaches
1060 1061 warm all known caches in the repository
1061 1062 debugupgraderepo
1062 1063 upgrade a repository to use different features
1063 1064 debugwalk show how files match on given patterns
1064 1065 debugwhyunstable
1065 1066 explain instabilities of a changeset
1066 1067 debugwireargs
1067 1068 (no help text available)
1068 1069 debugwireproto
1069 1070 send wire protocol commands to a server
1070 1071
1071 1072 (use 'hg help -v debug' to show built-in aliases and global options)
1072 1073
1073 1074 internals topic renders index of available sub-topics
1074 1075
1075 1076 $ hg help internals
1076 1077 Technical implementation topics
1077 1078 """""""""""""""""""""""""""""""
1078 1079
1079 1080 To access a subtopic, use "hg help internals.{subtopic-name}"
1080 1081
1081 1082 bundle2 Bundle2
1082 1083 bundles Bundles
1083 1084 cbor CBOR
1084 1085 censor Censor
1085 1086 changegroups Changegroups
1086 1087 config Config Registrar
1087 1088 extensions Extension API
1088 1089 mergestate Mergestate
1089 1090 requirements Repository Requirements
1090 1091 revlogs Revision Logs
1091 1092 wireprotocol Wire Protocol
1092 1093 wireprotocolrpc
1093 1094 Wire Protocol RPC
1094 1095 wireprotocolv2
1095 1096 Wire Protocol Version 2
1096 1097
1097 1098 sub-topics can be accessed
1098 1099
1099 1100 $ hg help internals.changegroups
1100 1101 Changegroups
1101 1102 """"""""""""
1102 1103
1103 1104 Changegroups are representations of repository revlog data, specifically
1104 1105 the changelog data, root/flat manifest data, treemanifest data, and
1105 1106 filelogs.
1106 1107
1107 1108 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1108 1109 level, versions "1" and "2" are almost exactly the same, with the only
1109 1110 difference being an additional item in the *delta header*. Version "3"
1110 1111 adds support for storage flags in the *delta header* and optionally
1111 1112 exchanging treemanifests (enabled by setting an option on the
1112 1113 "changegroup" part in the bundle2).
1113 1114
1114 1115 Changegroups when not exchanging treemanifests consist of 3 logical
1115 1116 segments:
1116 1117
1117 1118 +---------------------------------+
1118 1119 | | | |
1119 1120 | changeset | manifest | filelogs |
1120 1121 | | | |
1121 1122 | | | |
1122 1123 +---------------------------------+
1123 1124
1124 1125 When exchanging treemanifests, there are 4 logical segments:
1125 1126
1126 1127 +-------------------------------------------------+
1127 1128 | | | | |
1128 1129 | changeset | root | treemanifests | filelogs |
1129 1130 | | manifest | | |
1130 1131 | | | | |
1131 1132 +-------------------------------------------------+
1132 1133
1133 1134 The principle building block of each segment is a *chunk*. A *chunk* is a
1134 1135 framed piece of data:
1135 1136
1136 1137 +---------------------------------------+
1137 1138 | | |
1138 1139 | length | data |
1139 1140 | (4 bytes) | (<length - 4> bytes) |
1140 1141 | | |
1141 1142 +---------------------------------------+
1142 1143
1143 1144 All integers are big-endian signed integers. Each chunk starts with a
1144 1145 32-bit integer indicating the length of the entire chunk (including the
1145 1146 length field itself).
1146 1147
1147 1148 There is a special case chunk that has a value of 0 for the length
1148 1149 ("0x00000000"). We call this an *empty chunk*.
1149 1150
1150 1151 Delta Groups
1151 1152 ============
1152 1153
1153 1154 A *delta group* expresses the content of a revlog as a series of deltas,
1154 1155 or patches against previous revisions.
1155 1156
1156 1157 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1157 1158 to signal the end of the delta group:
1158 1159
1159 1160 +------------------------------------------------------------------------+
1160 1161 | | | | | |
1161 1162 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1162 1163 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1163 1164 | | | | | |
1164 1165 +------------------------------------------------------------------------+
1165 1166
1166 1167 Each *chunk*'s data consists of the following:
1167 1168
1168 1169 +---------------------------------------+
1169 1170 | | |
1170 1171 | delta header | delta data |
1171 1172 | (various by version) | (various) |
1172 1173 | | |
1173 1174 +---------------------------------------+
1174 1175
1175 1176 The *delta data* is a series of *delta*s that describe a diff from an
1176 1177 existing entry (either that the recipient already has, or previously
1177 1178 specified in the bundle/changegroup).
1178 1179
1179 1180 The *delta header* is different between versions "1", "2", and "3" of the
1180 1181 changegroup format.
1181 1182
1182 1183 Version 1 (headerlen=80):
1183 1184
1184 1185 +------------------------------------------------------+
1185 1186 | | | | |
1186 1187 | node | p1 node | p2 node | link node |
1187 1188 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1188 1189 | | | | |
1189 1190 +------------------------------------------------------+
1190 1191
1191 1192 Version 2 (headerlen=100):
1192 1193
1193 1194 +------------------------------------------------------------------+
1194 1195 | | | | | |
1195 1196 | node | p1 node | p2 node | base node | link node |
1196 1197 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1197 1198 | | | | | |
1198 1199 +------------------------------------------------------------------+
1199 1200
1200 1201 Version 3 (headerlen=102):
1201 1202
1202 1203 +------------------------------------------------------------------------------+
1203 1204 | | | | | | |
1204 1205 | node | p1 node | p2 node | base node | link node | flags |
1205 1206 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1206 1207 | | | | | | |
1207 1208 +------------------------------------------------------------------------------+
1208 1209
1209 1210 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1210 1211 contain a series of *delta*s, densely packed (no separators). These deltas
1211 1212 describe a diff from an existing entry (either that the recipient already
1212 1213 has, or previously specified in the bundle/changegroup). The format is
1213 1214 described more fully in "hg help internals.bdiff", but briefly:
1214 1215
1215 1216 +---------------------------------------------------------------+
1216 1217 | | | | |
1217 1218 | start offset | end offset | new length | content |
1218 1219 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1219 1220 | | | | |
1220 1221 +---------------------------------------------------------------+
1221 1222
1222 1223 Please note that the length field in the delta data does *not* include
1223 1224 itself.
1224 1225
1225 1226 In version 1, the delta is always applied against the previous node from
1226 1227 the changegroup or the first parent if this is the first entry in the
1227 1228 changegroup.
1228 1229
1229 1230 In version 2 and up, the delta base node is encoded in the entry in the
1230 1231 changegroup. This allows the delta to be expressed against any parent,
1231 1232 which can result in smaller deltas and more efficient encoding of data.
1232 1233
1233 1234 The *flags* field holds bitwise flags affecting the processing of revision
1234 1235 data. The following flags are defined:
1235 1236
1236 1237 32768
1237 1238 Censored revision. The revision's fulltext has been replaced by censor
1238 1239 metadata. May only occur on file revisions.
1239 1240
1240 1241 16384
1241 1242 Ellipsis revision. Revision hash does not match data (likely due to
1242 1243 rewritten parents).
1243 1244
1244 1245 8192
1245 1246 Externally stored. The revision fulltext contains "key:value" "\n"
1246 1247 delimited metadata defining an object stored elsewhere. Used by the LFS
1247 1248 extension.
1248 1249
1249 1250 For historical reasons, the integer values are identical to revlog version
1250 1251 1 per-revision storage flags and correspond to bits being set in this
1251 1252 2-byte field. Bits were allocated starting from the most-significant bit,
1252 1253 hence the reverse ordering and allocation of these flags.
1253 1254
1254 1255 Changeset Segment
1255 1256 =================
1256 1257
1257 1258 The *changeset segment* consists of a single *delta group* holding
1258 1259 changelog data. The *empty chunk* at the end of the *delta group* denotes
1259 1260 the boundary to the *manifest segment*.
1260 1261
1261 1262 Manifest Segment
1262 1263 ================
1263 1264
1264 1265 The *manifest segment* consists of a single *delta group* holding manifest
1265 1266 data. If treemanifests are in use, it contains only the manifest for the
1266 1267 root directory of the repository. Otherwise, it contains the entire
1267 1268 manifest data. The *empty chunk* at the end of the *delta group* denotes
1268 1269 the boundary to the next segment (either the *treemanifests segment* or
1269 1270 the *filelogs segment*, depending on version and the request options).
1270 1271
1271 1272 Treemanifests Segment
1272 1273 ---------------------
1273 1274
1274 1275 The *treemanifests segment* only exists in changegroup version "3", and
1275 1276 only if the 'treemanifest' param is part of the bundle2 changegroup part
1276 1277 (it is not possible to use changegroup version 3 outside of bundle2).
1277 1278 Aside from the filenames in the *treemanifests segment* containing a
1278 1279 trailing "/" character, it behaves identically to the *filelogs segment*
1279 1280 (see below). The final sub-segment is followed by an *empty chunk*
1280 1281 (logically, a sub-segment with filename size 0). This denotes the boundary
1281 1282 to the *filelogs segment*.
1282 1283
1283 1284 Filelogs Segment
1284 1285 ================
1285 1286
1286 1287 The *filelogs segment* consists of multiple sub-segments, each
1287 1288 corresponding to an individual file whose data is being described:
1288 1289
1289 1290 +--------------------------------------------------+
1290 1291 | | | | | |
1291 1292 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1292 1293 | | | | | (4 bytes) |
1293 1294 | | | | | |
1294 1295 +--------------------------------------------------+
1295 1296
1296 1297 The final filelog sub-segment is followed by an *empty chunk* (logically,
1297 1298 a sub-segment with filename size 0). This denotes the end of the segment
1298 1299 and of the overall changegroup.
1299 1300
1300 1301 Each filelog sub-segment consists of the following:
1301 1302
1302 1303 +------------------------------------------------------+
1303 1304 | | | |
1304 1305 | filename length | filename | delta group |
1305 1306 | (4 bytes) | (<length - 4> bytes) | (various) |
1306 1307 | | | |
1307 1308 +------------------------------------------------------+
1308 1309
1309 1310 That is, a *chunk* consisting of the filename (not terminated or padded)
1310 1311 followed by N chunks constituting the *delta group* for this file. The
1311 1312 *empty chunk* at the end of each *delta group* denotes the boundary to the
1312 1313 next filelog sub-segment.
1313 1314
1314 1315 non-existent subtopics print an error
1315 1316
1316 1317 $ hg help internals.foo
1317 1318 abort: no such help topic: internals.foo
1318 1319 (try 'hg help --keyword foo')
1319 1320 [255]
1320 1321
1321 1322 test advanced, deprecated and experimental options are hidden in command help
1322 1323 $ hg help debugoptADV
1323 1324 hg debugoptADV
1324 1325
1325 1326 (no help text available)
1326 1327
1327 1328 options:
1328 1329
1329 1330 (some details hidden, use --verbose to show complete help)
1330 1331 $ hg help debugoptDEP
1331 1332 hg debugoptDEP
1332 1333
1333 1334 (no help text available)
1334 1335
1335 1336 options:
1336 1337
1337 1338 (some details hidden, use --verbose to show complete help)
1338 1339
1339 1340 $ hg help debugoptEXP
1340 1341 hg debugoptEXP
1341 1342
1342 1343 (no help text available)
1343 1344
1344 1345 options:
1345 1346
1346 1347 (some details hidden, use --verbose to show complete help)
1347 1348
1348 1349 test advanced, deprecated and experimental options are shown with -v
1349 1350 $ hg help -v debugoptADV | grep aopt
1350 1351 --aopt option is (ADVANCED)
1351 1352 $ hg help -v debugoptDEP | grep dopt
1352 1353 --dopt option is (DEPRECATED)
1353 1354 $ hg help -v debugoptEXP | grep eopt
1354 1355 --eopt option is (EXPERIMENTAL)
1355 1356
1356 1357 #if gettext
1357 1358 test deprecated option is hidden with translation with untranslated description
1358 1359 (use many globy for not failing on changed transaction)
1359 1360 $ LANGUAGE=sv hg help debugoptDEP
1360 1361 hg debugoptDEP
1361 1362
1362 1363 (*) (glob)
1363 1364
1364 1365 options:
1365 1366
1366 1367 (some details hidden, use --verbose to show complete help)
1367 1368 #endif
1368 1369
1369 1370 Test commands that collide with topics (issue4240)
1370 1371
1371 1372 $ hg config -hq
1372 1373 hg config [-u] [NAME]...
1373 1374
1374 1375 show combined config settings from all hgrc files
1375 1376 $ hg showconfig -hq
1376 1377 hg config [-u] [NAME]...
1377 1378
1378 1379 show combined config settings from all hgrc files
1379 1380
1380 1381 Test a help topic
1381 1382
1382 1383 $ hg help dates
1383 1384 Date Formats
1384 1385 """"""""""""
1385 1386
1386 1387 Some commands allow the user to specify a date, e.g.:
1387 1388
1388 1389 - backout, commit, import, tag: Specify the commit date.
1389 1390 - log, revert, update: Select revision(s) by date.
1390 1391
1391 1392 Many date formats are valid. Here are some examples:
1392 1393
1393 1394 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1394 1395 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1395 1396 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1396 1397 - "Dec 6" (midnight)
1397 1398 - "13:18" (today assumed)
1398 1399 - "3:39" (3:39AM assumed)
1399 1400 - "3:39pm" (15:39)
1400 1401 - "2006-12-06 13:18:29" (ISO 8601 format)
1401 1402 - "2006-12-6 13:18"
1402 1403 - "2006-12-6"
1403 1404 - "12-6"
1404 1405 - "12/6"
1405 1406 - "12/6/6" (Dec 6 2006)
1406 1407 - "today" (midnight)
1407 1408 - "yesterday" (midnight)
1408 1409 - "now" - right now
1409 1410
1410 1411 Lastly, there is Mercurial's internal format:
1411 1412
1412 1413 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1413 1414
1414 1415 This is the internal representation format for dates. The first number is
1415 1416 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1416 1417 is the offset of the local timezone, in seconds west of UTC (negative if
1417 1418 the timezone is east of UTC).
1418 1419
1419 1420 The log command also accepts date ranges:
1420 1421
1421 1422 - "<DATE" - at or before a given date/time
1422 1423 - ">DATE" - on or after a given date/time
1423 1424 - "DATE to DATE" - a date range, inclusive
1424 1425 - "-DAYS" - within a given number of days of today
1425 1426
1426 1427 Test repeated config section name
1427 1428
1428 1429 $ hg help config.host
1429 1430 "http_proxy.host"
1430 1431 Host name and (optional) port of the proxy server, for example
1431 1432 "myproxy:8000".
1432 1433
1433 1434 "smtp.host"
1434 1435 Host name of mail server, e.g. "mail.example.com".
1435 1436
1436 1437
1437 1438 Test section name with dot
1438 1439
1439 1440 $ hg help config.ui.username
1440 1441 "ui.username"
1441 1442 The committer of a changeset created when running "commit". Typically
1442 1443 a person's name and email address, e.g. "Fred Widget
1443 1444 <fred@example.com>". Environment variables in the username are
1444 1445 expanded.
1445 1446
1446 1447 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1447 1448 empty, e.g. if the system admin set "username =" in the system hgrc,
1448 1449 it has to be specified manually or in a different hgrc file)
1449 1450
1450 1451
1451 1452 $ hg help config.annotate.git
1452 1453 abort: help section not found: config.annotate.git
1453 1454 [255]
1454 1455
1455 1456 $ hg help config.update.check
1456 1457 "commands.update.check"
1457 1458 Determines what level of checking 'hg update' will perform before
1458 1459 moving to a destination revision. Valid values are "abort", "none",
1459 1460 "linear", and "noconflict". "abort" always fails if the working
1460 1461 directory has uncommitted changes. "none" performs no checking, and
1461 1462 may result in a merge with uncommitted changes. "linear" allows any
1462 1463 update as long as it follows a straight line in the revision history,
1463 1464 and may trigger a merge with uncommitted changes. "noconflict" will
1464 1465 allow any update which would not trigger a merge with uncommitted
1465 1466 changes, if any are present. (default: "linear")
1466 1467
1467 1468
1468 1469 $ hg help config.commands.update.check
1469 1470 "commands.update.check"
1470 1471 Determines what level of checking 'hg update' will perform before
1471 1472 moving to a destination revision. Valid values are "abort", "none",
1472 1473 "linear", and "noconflict". "abort" always fails if the working
1473 1474 directory has uncommitted changes. "none" performs no checking, and
1474 1475 may result in a merge with uncommitted changes. "linear" allows any
1475 1476 update as long as it follows a straight line in the revision history,
1476 1477 and may trigger a merge with uncommitted changes. "noconflict" will
1477 1478 allow any update which would not trigger a merge with uncommitted
1478 1479 changes, if any are present. (default: "linear")
1479 1480
1480 1481
1481 1482 $ hg help config.ommands.update.check
1482 1483 abort: help section not found: config.ommands.update.check
1483 1484 [255]
1484 1485
1485 1486 Unrelated trailing paragraphs shouldn't be included
1486 1487
1487 1488 $ hg help config.extramsg | grep '^$'
1488 1489
1489 1490
1490 1491 Test capitalized section name
1491 1492
1492 1493 $ hg help scripting.HGPLAIN > /dev/null
1493 1494
1494 1495 Help subsection:
1495 1496
1496 1497 $ hg help config.charsets |grep "Email example:" > /dev/null
1497 1498 [1]
1498 1499
1499 1500 Show nested definitions
1500 1501 ("profiling.type"[break]"ls"[break]"stat"[break])
1501 1502
1502 1503 $ hg help config.type | egrep '^$'|wc -l
1503 1504 \s*3 (re)
1504 1505
1505 1506 $ hg help config.profiling.type.ls
1506 1507 "profiling.type.ls"
1507 1508 Use Python's built-in instrumenting profiler. This profiler works on
1508 1509 all platforms, but each line number it reports is the first line of
1509 1510 a function. This restriction makes it difficult to identify the
1510 1511 expensive parts of a non-trivial function.
1511 1512
1512 1513
1513 1514 Separate sections from subsections
1514 1515
1515 1516 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1516 1517 "format"
1517 1518 --------
1518 1519
1519 1520 "usegeneraldelta"
1520 1521
1521 1522 "dotencode"
1522 1523
1523 1524 "usefncache"
1524 1525
1525 1526 "usestore"
1526 1527
1527 1528 "sparse-revlog"
1528 1529
1529 1530 "revlog-compression"
1530 1531
1531 1532 "bookmarks-in-store"
1532 1533
1533 1534 "profiling"
1534 1535 -----------
1535 1536
1536 1537 "format"
1537 1538
1538 1539 "progress"
1539 1540 ----------
1540 1541
1541 1542 "format"
1542 1543
1543 1544
1544 1545 Last item in help config.*:
1545 1546
1546 1547 $ hg help config.`hg help config|grep '^ "'| \
1547 1548 > tail -1|sed 's![ "]*!!g'`| \
1548 1549 > grep 'hg help -c config' > /dev/null
1549 1550 [1]
1550 1551
1551 1552 note to use help -c for general hg help config:
1552 1553
1553 1554 $ hg help config |grep 'hg help -c config' > /dev/null
1554 1555
1555 1556 Test templating help
1556 1557
1557 1558 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1558 1559 desc String. The text of the changeset description.
1559 1560 diffstat String. Statistics of changes with the following format:
1560 1561 firstline Any text. Returns the first line of text.
1561 1562 nonempty Any text. Returns '(none)' if the string is empty.
1562 1563
1563 1564 Test deprecated items
1564 1565
1565 1566 $ hg help -v templating | grep currentbookmark
1566 1567 currentbookmark
1567 1568 $ hg help templating | (grep currentbookmark || true)
1568 1569
1569 1570 Test help hooks
1570 1571
1571 1572 $ cat > helphook1.py <<EOF
1572 1573 > from mercurial import help
1573 1574 >
1574 1575 > def rewrite(ui, topic, doc):
1575 1576 > return doc + b'\nhelphook1\n'
1576 1577 >
1577 1578 > def extsetup(ui):
1578 1579 > help.addtopichook(b'revisions', rewrite)
1579 1580 > EOF
1580 1581 $ cat > helphook2.py <<EOF
1581 1582 > from mercurial import help
1582 1583 >
1583 1584 > def rewrite(ui, topic, doc):
1584 1585 > return doc + b'\nhelphook2\n'
1585 1586 >
1586 1587 > def extsetup(ui):
1587 1588 > help.addtopichook(b'revisions', rewrite)
1588 1589 > EOF
1589 1590 $ echo '[extensions]' >> $HGRCPATH
1590 1591 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1591 1592 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1592 1593 $ hg help revsets | grep helphook
1593 1594 helphook1
1594 1595 helphook2
1595 1596
1596 1597 help -c should only show debug --debug
1597 1598
1598 1599 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1599 1600 [1]
1600 1601
1601 1602 help -c should only show deprecated for -v
1602 1603
1603 1604 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1604 1605 [1]
1605 1606
1606 1607 Test -s / --system
1607 1608
1608 1609 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1609 1610 > wc -l | sed -e 's/ //g'
1610 1611 0
1611 1612 $ hg help config.files --system unix | grep 'USER' | \
1612 1613 > wc -l | sed -e 's/ //g'
1613 1614 0
1614 1615
1615 1616 Test -e / -c / -k combinations
1616 1617
1617 1618 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1618 1619 Commands:
1619 1620 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1620 1621 Extensions:
1621 1622 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1622 1623 Topics:
1623 1624 Commands:
1624 1625 Extensions:
1625 1626 Extension Commands:
1626 1627 $ hg help -c schemes
1627 1628 abort: no such help topic: schemes
1628 1629 (try 'hg help --keyword schemes')
1629 1630 [255]
1630 1631 $ hg help -e schemes |head -1
1631 1632 schemes extension - extend schemes with shortcuts to repository swarms
1632 1633 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1633 1634 Commands:
1634 1635 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1635 1636 Extensions:
1636 1637 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1637 1638 Extensions:
1638 1639 Commands:
1639 1640 $ hg help -c commit > /dev/null
1640 1641 $ hg help -e -c commit > /dev/null
1641 1642 $ hg help -e commit
1642 1643 abort: no such help topic: commit
1643 1644 (try 'hg help --keyword commit')
1644 1645 [255]
1645 1646
1646 1647 Test keyword search help
1647 1648
1648 1649 $ cat > prefixedname.py <<EOF
1649 1650 > '''matched against word "clone"
1650 1651 > '''
1651 1652 > EOF
1652 1653 $ echo '[extensions]' >> $HGRCPATH
1653 1654 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1654 1655 $ hg help -k clone
1655 1656 Topics:
1656 1657
1657 1658 config Configuration Files
1658 1659 extensions Using Additional Features
1659 1660 glossary Glossary
1660 1661 phases Working with Phases
1661 1662 subrepos Subrepositories
1662 1663 urls URL Paths
1663 1664
1664 1665 Commands:
1665 1666
1666 1667 bookmarks create a new bookmark or list existing bookmarks
1667 1668 clone make a copy of an existing repository
1668 1669 paths show aliases for remote repositories
1669 1670 pull pull changes from the specified source
1670 1671 update update working directory (or switch revisions)
1671 1672
1672 1673 Extensions:
1673 1674
1674 1675 clonebundles advertise pre-generated bundles to seed clones
1675 1676 narrow create clones which fetch history data for subset of files
1676 1677 (EXPERIMENTAL)
1677 1678 prefixedname matched against word "clone"
1678 1679 relink recreates hardlinks between repository clones
1679 1680
1680 1681 Extension Commands:
1681 1682
1682 1683 qclone clone main and patch repository at same time
1683 1684
1684 1685 Test unfound topic
1685 1686
1686 1687 $ hg help nonexistingtopicthatwillneverexisteverever
1687 1688 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1688 1689 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1689 1690 [255]
1690 1691
1691 1692 Test unfound keyword
1692 1693
1693 1694 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1694 1695 abort: no matches
1695 1696 (try 'hg help' for a list of topics)
1696 1697 [255]
1697 1698
1698 1699 Test omit indicating for help
1699 1700
1700 1701 $ cat > addverboseitems.py <<EOF
1701 1702 > r'''extension to test omit indicating.
1702 1703 >
1703 1704 > This paragraph is never omitted (for extension)
1704 1705 >
1705 1706 > .. container:: verbose
1706 1707 >
1707 1708 > This paragraph is omitted,
1708 1709 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1709 1710 >
1710 1711 > This paragraph is never omitted, too (for extension)
1711 1712 > '''
1712 1713 > from __future__ import absolute_import
1713 1714 > from mercurial import commands, help
1714 1715 > testtopic = br"""This paragraph is never omitted (for topic).
1715 1716 >
1716 1717 > .. container:: verbose
1717 1718 >
1718 1719 > This paragraph is omitted,
1719 1720 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1720 1721 >
1721 1722 > This paragraph is never omitted, too (for topic)
1722 1723 > """
1723 1724 > def extsetup(ui):
1724 1725 > help.helptable.append(([b"topic-containing-verbose"],
1725 1726 > b"This is the topic to test omit indicating.",
1726 1727 > lambda ui: testtopic))
1727 1728 > EOF
1728 1729 $ echo '[extensions]' >> $HGRCPATH
1729 1730 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1730 1731 $ hg help addverboseitems
1731 1732 addverboseitems extension - extension to test omit indicating.
1732 1733
1733 1734 This paragraph is never omitted (for extension)
1734 1735
1735 1736 This paragraph is never omitted, too (for extension)
1736 1737
1737 1738 (some details hidden, use --verbose to show complete help)
1738 1739
1739 1740 no commands defined
1740 1741 $ hg help -v addverboseitems
1741 1742 addverboseitems extension - extension to test omit indicating.
1742 1743
1743 1744 This paragraph is never omitted (for extension)
1744 1745
1745 1746 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1746 1747 extension)
1747 1748
1748 1749 This paragraph is never omitted, too (for extension)
1749 1750
1750 1751 no commands defined
1751 1752 $ hg help topic-containing-verbose
1752 1753 This is the topic to test omit indicating.
1753 1754 """"""""""""""""""""""""""""""""""""""""""
1754 1755
1755 1756 This paragraph is never omitted (for topic).
1756 1757
1757 1758 This paragraph is never omitted, too (for topic)
1758 1759
1759 1760 (some details hidden, use --verbose to show complete help)
1760 1761 $ hg help -v topic-containing-verbose
1761 1762 This is the topic to test omit indicating.
1762 1763 """"""""""""""""""""""""""""""""""""""""""
1763 1764
1764 1765 This paragraph is never omitted (for topic).
1765 1766
1766 1767 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1767 1768 topic)
1768 1769
1769 1770 This paragraph is never omitted, too (for topic)
1770 1771
1771 1772 Test section lookup
1772 1773
1773 1774 $ hg help revset.merge
1774 1775 "merge()"
1775 1776 Changeset is a merge changeset.
1776 1777
1777 1778 $ hg help glossary.dag
1778 1779 DAG
1779 1780 The repository of changesets of a distributed version control system
1780 1781 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1781 1782 of nodes and edges, where nodes correspond to changesets and edges
1782 1783 imply a parent -> child relation. This graph can be visualized by
1783 1784 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1784 1785 limited by the requirement for children to have at most two parents.
1785 1786
1786 1787
1787 1788 $ hg help hgrc.paths
1788 1789 "paths"
1789 1790 -------
1790 1791
1791 1792 Assigns symbolic names and behavior to repositories.
1792 1793
1793 1794 Options are symbolic names defining the URL or directory that is the
1794 1795 location of the repository. Example:
1795 1796
1796 1797 [paths]
1797 1798 my_server = https://example.com/my_repo
1798 1799 local_path = /home/me/repo
1799 1800
1800 1801 These symbolic names can be used from the command line. To pull from
1801 1802 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1802 1803 local_path'.
1803 1804
1804 1805 Options containing colons (":") denote sub-options that can influence
1805 1806 behavior for that specific path. Example:
1806 1807
1807 1808 [paths]
1808 1809 my_server = https://example.com/my_path
1809 1810 my_server:pushurl = ssh://example.com/my_path
1810 1811
1811 1812 The following sub-options can be defined:
1812 1813
1813 1814 "pushurl"
1814 1815 The URL to use for push operations. If not defined, the location
1815 1816 defined by the path's main entry is used.
1816 1817
1817 1818 "pushrev"
1818 1819 A revset defining which revisions to push by default.
1819 1820
1820 1821 When 'hg push' is executed without a "-r" argument, the revset defined
1821 1822 by this sub-option is evaluated to determine what to push.
1822 1823
1823 1824 For example, a value of "." will push the working directory's revision
1824 1825 by default.
1825 1826
1826 1827 Revsets specifying bookmarks will not result in the bookmark being
1827 1828 pushed.
1828 1829
1829 1830 The following special named paths exist:
1830 1831
1831 1832 "default"
1832 1833 The URL or directory to use when no source or remote is specified.
1833 1834
1834 1835 'hg clone' will automatically define this path to the location the
1835 1836 repository was cloned from.
1836 1837
1837 1838 "default-push"
1838 1839 (deprecated) The URL or directory for the default 'hg push' location.
1839 1840 "default:pushurl" should be used instead.
1840 1841
1841 1842 $ hg help glossary.mcguffin
1842 1843 abort: help section not found: glossary.mcguffin
1843 1844 [255]
1844 1845
1845 1846 $ hg help glossary.mc.guffin
1846 1847 abort: help section not found: glossary.mc.guffin
1847 1848 [255]
1848 1849
1849 1850 $ hg help template.files
1850 1851 files List of strings. All files modified, added, or removed by
1851 1852 this changeset.
1852 1853 files(pattern)
1853 1854 All files of the current changeset matching the pattern. See
1854 1855 'hg help patterns'.
1855 1856
1856 1857 Test section lookup by translated message
1857 1858
1858 1859 str.lower() instead of encoding.lower(str) on translated message might
1859 1860 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1860 1861 as the second or later byte of multi-byte character.
1861 1862
1862 1863 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1863 1864 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1864 1865 replacement makes message meaningless.
1865 1866
1866 1867 This tests that section lookup by translated string isn't broken by
1867 1868 such str.lower().
1868 1869
1869 1870 $ "$PYTHON" <<EOF
1870 1871 > def escape(s):
1871 1872 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1872 1873 > # translation of "record" in ja_JP.cp932
1873 1874 > upper = b"\x8bL\x98^"
1874 1875 > # str.lower()-ed section name should be treated as different one
1875 1876 > lower = b"\x8bl\x98^"
1876 1877 > with open('ambiguous.py', 'wb') as fp:
1877 1878 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1878 1879 > u'''summary of extension
1879 1880 >
1880 1881 > %s
1881 1882 > ----
1882 1883 >
1883 1884 > Upper name should show only this message
1884 1885 >
1885 1886 > %s
1886 1887 > ----
1887 1888 >
1888 1889 > Lower name should show only this message
1889 1890 >
1890 1891 > subsequent section
1891 1892 > ------------------
1892 1893 >
1893 1894 > This should be hidden at 'hg help ambiguous' with section name.
1894 1895 > '''
1895 1896 > """ % (escape(upper), escape(lower)))
1896 1897 > EOF
1897 1898
1898 1899 $ cat >> $HGRCPATH <<EOF
1899 1900 > [extensions]
1900 1901 > ambiguous = ./ambiguous.py
1901 1902 > EOF
1902 1903
1903 1904 $ "$PYTHON" <<EOF | sh
1904 1905 > from mercurial import pycompat
1905 1906 > upper = b"\x8bL\x98^"
1906 1907 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1907 1908 > EOF
1908 1909 \x8bL\x98^ (esc)
1909 1910 ----
1910 1911
1911 1912 Upper name should show only this message
1912 1913
1913 1914
1914 1915 $ "$PYTHON" <<EOF | sh
1915 1916 > from mercurial import pycompat
1916 1917 > lower = b"\x8bl\x98^"
1917 1918 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1918 1919 > EOF
1919 1920 \x8bl\x98^ (esc)
1920 1921 ----
1921 1922
1922 1923 Lower name should show only this message
1923 1924
1924 1925
1925 1926 $ cat >> $HGRCPATH <<EOF
1926 1927 > [extensions]
1927 1928 > ambiguous = !
1928 1929 > EOF
1929 1930
1930 1931 Show help content of disabled extensions
1931 1932
1932 1933 $ cat >> $HGRCPATH <<EOF
1933 1934 > [extensions]
1934 1935 > ambiguous = !./ambiguous.py
1935 1936 > EOF
1936 1937 $ hg help -e ambiguous
1937 1938 ambiguous extension - (no help text available)
1938 1939
1939 1940 (use 'hg help extensions' for information on enabling extensions)
1940 1941
1941 1942 Test dynamic list of merge tools only shows up once
1942 1943 $ hg help merge-tools
1943 1944 Merge Tools
1944 1945 """""""""""
1945 1946
1946 1947 To merge files Mercurial uses merge tools.
1947 1948
1948 1949 A merge tool combines two different versions of a file into a merged file.
1949 1950 Merge tools are given the two files and the greatest common ancestor of
1950 1951 the two file versions, so they can determine the changes made on both
1951 1952 branches.
1952 1953
1953 1954 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1954 1955 backout' and in several extensions.
1955 1956
1956 1957 Usually, the merge tool tries to automatically reconcile the files by
1957 1958 combining all non-overlapping changes that occurred separately in the two
1958 1959 different evolutions of the same initial base file. Furthermore, some
1959 1960 interactive merge programs make it easier to manually resolve conflicting
1960 1961 merges, either in a graphical way, or by inserting some conflict markers.
1961 1962 Mercurial does not include any interactive merge programs but relies on
1962 1963 external tools for that.
1963 1964
1964 1965 Available merge tools
1965 1966 =====================
1966 1967
1967 1968 External merge tools and their properties are configured in the merge-
1968 1969 tools configuration section - see hgrc(5) - but they can often just be
1969 1970 named by their executable.
1970 1971
1971 1972 A merge tool is generally usable if its executable can be found on the
1972 1973 system and if it can handle the merge. The executable is found if it is an
1973 1974 absolute or relative executable path or the name of an application in the
1974 1975 executable search path. The tool is assumed to be able to handle the merge
1975 1976 if it can handle symlinks if the file is a symlink, if it can handle
1976 1977 binary files if the file is binary, and if a GUI is available if the tool
1977 1978 requires a GUI.
1978 1979
1979 1980 There are some internal merge tools which can be used. The internal merge
1980 1981 tools are:
1981 1982
1982 1983 ":dump"
1983 1984 Creates three versions of the files to merge, containing the contents of
1984 1985 local, other and base. These files can then be used to perform a merge
1985 1986 manually. If the file to be merged is named "a.txt", these files will
1986 1987 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1987 1988 they will be placed in the same directory as "a.txt".
1988 1989
1989 1990 This implies premerge. Therefore, files aren't dumped, if premerge runs
1990 1991 successfully. Use :forcedump to forcibly write files out.
1991 1992
1992 1993 (actual capabilities: binary, symlink)
1993 1994
1994 1995 ":fail"
1995 1996 Rather than attempting to merge files that were modified on both
1996 1997 branches, it marks them as unresolved. The resolve command must be used
1997 1998 to resolve these conflicts.
1998 1999
1999 2000 (actual capabilities: binary, symlink)
2000 2001
2001 2002 ":forcedump"
2002 2003 Creates three versions of the files as same as :dump, but omits
2003 2004 premerge.
2004 2005
2005 2006 (actual capabilities: binary, symlink)
2006 2007
2007 2008 ":local"
2008 2009 Uses the local 'p1()' version of files as the merged version.
2009 2010
2010 2011 (actual capabilities: binary, symlink)
2011 2012
2012 2013 ":merge"
2013 2014 Uses the internal non-interactive simple merge algorithm for merging
2014 2015 files. It will fail if there are any conflicts and leave markers in the
2015 2016 partially merged file. Markers will have two sections, one for each side
2016 2017 of merge.
2017 2018
2018 2019 ":merge-local"
2019 2020 Like :merge, but resolve all conflicts non-interactively in favor of the
2020 2021 local 'p1()' changes.
2021 2022
2022 2023 ":merge-other"
2023 2024 Like :merge, but resolve all conflicts non-interactively in favor of the
2024 2025 other 'p2()' changes.
2025 2026
2026 2027 ":merge3"
2027 2028 Uses the internal non-interactive simple merge algorithm for merging
2028 2029 files. It will fail if there are any conflicts and leave markers in the
2029 2030 partially merged file. Marker will have three sections, one from each
2030 2031 side of the merge and one for the base content.
2031 2032
2032 2033 ":other"
2033 2034 Uses the other 'p2()' version of files as the merged version.
2034 2035
2035 2036 (actual capabilities: binary, symlink)
2036 2037
2037 2038 ":prompt"
2038 2039 Asks the user which of the local 'p1()' or the other 'p2()' version to
2039 2040 keep as the merged version.
2040 2041
2041 2042 (actual capabilities: binary, symlink)
2042 2043
2043 2044 ":tagmerge"
2044 2045 Uses the internal tag merge algorithm (experimental).
2045 2046
2046 2047 ":union"
2047 2048 Uses the internal non-interactive simple merge algorithm for merging
2048 2049 files. It will use both left and right sides for conflict regions. No
2049 2050 markers are inserted.
2050 2051
2051 2052 Internal tools are always available and do not require a GUI but will by
2052 2053 default not handle symlinks or binary files. See next section for detail
2053 2054 about "actual capabilities" described above.
2054 2055
2055 2056 Choosing a merge tool
2056 2057 =====================
2057 2058
2058 2059 Mercurial uses these rules when deciding which merge tool to use:
2059 2060
2060 2061 1. If a tool has been specified with the --tool option to merge or
2061 2062 resolve, it is used. If it is the name of a tool in the merge-tools
2062 2063 configuration, its configuration is used. Otherwise the specified tool
2063 2064 must be executable by the shell.
2064 2065 2. If the "HGMERGE" environment variable is present, its value is used and
2065 2066 must be executable by the shell.
2066 2067 3. If the filename of the file to be merged matches any of the patterns in
2067 2068 the merge-patterns configuration section, the first usable merge tool
2068 2069 corresponding to a matching pattern is used.
2069 2070 4. If ui.merge is set it will be considered next. If the value is not the
2070 2071 name of a configured tool, the specified value is used and must be
2071 2072 executable by the shell. Otherwise the named tool is used if it is
2072 2073 usable.
2073 2074 5. If any usable merge tools are present in the merge-tools configuration
2074 2075 section, the one with the highest priority is used.
2075 2076 6. If a program named "hgmerge" can be found on the system, it is used -
2076 2077 but it will by default not be used for symlinks and binary files.
2077 2078 7. If the file to be merged is not binary and is not a symlink, then
2078 2079 internal ":merge" is used.
2079 2080 8. Otherwise, ":prompt" is used.
2080 2081
2081 2082 For historical reason, Mercurial treats merge tools as below while
2082 2083 examining rules above.
2083 2084
2084 2085 step specified via binary symlink
2085 2086 ----------------------------------
2086 2087 1. --tool o/o o/o
2087 2088 2. HGMERGE o/o o/o
2088 2089 3. merge-patterns o/o(*) x/?(*)
2089 2090 4. ui.merge x/?(*) x/?(*)
2090 2091
2091 2092 Each capability column indicates Mercurial behavior for internal/external
2092 2093 merge tools at examining each rule.
2093 2094
2094 2095 - "o": "assume that a tool has capability"
2095 2096 - "x": "assume that a tool does not have capability"
2096 2097 - "?": "check actual capability of a tool"
2097 2098
2098 2099 If "merge.strict-capability-check" configuration is true, Mercurial checks
2099 2100 capabilities of merge tools strictly in (*) cases above (= each capability
2100 2101 column becomes "?/?"). It is false by default for backward compatibility.
2101 2102
2102 2103 Note:
2103 2104 After selecting a merge program, Mercurial will by default attempt to
2104 2105 merge the files using a simple merge algorithm first. Only if it
2105 2106 doesn't succeed because of conflicting changes will Mercurial actually
2106 2107 execute the merge program. Whether to use the simple merge algorithm
2107 2108 first can be controlled by the premerge setting of the merge tool.
2108 2109 Premerge is enabled by default unless the file is binary or a symlink.
2109 2110
2110 2111 See the merge-tools and ui sections of hgrc(5) for details on the
2111 2112 configuration of merge tools.
2112 2113
2113 2114 Compression engines listed in `hg help bundlespec`
2114 2115
2115 2116 $ hg help bundlespec | grep gzip
2116 2117 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2117 2118 An algorithm that produces smaller bundles than "gzip".
2118 2119 This engine will likely produce smaller bundles than "gzip" but will be
2119 2120 "gzip"
2120 2121 better compression than "gzip". It also frequently yields better (?)
2121 2122
2122 2123 Test usage of section marks in help documents
2123 2124
2124 2125 $ cd "$TESTDIR"/../doc
2125 2126 $ "$PYTHON" check-seclevel.py
2126 2127 $ cd $TESTTMP
2127 2128
2128 2129 #if serve
2129 2130
2130 2131 Test the help pages in hgweb.
2131 2132
2132 2133 Dish up an empty repo; serve it cold.
2133 2134
2134 2135 $ hg init "$TESTTMP/test"
2135 2136 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2136 2137 $ cat hg.pid >> $DAEMON_PIDS
2137 2138
2138 2139 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2139 2140 200 Script output follows
2140 2141
2141 2142 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2142 2143 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2143 2144 <head>
2144 2145 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2145 2146 <meta name="robots" content="index, nofollow" />
2146 2147 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2147 2148 <script type="text/javascript" src="/static/mercurial.js"></script>
2148 2149
2149 2150 <title>Help: Index</title>
2150 2151 </head>
2151 2152 <body>
2152 2153
2153 2154 <div class="container">
2154 2155 <div class="menu">
2155 2156 <div class="logo">
2156 2157 <a href="https://mercurial-scm.org/">
2157 2158 <img src="/static/hglogo.png" alt="mercurial" /></a>
2158 2159 </div>
2159 2160 <ul>
2160 2161 <li><a href="/shortlog">log</a></li>
2161 2162 <li><a href="/graph">graph</a></li>
2162 2163 <li><a href="/tags">tags</a></li>
2163 2164 <li><a href="/bookmarks">bookmarks</a></li>
2164 2165 <li><a href="/branches">branches</a></li>
2165 2166 </ul>
2166 2167 <ul>
2167 2168 <li class="active">help</li>
2168 2169 </ul>
2169 2170 </div>
2170 2171
2171 2172 <div class="main">
2172 2173 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2173 2174
2174 2175 <form class="search" action="/log">
2175 2176
2176 2177 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2177 2178 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2178 2179 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2179 2180 </form>
2180 2181 <table class="bigtable">
2181 2182 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2182 2183
2183 2184 <tr><td>
2184 2185 <a href="/help/bundlespec">
2185 2186 bundlespec
2186 2187 </a>
2187 2188 </td><td>
2188 2189 Bundle File Formats
2189 2190 </td></tr>
2190 2191 <tr><td>
2191 2192 <a href="/help/color">
2192 2193 color
2193 2194 </a>
2194 2195 </td><td>
2195 2196 Colorizing Outputs
2196 2197 </td></tr>
2197 2198 <tr><td>
2198 2199 <a href="/help/config">
2199 2200 config
2200 2201 </a>
2201 2202 </td><td>
2202 2203 Configuration Files
2203 2204 </td></tr>
2204 2205 <tr><td>
2205 2206 <a href="/help/dates">
2206 2207 dates
2207 2208 </a>
2208 2209 </td><td>
2209 2210 Date Formats
2210 2211 </td></tr>
2211 2212 <tr><td>
2212 2213 <a href="/help/deprecated">
2213 2214 deprecated
2214 2215 </a>
2215 2216 </td><td>
2216 2217 Deprecated Features
2217 2218 </td></tr>
2218 2219 <tr><td>
2219 2220 <a href="/help/diffs">
2220 2221 diffs
2221 2222 </a>
2222 2223 </td><td>
2223 2224 Diff Formats
2224 2225 </td></tr>
2225 2226 <tr><td>
2226 2227 <a href="/help/environment">
2227 2228 environment
2228 2229 </a>
2229 2230 </td><td>
2230 2231 Environment Variables
2231 2232 </td></tr>
2232 2233 <tr><td>
2233 2234 <a href="/help/extensions">
2234 2235 extensions
2235 2236 </a>
2236 2237 </td><td>
2237 2238 Using Additional Features
2238 2239 </td></tr>
2239 2240 <tr><td>
2240 2241 <a href="/help/filesets">
2241 2242 filesets
2242 2243 </a>
2243 2244 </td><td>
2244 2245 Specifying File Sets
2245 2246 </td></tr>
2246 2247 <tr><td>
2247 2248 <a href="/help/flags">
2248 2249 flags
2249 2250 </a>
2250 2251 </td><td>
2251 2252 Command-line flags
2252 2253 </td></tr>
2253 2254 <tr><td>
2254 2255 <a href="/help/glossary">
2255 2256 glossary
2256 2257 </a>
2257 2258 </td><td>
2258 2259 Glossary
2259 2260 </td></tr>
2260 2261 <tr><td>
2261 2262 <a href="/help/hgignore">
2262 2263 hgignore
2263 2264 </a>
2264 2265 </td><td>
2265 2266 Syntax for Mercurial Ignore Files
2266 2267 </td></tr>
2267 2268 <tr><td>
2268 2269 <a href="/help/hgweb">
2269 2270 hgweb
2270 2271 </a>
2271 2272 </td><td>
2272 2273 Configuring hgweb
2273 2274 </td></tr>
2274 2275 <tr><td>
2275 2276 <a href="/help/internals">
2276 2277 internals
2277 2278 </a>
2278 2279 </td><td>
2279 2280 Technical implementation topics
2280 2281 </td></tr>
2281 2282 <tr><td>
2282 2283 <a href="/help/merge-tools">
2283 2284 merge-tools
2284 2285 </a>
2285 2286 </td><td>
2286 2287 Merge Tools
2287 2288 </td></tr>
2288 2289 <tr><td>
2289 2290 <a href="/help/pager">
2290 2291 pager
2291 2292 </a>
2292 2293 </td><td>
2293 2294 Pager Support
2294 2295 </td></tr>
2295 2296 <tr><td>
2296 2297 <a href="/help/patterns">
2297 2298 patterns
2298 2299 </a>
2299 2300 </td><td>
2300 2301 File Name Patterns
2301 2302 </td></tr>
2302 2303 <tr><td>
2303 2304 <a href="/help/phases">
2304 2305 phases
2305 2306 </a>
2306 2307 </td><td>
2307 2308 Working with Phases
2308 2309 </td></tr>
2309 2310 <tr><td>
2310 2311 <a href="/help/revisions">
2311 2312 revisions
2312 2313 </a>
2313 2314 </td><td>
2314 2315 Specifying Revisions
2315 2316 </td></tr>
2316 2317 <tr><td>
2317 2318 <a href="/help/scripting">
2318 2319 scripting
2319 2320 </a>
2320 2321 </td><td>
2321 2322 Using Mercurial from scripts and automation
2322 2323 </td></tr>
2323 2324 <tr><td>
2324 2325 <a href="/help/subrepos">
2325 2326 subrepos
2326 2327 </a>
2327 2328 </td><td>
2328 2329 Subrepositories
2329 2330 </td></tr>
2330 2331 <tr><td>
2331 2332 <a href="/help/templating">
2332 2333 templating
2333 2334 </a>
2334 2335 </td><td>
2335 2336 Template Usage
2336 2337 </td></tr>
2337 2338 <tr><td>
2338 2339 <a href="/help/urls">
2339 2340 urls
2340 2341 </a>
2341 2342 </td><td>
2342 2343 URL Paths
2343 2344 </td></tr>
2344 2345 <tr><td>
2345 2346 <a href="/help/topic-containing-verbose">
2346 2347 topic-containing-verbose
2347 2348 </a>
2348 2349 </td><td>
2349 2350 This is the topic to test omit indicating.
2350 2351 </td></tr>
2351 2352
2352 2353
2353 2354 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2354 2355
2355 2356 <tr><td>
2357 <a href="/help/abort">
2358 abort
2359 </a>
2360 </td><td>
2361 abort an unfinished operation (EXPERIMENTAL)
2362 </td></tr>
2363 <tr><td>
2356 2364 <a href="/help/add">
2357 2365 add
2358 2366 </a>
2359 2367 </td><td>
2360 2368 add the specified files on the next commit
2361 2369 </td></tr>
2362 2370 <tr><td>
2363 2371 <a href="/help/annotate">
2364 2372 annotate
2365 2373 </a>
2366 2374 </td><td>
2367 2375 show changeset information by line for each file
2368 2376 </td></tr>
2369 2377 <tr><td>
2370 2378 <a href="/help/clone">
2371 2379 clone
2372 2380 </a>
2373 2381 </td><td>
2374 2382 make a copy of an existing repository
2375 2383 </td></tr>
2376 2384 <tr><td>
2377 2385 <a href="/help/commit">
2378 2386 commit
2379 2387 </a>
2380 2388 </td><td>
2381 2389 commit the specified files or all outstanding changes
2382 2390 </td></tr>
2383 2391 <tr><td>
2384 2392 <a href="/help/diff">
2385 2393 diff
2386 2394 </a>
2387 2395 </td><td>
2388 2396 diff repository (or selected files)
2389 2397 </td></tr>
2390 2398 <tr><td>
2391 2399 <a href="/help/export">
2392 2400 export
2393 2401 </a>
2394 2402 </td><td>
2395 2403 dump the header and diffs for one or more changesets
2396 2404 </td></tr>
2397 2405 <tr><td>
2398 2406 <a href="/help/forget">
2399 2407 forget
2400 2408 </a>
2401 2409 </td><td>
2402 2410 forget the specified files on the next commit
2403 2411 </td></tr>
2404 2412 <tr><td>
2405 2413 <a href="/help/init">
2406 2414 init
2407 2415 </a>
2408 2416 </td><td>
2409 2417 create a new repository in the given directory
2410 2418 </td></tr>
2411 2419 <tr><td>
2412 2420 <a href="/help/log">
2413 2421 log
2414 2422 </a>
2415 2423 </td><td>
2416 2424 show revision history of entire repository or files
2417 2425 </td></tr>
2418 2426 <tr><td>
2419 2427 <a href="/help/merge">
2420 2428 merge
2421 2429 </a>
2422 2430 </td><td>
2423 2431 merge another revision into working directory
2424 2432 </td></tr>
2425 2433 <tr><td>
2426 2434 <a href="/help/pull">
2427 2435 pull
2428 2436 </a>
2429 2437 </td><td>
2430 2438 pull changes from the specified source
2431 2439 </td></tr>
2432 2440 <tr><td>
2433 2441 <a href="/help/push">
2434 2442 push
2435 2443 </a>
2436 2444 </td><td>
2437 2445 push changes to the specified destination
2438 2446 </td></tr>
2439 2447 <tr><td>
2440 2448 <a href="/help/remove">
2441 2449 remove
2442 2450 </a>
2443 2451 </td><td>
2444 2452 remove the specified files on the next commit
2445 2453 </td></tr>
2446 2454 <tr><td>
2447 2455 <a href="/help/serve">
2448 2456 serve
2449 2457 </a>
2450 2458 </td><td>
2451 2459 start stand-alone webserver
2452 2460 </td></tr>
2453 2461 <tr><td>
2454 2462 <a href="/help/status">
2455 2463 status
2456 2464 </a>
2457 2465 </td><td>
2458 2466 show changed files in the working directory
2459 2467 </td></tr>
2460 2468 <tr><td>
2461 2469 <a href="/help/summary">
2462 2470 summary
2463 2471 </a>
2464 2472 </td><td>
2465 2473 summarize working directory state
2466 2474 </td></tr>
2467 2475 <tr><td>
2468 2476 <a href="/help/update">
2469 2477 update
2470 2478 </a>
2471 2479 </td><td>
2472 2480 update working directory (or switch revisions)
2473 2481 </td></tr>
2474 2482
2475 2483
2476 2484
2477 2485 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2478 2486
2479 2487 <tr><td>
2480 2488 <a href="/help/addremove">
2481 2489 addremove
2482 2490 </a>
2483 2491 </td><td>
2484 2492 add all new files, delete all missing files
2485 2493 </td></tr>
2486 2494 <tr><td>
2487 2495 <a href="/help/archive">
2488 2496 archive
2489 2497 </a>
2490 2498 </td><td>
2491 2499 create an unversioned archive of a repository revision
2492 2500 </td></tr>
2493 2501 <tr><td>
2494 2502 <a href="/help/backout">
2495 2503 backout
2496 2504 </a>
2497 2505 </td><td>
2498 2506 reverse effect of earlier changeset
2499 2507 </td></tr>
2500 2508 <tr><td>
2501 2509 <a href="/help/bisect">
2502 2510 bisect
2503 2511 </a>
2504 2512 </td><td>
2505 2513 subdivision search of changesets
2506 2514 </td></tr>
2507 2515 <tr><td>
2508 2516 <a href="/help/bookmarks">
2509 2517 bookmarks
2510 2518 </a>
2511 2519 </td><td>
2512 2520 create a new bookmark or list existing bookmarks
2513 2521 </td></tr>
2514 2522 <tr><td>
2515 2523 <a href="/help/branch">
2516 2524 branch
2517 2525 </a>
2518 2526 </td><td>
2519 2527 set or show the current branch name
2520 2528 </td></tr>
2521 2529 <tr><td>
2522 2530 <a href="/help/branches">
2523 2531 branches
2524 2532 </a>
2525 2533 </td><td>
2526 2534 list repository named branches
2527 2535 </td></tr>
2528 2536 <tr><td>
2529 2537 <a href="/help/bundle">
2530 2538 bundle
2531 2539 </a>
2532 2540 </td><td>
2533 2541 create a bundle file
2534 2542 </td></tr>
2535 2543 <tr><td>
2536 2544 <a href="/help/cat">
2537 2545 cat
2538 2546 </a>
2539 2547 </td><td>
2540 2548 output the current or given revision of files
2541 2549 </td></tr>
2542 2550 <tr><td>
2543 2551 <a href="/help/config">
2544 2552 config
2545 2553 </a>
2546 2554 </td><td>
2547 2555 show combined config settings from all hgrc files
2548 2556 </td></tr>
2549 2557 <tr><td>
2550 2558 <a href="/help/copy">
2551 2559 copy
2552 2560 </a>
2553 2561 </td><td>
2554 2562 mark files as copied for the next commit
2555 2563 </td></tr>
2556 2564 <tr><td>
2557 2565 <a href="/help/files">
2558 2566 files
2559 2567 </a>
2560 2568 </td><td>
2561 2569 list tracked files
2562 2570 </td></tr>
2563 2571 <tr><td>
2564 2572 <a href="/help/graft">
2565 2573 graft
2566 2574 </a>
2567 2575 </td><td>
2568 2576 copy changes from other branches onto the current branch
2569 2577 </td></tr>
2570 2578 <tr><td>
2571 2579 <a href="/help/grep">
2572 2580 grep
2573 2581 </a>
2574 2582 </td><td>
2575 2583 search revision history for a pattern in specified files
2576 2584 </td></tr>
2577 2585 <tr><td>
2578 2586 <a href="/help/hashelp">
2579 2587 hashelp
2580 2588 </a>
2581 2589 </td><td>
2582 2590 Extension command's help
2583 2591 </td></tr>
2584 2592 <tr><td>
2585 2593 <a href="/help/heads">
2586 2594 heads
2587 2595 </a>
2588 2596 </td><td>
2589 2597 show branch heads
2590 2598 </td></tr>
2591 2599 <tr><td>
2592 2600 <a href="/help/help">
2593 2601 help
2594 2602 </a>
2595 2603 </td><td>
2596 2604 show help for a given topic or a help overview
2597 2605 </td></tr>
2598 2606 <tr><td>
2599 2607 <a href="/help/hgalias">
2600 2608 hgalias
2601 2609 </a>
2602 2610 </td><td>
2603 2611 My doc
2604 2612 </td></tr>
2605 2613 <tr><td>
2606 2614 <a href="/help/hgaliasnodoc">
2607 2615 hgaliasnodoc
2608 2616 </a>
2609 2617 </td><td>
2610 2618 summarize working directory state
2611 2619 </td></tr>
2612 2620 <tr><td>
2613 2621 <a href="/help/identify">
2614 2622 identify
2615 2623 </a>
2616 2624 </td><td>
2617 2625 identify the working directory or specified revision
2618 2626 </td></tr>
2619 2627 <tr><td>
2620 2628 <a href="/help/import">
2621 2629 import
2622 2630 </a>
2623 2631 </td><td>
2624 2632 import an ordered set of patches
2625 2633 </td></tr>
2626 2634 <tr><td>
2627 2635 <a href="/help/incoming">
2628 2636 incoming
2629 2637 </a>
2630 2638 </td><td>
2631 2639 show new changesets found in source
2632 2640 </td></tr>
2633 2641 <tr><td>
2634 2642 <a href="/help/manifest">
2635 2643 manifest
2636 2644 </a>
2637 2645 </td><td>
2638 2646 output the current or given revision of the project manifest
2639 2647 </td></tr>
2640 2648 <tr><td>
2641 2649 <a href="/help/nohelp">
2642 2650 nohelp
2643 2651 </a>
2644 2652 </td><td>
2645 2653 (no help text available)
2646 2654 </td></tr>
2647 2655 <tr><td>
2648 2656 <a href="/help/outgoing">
2649 2657 outgoing
2650 2658 </a>
2651 2659 </td><td>
2652 2660 show changesets not found in the destination
2653 2661 </td></tr>
2654 2662 <tr><td>
2655 2663 <a href="/help/paths">
2656 2664 paths
2657 2665 </a>
2658 2666 </td><td>
2659 2667 show aliases for remote repositories
2660 2668 </td></tr>
2661 2669 <tr><td>
2662 2670 <a href="/help/phase">
2663 2671 phase
2664 2672 </a>
2665 2673 </td><td>
2666 2674 set or show the current phase name
2667 2675 </td></tr>
2668 2676 <tr><td>
2669 2677 <a href="/help/recover">
2670 2678 recover
2671 2679 </a>
2672 2680 </td><td>
2673 2681 roll back an interrupted transaction
2674 2682 </td></tr>
2675 2683 <tr><td>
2676 2684 <a href="/help/rename">
2677 2685 rename
2678 2686 </a>
2679 2687 </td><td>
2680 2688 rename files; equivalent of copy + remove
2681 2689 </td></tr>
2682 2690 <tr><td>
2683 2691 <a href="/help/resolve">
2684 2692 resolve
2685 2693 </a>
2686 2694 </td><td>
2687 2695 redo merges or set/view the merge status of files
2688 2696 </td></tr>
2689 2697 <tr><td>
2690 2698 <a href="/help/revert">
2691 2699 revert
2692 2700 </a>
2693 2701 </td><td>
2694 2702 restore files to their checkout state
2695 2703 </td></tr>
2696 2704 <tr><td>
2697 2705 <a href="/help/root">
2698 2706 root
2699 2707 </a>
2700 2708 </td><td>
2701 2709 print the root (top) of the current working directory
2702 2710 </td></tr>
2703 2711 <tr><td>
2704 2712 <a href="/help/shellalias">
2705 2713 shellalias
2706 2714 </a>
2707 2715 </td><td>
2708 2716 (no help text available)
2709 2717 </td></tr>
2710 2718 <tr><td>
2711 2719 <a href="/help/shelve">
2712 2720 shelve
2713 2721 </a>
2714 2722 </td><td>
2715 2723 save and set aside changes from the working directory
2716 2724 </td></tr>
2717 2725 <tr><td>
2718 2726 <a href="/help/tag">
2719 2727 tag
2720 2728 </a>
2721 2729 </td><td>
2722 2730 add one or more tags for the current or given revision
2723 2731 </td></tr>
2724 2732 <tr><td>
2725 2733 <a href="/help/tags">
2726 2734 tags
2727 2735 </a>
2728 2736 </td><td>
2729 2737 list repository tags
2730 2738 </td></tr>
2731 2739 <tr><td>
2732 2740 <a href="/help/unbundle">
2733 2741 unbundle
2734 2742 </a>
2735 2743 </td><td>
2736 2744 apply one or more bundle files
2737 2745 </td></tr>
2738 2746 <tr><td>
2739 2747 <a href="/help/unshelve">
2740 2748 unshelve
2741 2749 </a>
2742 2750 </td><td>
2743 2751 restore a shelved change to the working directory
2744 2752 </td></tr>
2745 2753 <tr><td>
2746 2754 <a href="/help/verify">
2747 2755 verify
2748 2756 </a>
2749 2757 </td><td>
2750 2758 verify the integrity of the repository
2751 2759 </td></tr>
2752 2760 <tr><td>
2753 2761 <a href="/help/version">
2754 2762 version
2755 2763 </a>
2756 2764 </td><td>
2757 2765 output version and copyright information
2758 2766 </td></tr>
2759 2767
2760 2768
2761 2769 </table>
2762 2770 </div>
2763 2771 </div>
2764 2772
2765 2773
2766 2774
2767 2775 </body>
2768 2776 </html>
2769 2777
2770 2778
2771 2779 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2772 2780 200 Script output follows
2773 2781
2774 2782 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2775 2783 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2776 2784 <head>
2777 2785 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2778 2786 <meta name="robots" content="index, nofollow" />
2779 2787 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2780 2788 <script type="text/javascript" src="/static/mercurial.js"></script>
2781 2789
2782 2790 <title>Help: add</title>
2783 2791 </head>
2784 2792 <body>
2785 2793
2786 2794 <div class="container">
2787 2795 <div class="menu">
2788 2796 <div class="logo">
2789 2797 <a href="https://mercurial-scm.org/">
2790 2798 <img src="/static/hglogo.png" alt="mercurial" /></a>
2791 2799 </div>
2792 2800 <ul>
2793 2801 <li><a href="/shortlog">log</a></li>
2794 2802 <li><a href="/graph">graph</a></li>
2795 2803 <li><a href="/tags">tags</a></li>
2796 2804 <li><a href="/bookmarks">bookmarks</a></li>
2797 2805 <li><a href="/branches">branches</a></li>
2798 2806 </ul>
2799 2807 <ul>
2800 2808 <li class="active"><a href="/help">help</a></li>
2801 2809 </ul>
2802 2810 </div>
2803 2811
2804 2812 <div class="main">
2805 2813 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2806 2814 <h3>Help: add</h3>
2807 2815
2808 2816 <form class="search" action="/log">
2809 2817
2810 2818 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2811 2819 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2812 2820 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2813 2821 </form>
2814 2822 <div id="doc">
2815 2823 <p>
2816 2824 hg add [OPTION]... [FILE]...
2817 2825 </p>
2818 2826 <p>
2819 2827 add the specified files on the next commit
2820 2828 </p>
2821 2829 <p>
2822 2830 Schedule files to be version controlled and added to the
2823 2831 repository.
2824 2832 </p>
2825 2833 <p>
2826 2834 The files will be added to the repository at the next commit. To
2827 2835 undo an add before that, see 'hg forget'.
2828 2836 </p>
2829 2837 <p>
2830 2838 If no names are given, add all files to the repository (except
2831 2839 files matching &quot;.hgignore&quot;).
2832 2840 </p>
2833 2841 <p>
2834 2842 Examples:
2835 2843 </p>
2836 2844 <ul>
2837 2845 <li> New (unknown) files are added automatically by 'hg add':
2838 2846 <pre>
2839 2847 \$ ls (re)
2840 2848 foo.c
2841 2849 \$ hg status (re)
2842 2850 ? foo.c
2843 2851 \$ hg add (re)
2844 2852 adding foo.c
2845 2853 \$ hg status (re)
2846 2854 A foo.c
2847 2855 </pre>
2848 2856 <li> Specific files to be added can be specified:
2849 2857 <pre>
2850 2858 \$ ls (re)
2851 2859 bar.c foo.c
2852 2860 \$ hg status (re)
2853 2861 ? bar.c
2854 2862 ? foo.c
2855 2863 \$ hg add bar.c (re)
2856 2864 \$ hg status (re)
2857 2865 A bar.c
2858 2866 ? foo.c
2859 2867 </pre>
2860 2868 </ul>
2861 2869 <p>
2862 2870 Returns 0 if all files are successfully added.
2863 2871 </p>
2864 2872 <p>
2865 2873 options ([+] can be repeated):
2866 2874 </p>
2867 2875 <table>
2868 2876 <tr><td>-I</td>
2869 2877 <td>--include PATTERN [+]</td>
2870 2878 <td>include names matching the given patterns</td></tr>
2871 2879 <tr><td>-X</td>
2872 2880 <td>--exclude PATTERN [+]</td>
2873 2881 <td>exclude names matching the given patterns</td></tr>
2874 2882 <tr><td>-S</td>
2875 2883 <td>--subrepos</td>
2876 2884 <td>recurse into subrepositories</td></tr>
2877 2885 <tr><td>-n</td>
2878 2886 <td>--dry-run</td>
2879 2887 <td>do not perform actions, just print output</td></tr>
2880 2888 </table>
2881 2889 <p>
2882 2890 global options ([+] can be repeated):
2883 2891 </p>
2884 2892 <table>
2885 2893 <tr><td>-R</td>
2886 2894 <td>--repository REPO</td>
2887 2895 <td>repository root directory or name of overlay bundle file</td></tr>
2888 2896 <tr><td></td>
2889 2897 <td>--cwd DIR</td>
2890 2898 <td>change working directory</td></tr>
2891 2899 <tr><td>-y</td>
2892 2900 <td>--noninteractive</td>
2893 2901 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2894 2902 <tr><td>-q</td>
2895 2903 <td>--quiet</td>
2896 2904 <td>suppress output</td></tr>
2897 2905 <tr><td>-v</td>
2898 2906 <td>--verbose</td>
2899 2907 <td>enable additional output</td></tr>
2900 2908 <tr><td></td>
2901 2909 <td>--color TYPE</td>
2902 2910 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2903 2911 <tr><td></td>
2904 2912 <td>--config CONFIG [+]</td>
2905 2913 <td>set/override config option (use 'section.name=value')</td></tr>
2906 2914 <tr><td></td>
2907 2915 <td>--debug</td>
2908 2916 <td>enable debugging output</td></tr>
2909 2917 <tr><td></td>
2910 2918 <td>--debugger</td>
2911 2919 <td>start debugger</td></tr>
2912 2920 <tr><td></td>
2913 2921 <td>--encoding ENCODE</td>
2914 2922 <td>set the charset encoding (default: ascii)</td></tr>
2915 2923 <tr><td></td>
2916 2924 <td>--encodingmode MODE</td>
2917 2925 <td>set the charset encoding mode (default: strict)</td></tr>
2918 2926 <tr><td></td>
2919 2927 <td>--traceback</td>
2920 2928 <td>always print a traceback on exception</td></tr>
2921 2929 <tr><td></td>
2922 2930 <td>--time</td>
2923 2931 <td>time how long the command takes</td></tr>
2924 2932 <tr><td></td>
2925 2933 <td>--profile</td>
2926 2934 <td>print command execution profile</td></tr>
2927 2935 <tr><td></td>
2928 2936 <td>--version</td>
2929 2937 <td>output version information and exit</td></tr>
2930 2938 <tr><td>-h</td>
2931 2939 <td>--help</td>
2932 2940 <td>display help and exit</td></tr>
2933 2941 <tr><td></td>
2934 2942 <td>--hidden</td>
2935 2943 <td>consider hidden changesets</td></tr>
2936 2944 <tr><td></td>
2937 2945 <td>--pager TYPE</td>
2938 2946 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2939 2947 </table>
2940 2948
2941 2949 </div>
2942 2950 </div>
2943 2951 </div>
2944 2952
2945 2953
2946 2954
2947 2955 </body>
2948 2956 </html>
2949 2957
2950 2958
2951 2959 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2952 2960 200 Script output follows
2953 2961
2954 2962 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2955 2963 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2956 2964 <head>
2957 2965 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2958 2966 <meta name="robots" content="index, nofollow" />
2959 2967 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2960 2968 <script type="text/javascript" src="/static/mercurial.js"></script>
2961 2969
2962 2970 <title>Help: remove</title>
2963 2971 </head>
2964 2972 <body>
2965 2973
2966 2974 <div class="container">
2967 2975 <div class="menu">
2968 2976 <div class="logo">
2969 2977 <a href="https://mercurial-scm.org/">
2970 2978 <img src="/static/hglogo.png" alt="mercurial" /></a>
2971 2979 </div>
2972 2980 <ul>
2973 2981 <li><a href="/shortlog">log</a></li>
2974 2982 <li><a href="/graph">graph</a></li>
2975 2983 <li><a href="/tags">tags</a></li>
2976 2984 <li><a href="/bookmarks">bookmarks</a></li>
2977 2985 <li><a href="/branches">branches</a></li>
2978 2986 </ul>
2979 2987 <ul>
2980 2988 <li class="active"><a href="/help">help</a></li>
2981 2989 </ul>
2982 2990 </div>
2983 2991
2984 2992 <div class="main">
2985 2993 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2986 2994 <h3>Help: remove</h3>
2987 2995
2988 2996 <form class="search" action="/log">
2989 2997
2990 2998 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2991 2999 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2992 3000 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2993 3001 </form>
2994 3002 <div id="doc">
2995 3003 <p>
2996 3004 hg remove [OPTION]... FILE...
2997 3005 </p>
2998 3006 <p>
2999 3007 aliases: rm
3000 3008 </p>
3001 3009 <p>
3002 3010 remove the specified files on the next commit
3003 3011 </p>
3004 3012 <p>
3005 3013 Schedule the indicated files for removal from the current branch.
3006 3014 </p>
3007 3015 <p>
3008 3016 This command schedules the files to be removed at the next commit.
3009 3017 To undo a remove before that, see 'hg revert'. To undo added
3010 3018 files, see 'hg forget'.
3011 3019 </p>
3012 3020 <p>
3013 3021 -A/--after can be used to remove only files that have already
3014 3022 been deleted, -f/--force can be used to force deletion, and -Af
3015 3023 can be used to remove files from the next revision without
3016 3024 deleting them from the working directory.
3017 3025 </p>
3018 3026 <p>
3019 3027 The following table details the behavior of remove for different
3020 3028 file states (columns) and option combinations (rows). The file
3021 3029 states are Added [A], Clean [C], Modified [M] and Missing [!]
3022 3030 (as reported by 'hg status'). The actions are Warn, Remove
3023 3031 (from branch) and Delete (from disk):
3024 3032 </p>
3025 3033 <table>
3026 3034 <tr><td>opt/state</td>
3027 3035 <td>A</td>
3028 3036 <td>C</td>
3029 3037 <td>M</td>
3030 3038 <td>!</td></tr>
3031 3039 <tr><td>none</td>
3032 3040 <td>W</td>
3033 3041 <td>RD</td>
3034 3042 <td>W</td>
3035 3043 <td>R</td></tr>
3036 3044 <tr><td>-f</td>
3037 3045 <td>R</td>
3038 3046 <td>RD</td>
3039 3047 <td>RD</td>
3040 3048 <td>R</td></tr>
3041 3049 <tr><td>-A</td>
3042 3050 <td>W</td>
3043 3051 <td>W</td>
3044 3052 <td>W</td>
3045 3053 <td>R</td></tr>
3046 3054 <tr><td>-Af</td>
3047 3055 <td>R</td>
3048 3056 <td>R</td>
3049 3057 <td>R</td>
3050 3058 <td>R</td></tr>
3051 3059 </table>
3052 3060 <p>
3053 3061 <b>Note:</b>
3054 3062 </p>
3055 3063 <p>
3056 3064 'hg remove' never deletes files in Added [A] state from the
3057 3065 working directory, not even if &quot;--force&quot; is specified.
3058 3066 </p>
3059 3067 <p>
3060 3068 Returns 0 on success, 1 if any warnings encountered.
3061 3069 </p>
3062 3070 <p>
3063 3071 options ([+] can be repeated):
3064 3072 </p>
3065 3073 <table>
3066 3074 <tr><td>-A</td>
3067 3075 <td>--after</td>
3068 3076 <td>record delete for missing files</td></tr>
3069 3077 <tr><td>-f</td>
3070 3078 <td>--force</td>
3071 3079 <td>forget added files, delete modified files</td></tr>
3072 3080 <tr><td>-S</td>
3073 3081 <td>--subrepos</td>
3074 3082 <td>recurse into subrepositories</td></tr>
3075 3083 <tr><td>-I</td>
3076 3084 <td>--include PATTERN [+]</td>
3077 3085 <td>include names matching the given patterns</td></tr>
3078 3086 <tr><td>-X</td>
3079 3087 <td>--exclude PATTERN [+]</td>
3080 3088 <td>exclude names matching the given patterns</td></tr>
3081 3089 <tr><td>-n</td>
3082 3090 <td>--dry-run</td>
3083 3091 <td>do not perform actions, just print output</td></tr>
3084 3092 </table>
3085 3093 <p>
3086 3094 global options ([+] can be repeated):
3087 3095 </p>
3088 3096 <table>
3089 3097 <tr><td>-R</td>
3090 3098 <td>--repository REPO</td>
3091 3099 <td>repository root directory or name of overlay bundle file</td></tr>
3092 3100 <tr><td></td>
3093 3101 <td>--cwd DIR</td>
3094 3102 <td>change working directory</td></tr>
3095 3103 <tr><td>-y</td>
3096 3104 <td>--noninteractive</td>
3097 3105 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3098 3106 <tr><td>-q</td>
3099 3107 <td>--quiet</td>
3100 3108 <td>suppress output</td></tr>
3101 3109 <tr><td>-v</td>
3102 3110 <td>--verbose</td>
3103 3111 <td>enable additional output</td></tr>
3104 3112 <tr><td></td>
3105 3113 <td>--color TYPE</td>
3106 3114 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3107 3115 <tr><td></td>
3108 3116 <td>--config CONFIG [+]</td>
3109 3117 <td>set/override config option (use 'section.name=value')</td></tr>
3110 3118 <tr><td></td>
3111 3119 <td>--debug</td>
3112 3120 <td>enable debugging output</td></tr>
3113 3121 <tr><td></td>
3114 3122 <td>--debugger</td>
3115 3123 <td>start debugger</td></tr>
3116 3124 <tr><td></td>
3117 3125 <td>--encoding ENCODE</td>
3118 3126 <td>set the charset encoding (default: ascii)</td></tr>
3119 3127 <tr><td></td>
3120 3128 <td>--encodingmode MODE</td>
3121 3129 <td>set the charset encoding mode (default: strict)</td></tr>
3122 3130 <tr><td></td>
3123 3131 <td>--traceback</td>
3124 3132 <td>always print a traceback on exception</td></tr>
3125 3133 <tr><td></td>
3126 3134 <td>--time</td>
3127 3135 <td>time how long the command takes</td></tr>
3128 3136 <tr><td></td>
3129 3137 <td>--profile</td>
3130 3138 <td>print command execution profile</td></tr>
3131 3139 <tr><td></td>
3132 3140 <td>--version</td>
3133 3141 <td>output version information and exit</td></tr>
3134 3142 <tr><td>-h</td>
3135 3143 <td>--help</td>
3136 3144 <td>display help and exit</td></tr>
3137 3145 <tr><td></td>
3138 3146 <td>--hidden</td>
3139 3147 <td>consider hidden changesets</td></tr>
3140 3148 <tr><td></td>
3141 3149 <td>--pager TYPE</td>
3142 3150 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3143 3151 </table>
3144 3152
3145 3153 </div>
3146 3154 </div>
3147 3155 </div>
3148 3156
3149 3157
3150 3158
3151 3159 </body>
3152 3160 </html>
3153 3161
3154 3162
3155 3163 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3156 3164 200 Script output follows
3157 3165
3158 3166 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3159 3167 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3160 3168 <head>
3161 3169 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3162 3170 <meta name="robots" content="index, nofollow" />
3163 3171 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3164 3172 <script type="text/javascript" src="/static/mercurial.js"></script>
3165 3173
3166 3174 <title>Help: dates</title>
3167 3175 </head>
3168 3176 <body>
3169 3177
3170 3178 <div class="container">
3171 3179 <div class="menu">
3172 3180 <div class="logo">
3173 3181 <a href="https://mercurial-scm.org/">
3174 3182 <img src="/static/hglogo.png" alt="mercurial" /></a>
3175 3183 </div>
3176 3184 <ul>
3177 3185 <li><a href="/shortlog">log</a></li>
3178 3186 <li><a href="/graph">graph</a></li>
3179 3187 <li><a href="/tags">tags</a></li>
3180 3188 <li><a href="/bookmarks">bookmarks</a></li>
3181 3189 <li><a href="/branches">branches</a></li>
3182 3190 </ul>
3183 3191 <ul>
3184 3192 <li class="active"><a href="/help">help</a></li>
3185 3193 </ul>
3186 3194 </div>
3187 3195
3188 3196 <div class="main">
3189 3197 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3190 3198 <h3>Help: dates</h3>
3191 3199
3192 3200 <form class="search" action="/log">
3193 3201
3194 3202 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3195 3203 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3196 3204 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3197 3205 </form>
3198 3206 <div id="doc">
3199 3207 <h1>Date Formats</h1>
3200 3208 <p>
3201 3209 Some commands allow the user to specify a date, e.g.:
3202 3210 </p>
3203 3211 <ul>
3204 3212 <li> backout, commit, import, tag: Specify the commit date.
3205 3213 <li> log, revert, update: Select revision(s) by date.
3206 3214 </ul>
3207 3215 <p>
3208 3216 Many date formats are valid. Here are some examples:
3209 3217 </p>
3210 3218 <ul>
3211 3219 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3212 3220 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3213 3221 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3214 3222 <li> &quot;Dec 6&quot; (midnight)
3215 3223 <li> &quot;13:18&quot; (today assumed)
3216 3224 <li> &quot;3:39&quot; (3:39AM assumed)
3217 3225 <li> &quot;3:39pm&quot; (15:39)
3218 3226 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3219 3227 <li> &quot;2006-12-6 13:18&quot;
3220 3228 <li> &quot;2006-12-6&quot;
3221 3229 <li> &quot;12-6&quot;
3222 3230 <li> &quot;12/6&quot;
3223 3231 <li> &quot;12/6/6&quot; (Dec 6 2006)
3224 3232 <li> &quot;today&quot; (midnight)
3225 3233 <li> &quot;yesterday&quot; (midnight)
3226 3234 <li> &quot;now&quot; - right now
3227 3235 </ul>
3228 3236 <p>
3229 3237 Lastly, there is Mercurial's internal format:
3230 3238 </p>
3231 3239 <ul>
3232 3240 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3233 3241 </ul>
3234 3242 <p>
3235 3243 This is the internal representation format for dates. The first number
3236 3244 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3237 3245 second is the offset of the local timezone, in seconds west of UTC
3238 3246 (negative if the timezone is east of UTC).
3239 3247 </p>
3240 3248 <p>
3241 3249 The log command also accepts date ranges:
3242 3250 </p>
3243 3251 <ul>
3244 3252 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3245 3253 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3246 3254 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3247 3255 <li> &quot;-DAYS&quot; - within a given number of days of today
3248 3256 </ul>
3249 3257
3250 3258 </div>
3251 3259 </div>
3252 3260 </div>
3253 3261
3254 3262
3255 3263
3256 3264 </body>
3257 3265 </html>
3258 3266
3259 3267
3260 3268 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3261 3269 200 Script output follows
3262 3270
3263 3271 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3264 3272 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3265 3273 <head>
3266 3274 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3267 3275 <meta name="robots" content="index, nofollow" />
3268 3276 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3269 3277 <script type="text/javascript" src="/static/mercurial.js"></script>
3270 3278
3271 3279 <title>Help: pager</title>
3272 3280 </head>
3273 3281 <body>
3274 3282
3275 3283 <div class="container">
3276 3284 <div class="menu">
3277 3285 <div class="logo">
3278 3286 <a href="https://mercurial-scm.org/">
3279 3287 <img src="/static/hglogo.png" alt="mercurial" /></a>
3280 3288 </div>
3281 3289 <ul>
3282 3290 <li><a href="/shortlog">log</a></li>
3283 3291 <li><a href="/graph">graph</a></li>
3284 3292 <li><a href="/tags">tags</a></li>
3285 3293 <li><a href="/bookmarks">bookmarks</a></li>
3286 3294 <li><a href="/branches">branches</a></li>
3287 3295 </ul>
3288 3296 <ul>
3289 3297 <li class="active"><a href="/help">help</a></li>
3290 3298 </ul>
3291 3299 </div>
3292 3300
3293 3301 <div class="main">
3294 3302 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3295 3303 <h3>Help: pager</h3>
3296 3304
3297 3305 <form class="search" action="/log">
3298 3306
3299 3307 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3300 3308 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3301 3309 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3302 3310 </form>
3303 3311 <div id="doc">
3304 3312 <h1>Pager Support</h1>
3305 3313 <p>
3306 3314 Some Mercurial commands can produce a lot of output, and Mercurial will
3307 3315 attempt to use a pager to make those commands more pleasant.
3308 3316 </p>
3309 3317 <p>
3310 3318 To set the pager that should be used, set the application variable:
3311 3319 </p>
3312 3320 <pre>
3313 3321 [pager]
3314 3322 pager = less -FRX
3315 3323 </pre>
3316 3324 <p>
3317 3325 If no pager is set in the user or repository configuration, Mercurial uses the
3318 3326 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3319 3327 or system configuration is used. If none of these are set, a default pager will
3320 3328 be used, typically 'less' on Unix and 'more' on Windows.
3321 3329 </p>
3322 3330 <p>
3323 3331 You can disable the pager for certain commands by adding them to the
3324 3332 pager.ignore list:
3325 3333 </p>
3326 3334 <pre>
3327 3335 [pager]
3328 3336 ignore = version, help, update
3329 3337 </pre>
3330 3338 <p>
3331 3339 To ignore global commands like 'hg version' or 'hg help', you have
3332 3340 to specify them in your user configuration file.
3333 3341 </p>
3334 3342 <p>
3335 3343 To control whether the pager is used at all for an individual command,
3336 3344 you can use --pager=&lt;value&gt;:
3337 3345 </p>
3338 3346 <ul>
3339 3347 <li> use as needed: 'auto'.
3340 3348 <li> require the pager: 'yes' or 'on'.
3341 3349 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3342 3350 </ul>
3343 3351 <p>
3344 3352 To globally turn off all attempts to use a pager, set:
3345 3353 </p>
3346 3354 <pre>
3347 3355 [ui]
3348 3356 paginate = never
3349 3357 </pre>
3350 3358 <p>
3351 3359 which will prevent the pager from running.
3352 3360 </p>
3353 3361
3354 3362 </div>
3355 3363 </div>
3356 3364 </div>
3357 3365
3358 3366
3359 3367
3360 3368 </body>
3361 3369 </html>
3362 3370
3363 3371
3364 3372 Sub-topic indexes rendered properly
3365 3373
3366 3374 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3367 3375 200 Script output follows
3368 3376
3369 3377 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3370 3378 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3371 3379 <head>
3372 3380 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3373 3381 <meta name="robots" content="index, nofollow" />
3374 3382 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3375 3383 <script type="text/javascript" src="/static/mercurial.js"></script>
3376 3384
3377 3385 <title>Help: internals</title>
3378 3386 </head>
3379 3387 <body>
3380 3388
3381 3389 <div class="container">
3382 3390 <div class="menu">
3383 3391 <div class="logo">
3384 3392 <a href="https://mercurial-scm.org/">
3385 3393 <img src="/static/hglogo.png" alt="mercurial" /></a>
3386 3394 </div>
3387 3395 <ul>
3388 3396 <li><a href="/shortlog">log</a></li>
3389 3397 <li><a href="/graph">graph</a></li>
3390 3398 <li><a href="/tags">tags</a></li>
3391 3399 <li><a href="/bookmarks">bookmarks</a></li>
3392 3400 <li><a href="/branches">branches</a></li>
3393 3401 </ul>
3394 3402 <ul>
3395 3403 <li><a href="/help">help</a></li>
3396 3404 </ul>
3397 3405 </div>
3398 3406
3399 3407 <div class="main">
3400 3408 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3401 3409
3402 3410 <form class="search" action="/log">
3403 3411
3404 3412 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3405 3413 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3406 3414 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3407 3415 </form>
3408 3416 <table class="bigtable">
3409 3417 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3410 3418
3411 3419 <tr><td>
3412 3420 <a href="/help/internals.bundle2">
3413 3421 bundle2
3414 3422 </a>
3415 3423 </td><td>
3416 3424 Bundle2
3417 3425 </td></tr>
3418 3426 <tr><td>
3419 3427 <a href="/help/internals.bundles">
3420 3428 bundles
3421 3429 </a>
3422 3430 </td><td>
3423 3431 Bundles
3424 3432 </td></tr>
3425 3433 <tr><td>
3426 3434 <a href="/help/internals.cbor">
3427 3435 cbor
3428 3436 </a>
3429 3437 </td><td>
3430 3438 CBOR
3431 3439 </td></tr>
3432 3440 <tr><td>
3433 3441 <a href="/help/internals.censor">
3434 3442 censor
3435 3443 </a>
3436 3444 </td><td>
3437 3445 Censor
3438 3446 </td></tr>
3439 3447 <tr><td>
3440 3448 <a href="/help/internals.changegroups">
3441 3449 changegroups
3442 3450 </a>
3443 3451 </td><td>
3444 3452 Changegroups
3445 3453 </td></tr>
3446 3454 <tr><td>
3447 3455 <a href="/help/internals.config">
3448 3456 config
3449 3457 </a>
3450 3458 </td><td>
3451 3459 Config Registrar
3452 3460 </td></tr>
3453 3461 <tr><td>
3454 3462 <a href="/help/internals.extensions">
3455 3463 extensions
3456 3464 </a>
3457 3465 </td><td>
3458 3466 Extension API
3459 3467 </td></tr>
3460 3468 <tr><td>
3461 3469 <a href="/help/internals.mergestate">
3462 3470 mergestate
3463 3471 </a>
3464 3472 </td><td>
3465 3473 Mergestate
3466 3474 </td></tr>
3467 3475 <tr><td>
3468 3476 <a href="/help/internals.requirements">
3469 3477 requirements
3470 3478 </a>
3471 3479 </td><td>
3472 3480 Repository Requirements
3473 3481 </td></tr>
3474 3482 <tr><td>
3475 3483 <a href="/help/internals.revlogs">
3476 3484 revlogs
3477 3485 </a>
3478 3486 </td><td>
3479 3487 Revision Logs
3480 3488 </td></tr>
3481 3489 <tr><td>
3482 3490 <a href="/help/internals.wireprotocol">
3483 3491 wireprotocol
3484 3492 </a>
3485 3493 </td><td>
3486 3494 Wire Protocol
3487 3495 </td></tr>
3488 3496 <tr><td>
3489 3497 <a href="/help/internals.wireprotocolrpc">
3490 3498 wireprotocolrpc
3491 3499 </a>
3492 3500 </td><td>
3493 3501 Wire Protocol RPC
3494 3502 </td></tr>
3495 3503 <tr><td>
3496 3504 <a href="/help/internals.wireprotocolv2">
3497 3505 wireprotocolv2
3498 3506 </a>
3499 3507 </td><td>
3500 3508 Wire Protocol Version 2
3501 3509 </td></tr>
3502 3510
3503 3511
3504 3512
3505 3513
3506 3514
3507 3515 </table>
3508 3516 </div>
3509 3517 </div>
3510 3518
3511 3519
3512 3520
3513 3521 </body>
3514 3522 </html>
3515 3523
3516 3524
3517 3525 Sub-topic topics rendered properly
3518 3526
3519 3527 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3520 3528 200 Script output follows
3521 3529
3522 3530 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3523 3531 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3524 3532 <head>
3525 3533 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3526 3534 <meta name="robots" content="index, nofollow" />
3527 3535 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3528 3536 <script type="text/javascript" src="/static/mercurial.js"></script>
3529 3537
3530 3538 <title>Help: internals.changegroups</title>
3531 3539 </head>
3532 3540 <body>
3533 3541
3534 3542 <div class="container">
3535 3543 <div class="menu">
3536 3544 <div class="logo">
3537 3545 <a href="https://mercurial-scm.org/">
3538 3546 <img src="/static/hglogo.png" alt="mercurial" /></a>
3539 3547 </div>
3540 3548 <ul>
3541 3549 <li><a href="/shortlog">log</a></li>
3542 3550 <li><a href="/graph">graph</a></li>
3543 3551 <li><a href="/tags">tags</a></li>
3544 3552 <li><a href="/bookmarks">bookmarks</a></li>
3545 3553 <li><a href="/branches">branches</a></li>
3546 3554 </ul>
3547 3555 <ul>
3548 3556 <li class="active"><a href="/help">help</a></li>
3549 3557 </ul>
3550 3558 </div>
3551 3559
3552 3560 <div class="main">
3553 3561 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3554 3562 <h3>Help: internals.changegroups</h3>
3555 3563
3556 3564 <form class="search" action="/log">
3557 3565
3558 3566 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3559 3567 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3560 3568 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3561 3569 </form>
3562 3570 <div id="doc">
3563 3571 <h1>Changegroups</h1>
3564 3572 <p>
3565 3573 Changegroups are representations of repository revlog data, specifically
3566 3574 the changelog data, root/flat manifest data, treemanifest data, and
3567 3575 filelogs.
3568 3576 </p>
3569 3577 <p>
3570 3578 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3571 3579 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3572 3580 only difference being an additional item in the *delta header*. Version
3573 3581 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3574 3582 exchanging treemanifests (enabled by setting an option on the
3575 3583 &quot;changegroup&quot; part in the bundle2).
3576 3584 </p>
3577 3585 <p>
3578 3586 Changegroups when not exchanging treemanifests consist of 3 logical
3579 3587 segments:
3580 3588 </p>
3581 3589 <pre>
3582 3590 +---------------------------------+
3583 3591 | | | |
3584 3592 | changeset | manifest | filelogs |
3585 3593 | | | |
3586 3594 | | | |
3587 3595 +---------------------------------+
3588 3596 </pre>
3589 3597 <p>
3590 3598 When exchanging treemanifests, there are 4 logical segments:
3591 3599 </p>
3592 3600 <pre>
3593 3601 +-------------------------------------------------+
3594 3602 | | | | |
3595 3603 | changeset | root | treemanifests | filelogs |
3596 3604 | | manifest | | |
3597 3605 | | | | |
3598 3606 +-------------------------------------------------+
3599 3607 </pre>
3600 3608 <p>
3601 3609 The principle building block of each segment is a *chunk*. A *chunk*
3602 3610 is a framed piece of data:
3603 3611 </p>
3604 3612 <pre>
3605 3613 +---------------------------------------+
3606 3614 | | |
3607 3615 | length | data |
3608 3616 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3609 3617 | | |
3610 3618 +---------------------------------------+
3611 3619 </pre>
3612 3620 <p>
3613 3621 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3614 3622 integer indicating the length of the entire chunk (including the length field
3615 3623 itself).
3616 3624 </p>
3617 3625 <p>
3618 3626 There is a special case chunk that has a value of 0 for the length
3619 3627 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3620 3628 </p>
3621 3629 <h2>Delta Groups</h2>
3622 3630 <p>
3623 3631 A *delta group* expresses the content of a revlog as a series of deltas,
3624 3632 or patches against previous revisions.
3625 3633 </p>
3626 3634 <p>
3627 3635 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3628 3636 to signal the end of the delta group:
3629 3637 </p>
3630 3638 <pre>
3631 3639 +------------------------------------------------------------------------+
3632 3640 | | | | | |
3633 3641 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3634 3642 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3635 3643 | | | | | |
3636 3644 +------------------------------------------------------------------------+
3637 3645 </pre>
3638 3646 <p>
3639 3647 Each *chunk*'s data consists of the following:
3640 3648 </p>
3641 3649 <pre>
3642 3650 +---------------------------------------+
3643 3651 | | |
3644 3652 | delta header | delta data |
3645 3653 | (various by version) | (various) |
3646 3654 | | |
3647 3655 +---------------------------------------+
3648 3656 </pre>
3649 3657 <p>
3650 3658 The *delta data* is a series of *delta*s that describe a diff from an existing
3651 3659 entry (either that the recipient already has, or previously specified in the
3652 3660 bundle/changegroup).
3653 3661 </p>
3654 3662 <p>
3655 3663 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3656 3664 &quot;3&quot; of the changegroup format.
3657 3665 </p>
3658 3666 <p>
3659 3667 Version 1 (headerlen=80):
3660 3668 </p>
3661 3669 <pre>
3662 3670 +------------------------------------------------------+
3663 3671 | | | | |
3664 3672 | node | p1 node | p2 node | link node |
3665 3673 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3666 3674 | | | | |
3667 3675 +------------------------------------------------------+
3668 3676 </pre>
3669 3677 <p>
3670 3678 Version 2 (headerlen=100):
3671 3679 </p>
3672 3680 <pre>
3673 3681 +------------------------------------------------------------------+
3674 3682 | | | | | |
3675 3683 | node | p1 node | p2 node | base node | link node |
3676 3684 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3677 3685 | | | | | |
3678 3686 +------------------------------------------------------------------+
3679 3687 </pre>
3680 3688 <p>
3681 3689 Version 3 (headerlen=102):
3682 3690 </p>
3683 3691 <pre>
3684 3692 +------------------------------------------------------------------------------+
3685 3693 | | | | | | |
3686 3694 | node | p1 node | p2 node | base node | link node | flags |
3687 3695 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3688 3696 | | | | | | |
3689 3697 +------------------------------------------------------------------------------+
3690 3698 </pre>
3691 3699 <p>
3692 3700 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3693 3701 series of *delta*s, densely packed (no separators). These deltas describe a diff
3694 3702 from an existing entry (either that the recipient already has, or previously
3695 3703 specified in the bundle/changegroup). The format is described more fully in
3696 3704 &quot;hg help internals.bdiff&quot;, but briefly:
3697 3705 </p>
3698 3706 <pre>
3699 3707 +---------------------------------------------------------------+
3700 3708 | | | | |
3701 3709 | start offset | end offset | new length | content |
3702 3710 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3703 3711 | | | | |
3704 3712 +---------------------------------------------------------------+
3705 3713 </pre>
3706 3714 <p>
3707 3715 Please note that the length field in the delta data does *not* include itself.
3708 3716 </p>
3709 3717 <p>
3710 3718 In version 1, the delta is always applied against the previous node from
3711 3719 the changegroup or the first parent if this is the first entry in the
3712 3720 changegroup.
3713 3721 </p>
3714 3722 <p>
3715 3723 In version 2 and up, the delta base node is encoded in the entry in the
3716 3724 changegroup. This allows the delta to be expressed against any parent,
3717 3725 which can result in smaller deltas and more efficient encoding of data.
3718 3726 </p>
3719 3727 <p>
3720 3728 The *flags* field holds bitwise flags affecting the processing of revision
3721 3729 data. The following flags are defined:
3722 3730 </p>
3723 3731 <dl>
3724 3732 <dt>32768
3725 3733 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3726 3734 <dt>16384
3727 3735 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3728 3736 <dt>8192
3729 3737 <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.
3730 3738 </dl>
3731 3739 <p>
3732 3740 For historical reasons, the integer values are identical to revlog version 1
3733 3741 per-revision storage flags and correspond to bits being set in this 2-byte
3734 3742 field. Bits were allocated starting from the most-significant bit, hence the
3735 3743 reverse ordering and allocation of these flags.
3736 3744 </p>
3737 3745 <h2>Changeset Segment</h2>
3738 3746 <p>
3739 3747 The *changeset segment* consists of a single *delta group* holding
3740 3748 changelog data. The *empty chunk* at the end of the *delta group* denotes
3741 3749 the boundary to the *manifest segment*.
3742 3750 </p>
3743 3751 <h2>Manifest Segment</h2>
3744 3752 <p>
3745 3753 The *manifest segment* consists of a single *delta group* holding manifest
3746 3754 data. If treemanifests are in use, it contains only the manifest for the
3747 3755 root directory of the repository. Otherwise, it contains the entire
3748 3756 manifest data. The *empty chunk* at the end of the *delta group* denotes
3749 3757 the boundary to the next segment (either the *treemanifests segment* or the
3750 3758 *filelogs segment*, depending on version and the request options).
3751 3759 </p>
3752 3760 <h3>Treemanifests Segment</h3>
3753 3761 <p>
3754 3762 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3755 3763 only if the 'treemanifest' param is part of the bundle2 changegroup part
3756 3764 (it is not possible to use changegroup version 3 outside of bundle2).
3757 3765 Aside from the filenames in the *treemanifests segment* containing a
3758 3766 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3759 3767 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3760 3768 a sub-segment with filename size 0). This denotes the boundary to the
3761 3769 *filelogs segment*.
3762 3770 </p>
3763 3771 <h2>Filelogs Segment</h2>
3764 3772 <p>
3765 3773 The *filelogs segment* consists of multiple sub-segments, each
3766 3774 corresponding to an individual file whose data is being described:
3767 3775 </p>
3768 3776 <pre>
3769 3777 +--------------------------------------------------+
3770 3778 | | | | | |
3771 3779 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3772 3780 | | | | | (4 bytes) |
3773 3781 | | | | | |
3774 3782 +--------------------------------------------------+
3775 3783 </pre>
3776 3784 <p>
3777 3785 The final filelog sub-segment is followed by an *empty chunk* (logically,
3778 3786 a sub-segment with filename size 0). This denotes the end of the segment
3779 3787 and of the overall changegroup.
3780 3788 </p>
3781 3789 <p>
3782 3790 Each filelog sub-segment consists of the following:
3783 3791 </p>
3784 3792 <pre>
3785 3793 +------------------------------------------------------+
3786 3794 | | | |
3787 3795 | filename length | filename | delta group |
3788 3796 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3789 3797 | | | |
3790 3798 +------------------------------------------------------+
3791 3799 </pre>
3792 3800 <p>
3793 3801 That is, a *chunk* consisting of the filename (not terminated or padded)
3794 3802 followed by N chunks constituting the *delta group* for this file. The
3795 3803 *empty chunk* at the end of each *delta group* denotes the boundary to the
3796 3804 next filelog sub-segment.
3797 3805 </p>
3798 3806
3799 3807 </div>
3800 3808 </div>
3801 3809 </div>
3802 3810
3803 3811
3804 3812
3805 3813 </body>
3806 3814 </html>
3807 3815
3808 3816
3809 3817 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3810 3818 404 Not Found
3811 3819
3812 3820 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3813 3821 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3814 3822 <head>
3815 3823 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3816 3824 <meta name="robots" content="index, nofollow" />
3817 3825 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3818 3826 <script type="text/javascript" src="/static/mercurial.js"></script>
3819 3827
3820 3828 <title>test: error</title>
3821 3829 </head>
3822 3830 <body>
3823 3831
3824 3832 <div class="container">
3825 3833 <div class="menu">
3826 3834 <div class="logo">
3827 3835 <a href="https://mercurial-scm.org/">
3828 3836 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3829 3837 </div>
3830 3838 <ul>
3831 3839 <li><a href="/shortlog">log</a></li>
3832 3840 <li><a href="/graph">graph</a></li>
3833 3841 <li><a href="/tags">tags</a></li>
3834 3842 <li><a href="/bookmarks">bookmarks</a></li>
3835 3843 <li><a href="/branches">branches</a></li>
3836 3844 </ul>
3837 3845 <ul>
3838 3846 <li><a href="/help">help</a></li>
3839 3847 </ul>
3840 3848 </div>
3841 3849
3842 3850 <div class="main">
3843 3851
3844 3852 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3845 3853 <h3>error</h3>
3846 3854
3847 3855
3848 3856 <form class="search" action="/log">
3849 3857
3850 3858 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3851 3859 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3852 3860 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3853 3861 </form>
3854 3862
3855 3863 <div class="description">
3856 3864 <p>
3857 3865 An error occurred while processing your request:
3858 3866 </p>
3859 3867 <p>
3860 3868 Not Found
3861 3869 </p>
3862 3870 </div>
3863 3871 </div>
3864 3872 </div>
3865 3873
3866 3874
3867 3875
3868 3876 </body>
3869 3877 </html>
3870 3878
3871 3879 [1]
3872 3880
3873 3881 $ killdaemons.py
3874 3882
3875 3883 #endif
@@ -1,2228 +1,2232 b''
1 1 #require serve
2 2
3 3 $ request() {
4 4 > get-with-headers.py --json localhost:$HGPORT "$1"
5 5 > }
6 6
7 7 $ hg init test
8 8 $ cd test
9 9 $ mkdir da
10 10 $ echo foo > da/foo
11 11 $ echo foo > foo
12 12 $ hg -q ci -A -m initial
13 13 $ echo bar > foo
14 14 $ hg ci -m 'modify foo'
15 15 $ echo bar > da/foo
16 16 $ hg ci -m 'modify da/foo'
17 17 $ hg bookmark bookmark1
18 18 $ hg up default
19 19 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20 (leaving bookmark bookmark1)
21 21 $ hg mv foo foo-new
22 22 $ hg commit -m 'move foo'
23 23 $ hg tag -m 'create tag' tag1
24 24 $ hg phase --public -r .
25 25 $ echo baz > da/foo
26 26 $ hg commit -m 'another commit to da/foo'
27 27 $ hg tag -m 'create tag2' tag2
28 28 $ hg bookmark bookmark2
29 29 $ hg -q up -r 0
30 30 $ hg -q branch test-branch
31 31 $ echo branch > foo
32 32 $ hg commit -m 'create test branch'
33 33 $ echo branch_commit_2 > foo
34 34 $ hg commit -m 'another commit in test-branch'
35 35 $ hg -q up default
36 36 $ hg merge --tool :local test-branch
37 37 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
38 38 (branch merge, don't forget to commit)
39 39 $ hg commit -m 'merge test-branch into default'
40 40
41 41 $ hg log -G
42 42 @ changeset: 9:cc725e08502a
43 43 |\ tag: tip
44 44 | | parent: 6:ceed296fe500
45 45 | | parent: 8:ed66c30e87eb
46 46 | | user: test
47 47 | | date: Thu Jan 01 00:00:00 1970 +0000
48 48 | | summary: merge test-branch into default
49 49 | |
50 50 | o changeset: 8:ed66c30e87eb
51 51 | | branch: test-branch
52 52 | | user: test
53 53 | | date: Thu Jan 01 00:00:00 1970 +0000
54 54 | | summary: another commit in test-branch
55 55 | |
56 56 | o changeset: 7:6ab967a8ab34
57 57 | | branch: test-branch
58 58 | | parent: 0:06e557f3edf6
59 59 | | user: test
60 60 | | date: Thu Jan 01 00:00:00 1970 +0000
61 61 | | summary: create test branch
62 62 | |
63 63 o | changeset: 6:ceed296fe500
64 64 | | bookmark: bookmark2
65 65 | | user: test
66 66 | | date: Thu Jan 01 00:00:00 1970 +0000
67 67 | | summary: create tag2
68 68 | |
69 69 o | changeset: 5:f2890a05fea4
70 70 | | tag: tag2
71 71 | | user: test
72 72 | | date: Thu Jan 01 00:00:00 1970 +0000
73 73 | | summary: another commit to da/foo
74 74 | |
75 75 o | changeset: 4:93a8ce14f891
76 76 | | user: test
77 77 | | date: Thu Jan 01 00:00:00 1970 +0000
78 78 | | summary: create tag
79 79 | |
80 80 o | changeset: 3:78896eb0e102
81 81 | | tag: tag1
82 82 | | user: test
83 83 | | date: Thu Jan 01 00:00:00 1970 +0000
84 84 | | summary: move foo
85 85 | |
86 86 o | changeset: 2:8d7c456572ac
87 87 | | bookmark: bookmark1
88 88 | | user: test
89 89 | | date: Thu Jan 01 00:00:00 1970 +0000
90 90 | | summary: modify da/foo
91 91 | |
92 92 o | changeset: 1:f8bbb9024b10
93 93 |/ user: test
94 94 | date: Thu Jan 01 00:00:00 1970 +0000
95 95 | summary: modify foo
96 96 |
97 97 o changeset: 0:06e557f3edf6
98 98 user: test
99 99 date: Thu Jan 01 00:00:00 1970 +0000
100 100 summary: initial
101 101
102 102
103 103 $ echo '[web]' >> .hg/hgrc
104 104 $ echo 'allow-archive = bz2' >> .hg/hgrc
105 105 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E error.log
106 106 $ cat hg.pid >> $DAEMON_PIDS
107 107
108 108 (Try to keep these in roughly the order they are defined in webcommands.py)
109 109
110 110 (log is handled by filelog/ and changelog/ - ignore it)
111 111
112 112 (rawfile/ doesn't use templating - nothing to test)
113 113
114 114 file/{revision}/{path} shows file revision
115 115
116 116 $ request json-file/78896eb0e102/foo-new
117 117 200 Script output follows
118 118
119 119 {
120 120 "bookmarks": [],
121 121 "branch": "default",
122 122 "date": [
123 123 0.0,
124 124 0
125 125 ],
126 126 "desc": "move foo",
127 127 "lines": [
128 128 {
129 129 "line": "bar\n"
130 130 }
131 131 ],
132 132 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
133 133 "parents": [
134 134 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
135 135 ],
136 136 "path": "foo-new",
137 137 "phase": "public",
138 138 "tags": [
139 139 "tag1"
140 140 ],
141 141 "user": "test"
142 142 }
143 143
144 144 file/{revision} shows root directory info
145 145
146 146 $ request json-file/cc725e08502a
147 147 200 Script output follows
148 148
149 149 {
150 150 "abspath": "/",
151 151 "bookmarks": [],
152 152 "directories": [
153 153 {
154 154 "abspath": "/da",
155 155 "basename": "da",
156 156 "emptydirs": ""
157 157 }
158 158 ],
159 159 "files": [
160 160 {
161 161 "abspath": ".hgtags",
162 162 "basename": ".hgtags",
163 163 "date": [
164 164 0.0,
165 165 0
166 166 ],
167 167 "flags": "",
168 168 "size": 92
169 169 },
170 170 {
171 171 "abspath": "foo-new",
172 172 "basename": "foo-new",
173 173 "date": [
174 174 0.0,
175 175 0
176 176 ],
177 177 "flags": "",
178 178 "size": 4
179 179 }
180 180 ],
181 181 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
182 182 "tags": [
183 183 "tip"
184 184 ]
185 185 }
186 186
187 187 changelog/ shows information about several changesets
188 188
189 189 $ request json-changelog
190 190 200 Script output follows
191 191
192 192 {
193 193 "changeset_count": 10,
194 194 "changesets": [
195 195 {
196 196 "bookmarks": [],
197 197 "branch": "default",
198 198 "date": [
199 199 0.0,
200 200 0
201 201 ],
202 202 "desc": "merge test-branch into default",
203 203 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
204 204 "parents": [
205 205 "ceed296fe500c3fac9541e31dad860cb49c89e45",
206 206 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
207 207 ],
208 208 "phase": "draft",
209 209 "tags": [
210 210 "tip"
211 211 ],
212 212 "user": "test"
213 213 },
214 214 {
215 215 "bookmarks": [],
216 216 "branch": "test-branch",
217 217 "date": [
218 218 0.0,
219 219 0
220 220 ],
221 221 "desc": "another commit in test-branch",
222 222 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
223 223 "parents": [
224 224 "6ab967a8ab3489227a83f80e920faa039a71819f"
225 225 ],
226 226 "phase": "draft",
227 227 "tags": [],
228 228 "user": "test"
229 229 },
230 230 {
231 231 "bookmarks": [],
232 232 "branch": "test-branch",
233 233 "date": [
234 234 0.0,
235 235 0
236 236 ],
237 237 "desc": "create test branch",
238 238 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
239 239 "parents": [
240 240 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
241 241 ],
242 242 "phase": "draft",
243 243 "tags": [],
244 244 "user": "test"
245 245 },
246 246 {
247 247 "bookmarks": [
248 248 "bookmark2"
249 249 ],
250 250 "branch": "default",
251 251 "date": [
252 252 0.0,
253 253 0
254 254 ],
255 255 "desc": "create tag2",
256 256 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
257 257 "parents": [
258 258 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
259 259 ],
260 260 "phase": "draft",
261 261 "tags": [],
262 262 "user": "test"
263 263 },
264 264 {
265 265 "bookmarks": [],
266 266 "branch": "default",
267 267 "date": [
268 268 0.0,
269 269 0
270 270 ],
271 271 "desc": "another commit to da/foo",
272 272 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
273 273 "parents": [
274 274 "93a8ce14f89156426b7fa981af8042da53f03aa0"
275 275 ],
276 276 "phase": "draft",
277 277 "tags": [
278 278 "tag2"
279 279 ],
280 280 "user": "test"
281 281 },
282 282 {
283 283 "bookmarks": [],
284 284 "branch": "default",
285 285 "date": [
286 286 0.0,
287 287 0
288 288 ],
289 289 "desc": "create tag",
290 290 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
291 291 "parents": [
292 292 "78896eb0e102174ce9278438a95e12543e4367a7"
293 293 ],
294 294 "phase": "public",
295 295 "tags": [],
296 296 "user": "test"
297 297 },
298 298 {
299 299 "bookmarks": [],
300 300 "branch": "default",
301 301 "date": [
302 302 0.0,
303 303 0
304 304 ],
305 305 "desc": "move foo",
306 306 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
307 307 "parents": [
308 308 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
309 309 ],
310 310 "phase": "public",
311 311 "tags": [
312 312 "tag1"
313 313 ],
314 314 "user": "test"
315 315 },
316 316 {
317 317 "bookmarks": [
318 318 "bookmark1"
319 319 ],
320 320 "branch": "default",
321 321 "date": [
322 322 0.0,
323 323 0
324 324 ],
325 325 "desc": "modify da/foo",
326 326 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
327 327 "parents": [
328 328 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
329 329 ],
330 330 "phase": "public",
331 331 "tags": [],
332 332 "user": "test"
333 333 },
334 334 {
335 335 "bookmarks": [],
336 336 "branch": "default",
337 337 "date": [
338 338 0.0,
339 339 0
340 340 ],
341 341 "desc": "modify foo",
342 342 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
343 343 "parents": [
344 344 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
345 345 ],
346 346 "phase": "public",
347 347 "tags": [],
348 348 "user": "test"
349 349 },
350 350 {
351 351 "bookmarks": [],
352 352 "branch": "default",
353 353 "date": [
354 354 0.0,
355 355 0
356 356 ],
357 357 "desc": "initial",
358 358 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
359 359 "parents": [],
360 360 "phase": "public",
361 361 "tags": [],
362 362 "user": "test"
363 363 }
364 364 ],
365 365 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
366 366 }
367 367
368 368 changelog/{revision} shows information starting at a specific changeset
369 369
370 370 $ request json-changelog/f8bbb9024b10
371 371 200 Script output follows
372 372
373 373 {
374 374 "changeset_count": 10,
375 375 "changesets": [
376 376 {
377 377 "bookmarks": [],
378 378 "branch": "default",
379 379 "date": [
380 380 0.0,
381 381 0
382 382 ],
383 383 "desc": "modify foo",
384 384 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
385 385 "parents": [
386 386 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
387 387 ],
388 388 "phase": "public",
389 389 "tags": [],
390 390 "user": "test"
391 391 },
392 392 {
393 393 "bookmarks": [],
394 394 "branch": "default",
395 395 "date": [
396 396 0.0,
397 397 0
398 398 ],
399 399 "desc": "initial",
400 400 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
401 401 "parents": [],
402 402 "phase": "public",
403 403 "tags": [],
404 404 "user": "test"
405 405 }
406 406 ],
407 407 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8"
408 408 }
409 409
410 410 shortlog/ shows information about a set of changesets
411 411
412 412 $ request json-shortlog
413 413 200 Script output follows
414 414
415 415 {
416 416 "changeset_count": 10,
417 417 "changesets": [
418 418 {
419 419 "bookmarks": [],
420 420 "branch": "default",
421 421 "date": [
422 422 0.0,
423 423 0
424 424 ],
425 425 "desc": "merge test-branch into default",
426 426 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
427 427 "parents": [
428 428 "ceed296fe500c3fac9541e31dad860cb49c89e45",
429 429 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
430 430 ],
431 431 "phase": "draft",
432 432 "tags": [
433 433 "tip"
434 434 ],
435 435 "user": "test"
436 436 },
437 437 {
438 438 "bookmarks": [],
439 439 "branch": "test-branch",
440 440 "date": [
441 441 0.0,
442 442 0
443 443 ],
444 444 "desc": "another commit in test-branch",
445 445 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
446 446 "parents": [
447 447 "6ab967a8ab3489227a83f80e920faa039a71819f"
448 448 ],
449 449 "phase": "draft",
450 450 "tags": [],
451 451 "user": "test"
452 452 },
453 453 {
454 454 "bookmarks": [],
455 455 "branch": "test-branch",
456 456 "date": [
457 457 0.0,
458 458 0
459 459 ],
460 460 "desc": "create test branch",
461 461 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
462 462 "parents": [
463 463 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
464 464 ],
465 465 "phase": "draft",
466 466 "tags": [],
467 467 "user": "test"
468 468 },
469 469 {
470 470 "bookmarks": [
471 471 "bookmark2"
472 472 ],
473 473 "branch": "default",
474 474 "date": [
475 475 0.0,
476 476 0
477 477 ],
478 478 "desc": "create tag2",
479 479 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
480 480 "parents": [
481 481 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
482 482 ],
483 483 "phase": "draft",
484 484 "tags": [],
485 485 "user": "test"
486 486 },
487 487 {
488 488 "bookmarks": [],
489 489 "branch": "default",
490 490 "date": [
491 491 0.0,
492 492 0
493 493 ],
494 494 "desc": "another commit to da/foo",
495 495 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
496 496 "parents": [
497 497 "93a8ce14f89156426b7fa981af8042da53f03aa0"
498 498 ],
499 499 "phase": "draft",
500 500 "tags": [
501 501 "tag2"
502 502 ],
503 503 "user": "test"
504 504 },
505 505 {
506 506 "bookmarks": [],
507 507 "branch": "default",
508 508 "date": [
509 509 0.0,
510 510 0
511 511 ],
512 512 "desc": "create tag",
513 513 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
514 514 "parents": [
515 515 "78896eb0e102174ce9278438a95e12543e4367a7"
516 516 ],
517 517 "phase": "public",
518 518 "tags": [],
519 519 "user": "test"
520 520 },
521 521 {
522 522 "bookmarks": [],
523 523 "branch": "default",
524 524 "date": [
525 525 0.0,
526 526 0
527 527 ],
528 528 "desc": "move foo",
529 529 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
530 530 "parents": [
531 531 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
532 532 ],
533 533 "phase": "public",
534 534 "tags": [
535 535 "tag1"
536 536 ],
537 537 "user": "test"
538 538 },
539 539 {
540 540 "bookmarks": [
541 541 "bookmark1"
542 542 ],
543 543 "branch": "default",
544 544 "date": [
545 545 0.0,
546 546 0
547 547 ],
548 548 "desc": "modify da/foo",
549 549 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
550 550 "parents": [
551 551 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
552 552 ],
553 553 "phase": "public",
554 554 "tags": [],
555 555 "user": "test"
556 556 },
557 557 {
558 558 "bookmarks": [],
559 559 "branch": "default",
560 560 "date": [
561 561 0.0,
562 562 0
563 563 ],
564 564 "desc": "modify foo",
565 565 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
566 566 "parents": [
567 567 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
568 568 ],
569 569 "phase": "public",
570 570 "tags": [],
571 571 "user": "test"
572 572 },
573 573 {
574 574 "bookmarks": [],
575 575 "branch": "default",
576 576 "date": [
577 577 0.0,
578 578 0
579 579 ],
580 580 "desc": "initial",
581 581 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
582 582 "parents": [],
583 583 "phase": "public",
584 584 "tags": [],
585 585 "user": "test"
586 586 }
587 587 ],
588 588 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
589 589 }
590 590
591 591 shortlog is displayed by default (issue5978)
592 592
593 593 $ request '?style=json'
594 594 200 Script output follows
595 595
596 596 {
597 597 "changeset_count": 10,
598 598 "changesets": [
599 599 {
600 600 "bookmarks": [],
601 601 "branch": "default",
602 602 "date": [
603 603 0.0,
604 604 0
605 605 ],
606 606 "desc": "merge test-branch into default",
607 607 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
608 608 "parents": [
609 609 "ceed296fe500c3fac9541e31dad860cb49c89e45",
610 610 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
611 611 ],
612 612 "phase": "draft",
613 613 "tags": [
614 614 "tip"
615 615 ],
616 616 "user": "test"
617 617 },
618 618 {
619 619 "bookmarks": [],
620 620 "branch": "test-branch",
621 621 "date": [
622 622 0.0,
623 623 0
624 624 ],
625 625 "desc": "another commit in test-branch",
626 626 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
627 627 "parents": [
628 628 "6ab967a8ab3489227a83f80e920faa039a71819f"
629 629 ],
630 630 "phase": "draft",
631 631 "tags": [],
632 632 "user": "test"
633 633 },
634 634 {
635 635 "bookmarks": [],
636 636 "branch": "test-branch",
637 637 "date": [
638 638 0.0,
639 639 0
640 640 ],
641 641 "desc": "create test branch",
642 642 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
643 643 "parents": [
644 644 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
645 645 ],
646 646 "phase": "draft",
647 647 "tags": [],
648 648 "user": "test"
649 649 },
650 650 {
651 651 "bookmarks": [
652 652 "bookmark2"
653 653 ],
654 654 "branch": "default",
655 655 "date": [
656 656 0.0,
657 657 0
658 658 ],
659 659 "desc": "create tag2",
660 660 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
661 661 "parents": [
662 662 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
663 663 ],
664 664 "phase": "draft",
665 665 "tags": [],
666 666 "user": "test"
667 667 },
668 668 {
669 669 "bookmarks": [],
670 670 "branch": "default",
671 671 "date": [
672 672 0.0,
673 673 0
674 674 ],
675 675 "desc": "another commit to da/foo",
676 676 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
677 677 "parents": [
678 678 "93a8ce14f89156426b7fa981af8042da53f03aa0"
679 679 ],
680 680 "phase": "draft",
681 681 "tags": [
682 682 "tag2"
683 683 ],
684 684 "user": "test"
685 685 },
686 686 {
687 687 "bookmarks": [],
688 688 "branch": "default",
689 689 "date": [
690 690 0.0,
691 691 0
692 692 ],
693 693 "desc": "create tag",
694 694 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
695 695 "parents": [
696 696 "78896eb0e102174ce9278438a95e12543e4367a7"
697 697 ],
698 698 "phase": "public",
699 699 "tags": [],
700 700 "user": "test"
701 701 },
702 702 {
703 703 "bookmarks": [],
704 704 "branch": "default",
705 705 "date": [
706 706 0.0,
707 707 0
708 708 ],
709 709 "desc": "move foo",
710 710 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
711 711 "parents": [
712 712 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
713 713 ],
714 714 "phase": "public",
715 715 "tags": [
716 716 "tag1"
717 717 ],
718 718 "user": "test"
719 719 },
720 720 {
721 721 "bookmarks": [
722 722 "bookmark1"
723 723 ],
724 724 "branch": "default",
725 725 "date": [
726 726 0.0,
727 727 0
728 728 ],
729 729 "desc": "modify da/foo",
730 730 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
731 731 "parents": [
732 732 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
733 733 ],
734 734 "phase": "public",
735 735 "tags": [],
736 736 "user": "test"
737 737 },
738 738 {
739 739 "bookmarks": [],
740 740 "branch": "default",
741 741 "date": [
742 742 0.0,
743 743 0
744 744 ],
745 745 "desc": "modify foo",
746 746 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
747 747 "parents": [
748 748 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
749 749 ],
750 750 "phase": "public",
751 751 "tags": [],
752 752 "user": "test"
753 753 },
754 754 {
755 755 "bookmarks": [],
756 756 "branch": "default",
757 757 "date": [
758 758 0.0,
759 759 0
760 760 ],
761 761 "desc": "initial",
762 762 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
763 763 "parents": [],
764 764 "phase": "public",
765 765 "tags": [],
766 766 "user": "test"
767 767 }
768 768 ],
769 769 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
770 770 }
771 771
772 772 changeset/ renders the tip changeset
773 773
774 774 $ request json-rev
775 775 200 Script output follows
776 776
777 777 {
778 778 "bookmarks": [],
779 779 "branch": "default",
780 780 "date": [
781 781 0.0,
782 782 0
783 783 ],
784 784 "desc": "merge test-branch into default",
785 785 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
786 786 "parents": [
787 787 "ceed296fe500c3fac9541e31dad860cb49c89e45",
788 788 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
789 789 ],
790 790 "phase": "draft",
791 791 "tags": [
792 792 "tip"
793 793 ],
794 794 "user": "test"
795 795 }
796 796
797 797 changeset/{revision} shows tags
798 798
799 799 $ request json-rev/78896eb0e102
800 800 200 Script output follows
801 801
802 802 {
803 803 "bookmarks": [],
804 804 "branch": "default",
805 805 "date": [
806 806 0.0,
807 807 0
808 808 ],
809 809 "desc": "move foo",
810 810 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
811 811 "parents": [
812 812 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
813 813 ],
814 814 "phase": "public",
815 815 "tags": [
816 816 "tag1"
817 817 ],
818 818 "user": "test"
819 819 }
820 820
821 821 changeset/{revision} shows bookmarks
822 822
823 823 $ request json-rev/8d7c456572ac
824 824 200 Script output follows
825 825
826 826 {
827 827 "bookmarks": [
828 828 "bookmark1"
829 829 ],
830 830 "branch": "default",
831 831 "date": [
832 832 0.0,
833 833 0
834 834 ],
835 835 "desc": "modify da/foo",
836 836 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
837 837 "parents": [
838 838 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
839 839 ],
840 840 "phase": "public",
841 841 "tags": [],
842 842 "user": "test"
843 843 }
844 844
845 845 changeset/{revision} shows branches
846 846
847 847 $ request json-rev/6ab967a8ab34
848 848 200 Script output follows
849 849
850 850 {
851 851 "bookmarks": [],
852 852 "branch": "test-branch",
853 853 "date": [
854 854 0.0,
855 855 0
856 856 ],
857 857 "desc": "create test branch",
858 858 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
859 859 "parents": [
860 860 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
861 861 ],
862 862 "phase": "draft",
863 863 "tags": [],
864 864 "user": "test"
865 865 }
866 866
867 867 manifest/{revision}/{path} shows info about a directory at a revision
868 868
869 869 $ request json-manifest/06e557f3edf6/
870 870 200 Script output follows
871 871
872 872 {
873 873 "abspath": "/",
874 874 "bookmarks": [],
875 875 "directories": [
876 876 {
877 877 "abspath": "/da",
878 878 "basename": "da",
879 879 "emptydirs": ""
880 880 }
881 881 ],
882 882 "files": [
883 883 {
884 884 "abspath": "foo",
885 885 "basename": "foo",
886 886 "date": [
887 887 0.0,
888 888 0
889 889 ],
890 890 "flags": "",
891 891 "size": 4
892 892 }
893 893 ],
894 894 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
895 895 "tags": []
896 896 }
897 897
898 898 tags/ shows tags info
899 899
900 900 $ request json-tags
901 901 200 Script output follows
902 902
903 903 {
904 904 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
905 905 "tags": [
906 906 {
907 907 "date": [
908 908 0.0,
909 909 0
910 910 ],
911 911 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
912 912 "tag": "tag2"
913 913 },
914 914 {
915 915 "date": [
916 916 0.0,
917 917 0
918 918 ],
919 919 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
920 920 "tag": "tag1"
921 921 }
922 922 ]
923 923 }
924 924
925 925 bookmarks/ shows bookmarks info
926 926
927 927 $ request json-bookmarks
928 928 200 Script output follows
929 929
930 930 {
931 931 "bookmarks": [
932 932 {
933 933 "bookmark": "bookmark2",
934 934 "date": [
935 935 0.0,
936 936 0
937 937 ],
938 938 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45"
939 939 },
940 940 {
941 941 "bookmark": "bookmark1",
942 942 "date": [
943 943 0.0,
944 944 0
945 945 ],
946 946 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5"
947 947 }
948 948 ],
949 949 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
950 950 }
951 951
952 952 branches/ shows branches info
953 953
954 954 $ request json-branches
955 955 200 Script output follows
956 956
957 957 {
958 958 "branches": [
959 959 {
960 960 "branch": "default",
961 961 "date": [
962 962 0.0,
963 963 0
964 964 ],
965 965 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
966 966 "status": "open"
967 967 },
968 968 {
969 969 "branch": "test-branch",
970 970 "date": [
971 971 0.0,
972 972 0
973 973 ],
974 974 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
975 975 "status": "inactive"
976 976 }
977 977 ]
978 978 }
979 979
980 980 summary/ shows a summary of repository state
981 981
982 982 $ request json-summary
983 983 200 Script output follows
984 984
985 985 {
986 986 "archives": [
987 987 {
988 988 "extension": ".tar.bz2",
989 989 "node": "tip",
990 990 "type": "bz2",
991 991 "url": "http://*:$HGPORT/archive/tip.tar.bz2" (glob)
992 992 }
993 993 ],
994 994 "bookmarks": [
995 995 {
996 996 "bookmark": "bookmark2",
997 997 "date": [
998 998 0.0,
999 999 0
1000 1000 ],
1001 1001 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45"
1002 1002 },
1003 1003 {
1004 1004 "bookmark": "bookmark1",
1005 1005 "date": [
1006 1006 0.0,
1007 1007 0
1008 1008 ],
1009 1009 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5"
1010 1010 }
1011 1011 ],
1012 1012 "branches": [
1013 1013 {
1014 1014 "branch": "default",
1015 1015 "date": [
1016 1016 0.0,
1017 1017 0
1018 1018 ],
1019 1019 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1020 1020 "status": "open"
1021 1021 },
1022 1022 {
1023 1023 "branch": "test-branch",
1024 1024 "date": [
1025 1025 0.0,
1026 1026 0
1027 1027 ],
1028 1028 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
1029 1029 "status": "inactive"
1030 1030 }
1031 1031 ],
1032 1032 "labels": [],
1033 1033 "lastchange": [
1034 1034 0.0,
1035 1035 0
1036 1036 ],
1037 1037 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1038 1038 "shortlog": [
1039 1039 {
1040 1040 "bookmarks": [],
1041 1041 "branch": "default",
1042 1042 "date": [
1043 1043 0.0,
1044 1044 0
1045 1045 ],
1046 1046 "desc": "merge test-branch into default",
1047 1047 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1048 1048 "parents": [
1049 1049 "ceed296fe500c3fac9541e31dad860cb49c89e45",
1050 1050 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
1051 1051 ],
1052 1052 "phase": "draft",
1053 1053 "tags": [
1054 1054 "tip"
1055 1055 ],
1056 1056 "user": "test"
1057 1057 },
1058 1058 {
1059 1059 "bookmarks": [],
1060 1060 "branch": "test-branch",
1061 1061 "date": [
1062 1062 0.0,
1063 1063 0
1064 1064 ],
1065 1065 "desc": "another commit in test-branch",
1066 1066 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
1067 1067 "parents": [
1068 1068 "6ab967a8ab3489227a83f80e920faa039a71819f"
1069 1069 ],
1070 1070 "phase": "draft",
1071 1071 "tags": [],
1072 1072 "user": "test"
1073 1073 },
1074 1074 {
1075 1075 "bookmarks": [],
1076 1076 "branch": "test-branch",
1077 1077 "date": [
1078 1078 0.0,
1079 1079 0
1080 1080 ],
1081 1081 "desc": "create test branch",
1082 1082 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
1083 1083 "parents": [
1084 1084 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1085 1085 ],
1086 1086 "phase": "draft",
1087 1087 "tags": [],
1088 1088 "user": "test"
1089 1089 },
1090 1090 {
1091 1091 "bookmarks": [
1092 1092 "bookmark2"
1093 1093 ],
1094 1094 "branch": "default",
1095 1095 "date": [
1096 1096 0.0,
1097 1097 0
1098 1098 ],
1099 1099 "desc": "create tag2",
1100 1100 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
1101 1101 "parents": [
1102 1102 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
1103 1103 ],
1104 1104 "phase": "draft",
1105 1105 "tags": [],
1106 1106 "user": "test"
1107 1107 },
1108 1108 {
1109 1109 "bookmarks": [],
1110 1110 "branch": "default",
1111 1111 "date": [
1112 1112 0.0,
1113 1113 0
1114 1114 ],
1115 1115 "desc": "another commit to da/foo",
1116 1116 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1117 1117 "parents": [
1118 1118 "93a8ce14f89156426b7fa981af8042da53f03aa0"
1119 1119 ],
1120 1120 "phase": "draft",
1121 1121 "tags": [
1122 1122 "tag2"
1123 1123 ],
1124 1124 "user": "test"
1125 1125 },
1126 1126 {
1127 1127 "bookmarks": [],
1128 1128 "branch": "default",
1129 1129 "date": [
1130 1130 0.0,
1131 1131 0
1132 1132 ],
1133 1133 "desc": "create tag",
1134 1134 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
1135 1135 "parents": [
1136 1136 "78896eb0e102174ce9278438a95e12543e4367a7"
1137 1137 ],
1138 1138 "phase": "public",
1139 1139 "tags": [],
1140 1140 "user": "test"
1141 1141 },
1142 1142 {
1143 1143 "bookmarks": [],
1144 1144 "branch": "default",
1145 1145 "date": [
1146 1146 0.0,
1147 1147 0
1148 1148 ],
1149 1149 "desc": "move foo",
1150 1150 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
1151 1151 "parents": [
1152 1152 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
1153 1153 ],
1154 1154 "phase": "public",
1155 1155 "tags": [
1156 1156 "tag1"
1157 1157 ],
1158 1158 "user": "test"
1159 1159 },
1160 1160 {
1161 1161 "bookmarks": [
1162 1162 "bookmark1"
1163 1163 ],
1164 1164 "branch": "default",
1165 1165 "date": [
1166 1166 0.0,
1167 1167 0
1168 1168 ],
1169 1169 "desc": "modify da/foo",
1170 1170 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
1171 1171 "parents": [
1172 1172 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
1173 1173 ],
1174 1174 "phase": "public",
1175 1175 "tags": [],
1176 1176 "user": "test"
1177 1177 },
1178 1178 {
1179 1179 "bookmarks": [],
1180 1180 "branch": "default",
1181 1181 "date": [
1182 1182 0.0,
1183 1183 0
1184 1184 ],
1185 1185 "desc": "modify foo",
1186 1186 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1187 1187 "parents": [
1188 1188 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1189 1189 ],
1190 1190 "phase": "public",
1191 1191 "tags": [],
1192 1192 "user": "test"
1193 1193 },
1194 1194 {
1195 1195 "bookmarks": [],
1196 1196 "branch": "default",
1197 1197 "date": [
1198 1198 0.0,
1199 1199 0
1200 1200 ],
1201 1201 "desc": "initial",
1202 1202 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1203 1203 "parents": [],
1204 1204 "phase": "public",
1205 1205 "tags": [],
1206 1206 "user": "test"
1207 1207 }
1208 1208 ],
1209 1209 "tags": [
1210 1210 {
1211 1211 "date": [
1212 1212 0.0,
1213 1213 0
1214 1214 ],
1215 1215 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1216 1216 "tag": "tag2"
1217 1217 },
1218 1218 {
1219 1219 "date": [
1220 1220 0.0,
1221 1221 0
1222 1222 ],
1223 1223 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
1224 1224 "tag": "tag1"
1225 1225 }
1226 1226 ]
1227 1227 }
1228 1228
1229 1229 $ request json-changelog?rev=create
1230 1230 200 Script output follows
1231 1231
1232 1232 {
1233 1233 "entries": [
1234 1234 {
1235 1235 "bookmarks": [],
1236 1236 "branch": "test-branch",
1237 1237 "date": [
1238 1238 0.0,
1239 1239 0
1240 1240 ],
1241 1241 "desc": "create test branch",
1242 1242 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
1243 1243 "parents": [
1244 1244 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1245 1245 ],
1246 1246 "phase": "draft",
1247 1247 "tags": [],
1248 1248 "user": "test"
1249 1249 },
1250 1250 {
1251 1251 "bookmarks": [
1252 1252 "bookmark2"
1253 1253 ],
1254 1254 "branch": "default",
1255 1255 "date": [
1256 1256 0.0,
1257 1257 0
1258 1258 ],
1259 1259 "desc": "create tag2",
1260 1260 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
1261 1261 "parents": [
1262 1262 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
1263 1263 ],
1264 1264 "phase": "draft",
1265 1265 "tags": [],
1266 1266 "user": "test"
1267 1267 },
1268 1268 {
1269 1269 "bookmarks": [],
1270 1270 "branch": "default",
1271 1271 "date": [
1272 1272 0.0,
1273 1273 0
1274 1274 ],
1275 1275 "desc": "create tag",
1276 1276 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
1277 1277 "parents": [
1278 1278 "78896eb0e102174ce9278438a95e12543e4367a7"
1279 1279 ],
1280 1280 "phase": "public",
1281 1281 "tags": [],
1282 1282 "user": "test"
1283 1283 }
1284 1284 ],
1285 1285 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1286 1286 "query": "create"
1287 1287 }
1288 1288
1289 1289 filediff/{revision}/{path} shows changes to a file in a revision
1290 1290
1291 1291 $ request json-diff/f8bbb9024b10/foo
1292 1292 200 Script output follows
1293 1293
1294 1294 {
1295 1295 "author": "test",
1296 1296 "children": [],
1297 1297 "date": [
1298 1298 0.0,
1299 1299 0
1300 1300 ],
1301 1301 "desc": "modify foo",
1302 1302 "diff": [
1303 1303 {
1304 1304 "blockno": 1,
1305 1305 "lines": [
1306 1306 {
1307 1307 "l": "--- a/foo\tThu Jan 01 00:00:00 1970 +0000\n",
1308 1308 "n": 1,
1309 1309 "t": "-"
1310 1310 },
1311 1311 {
1312 1312 "l": "+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n",
1313 1313 "n": 2,
1314 1314 "t": "+"
1315 1315 },
1316 1316 {
1317 1317 "l": "@@ -1,1 +1,1 @@\n",
1318 1318 "n": 3,
1319 1319 "t": "@"
1320 1320 },
1321 1321 {
1322 1322 "l": "-foo\n",
1323 1323 "n": 4,
1324 1324 "t": "-"
1325 1325 },
1326 1326 {
1327 1327 "l": "+bar\n",
1328 1328 "n": 5,
1329 1329 "t": "+"
1330 1330 }
1331 1331 ]
1332 1332 }
1333 1333 ],
1334 1334 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1335 1335 "parents": [
1336 1336 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1337 1337 ],
1338 1338 "path": "foo"
1339 1339 }
1340 1340
1341 1341 comparison/{revision}/{path} shows information about before and after for a file
1342 1342
1343 1343 $ request json-comparison/f8bbb9024b10/foo
1344 1344 200 Script output follows
1345 1345
1346 1346 {
1347 1347 "author": "test",
1348 1348 "children": [],
1349 1349 "comparison": [
1350 1350 {
1351 1351 "lines": [
1352 1352 {
1353 1353 "ll": "foo",
1354 1354 "ln": 1,
1355 1355 "rl": "bar",
1356 1356 "rn": 1,
1357 1357 "t": "replace"
1358 1358 }
1359 1359 ]
1360 1360 }
1361 1361 ],
1362 1362 "date": [
1363 1363 0.0,
1364 1364 0
1365 1365 ],
1366 1366 "desc": "modify foo",
1367 1367 "leftnode": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1368 1368 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1369 1369 "parents": [
1370 1370 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1371 1371 ],
1372 1372 "path": "foo",
1373 1373 "rightnode": "f8bbb9024b10f93cdbb8d940337398291d40dea8"
1374 1374 }
1375 1375
1376 1376 annotate/{revision}/{path} shows annotations for each line
1377 1377
1378 1378 $ request json-annotate/f8bbb9024b10/foo
1379 1379 200 Script output follows
1380 1380
1381 1381 {
1382 1382 "abspath": "foo",
1383 1383 "annotate": [
1384 1384 {
1385 1385 "abspath": "foo",
1386 1386 "author": "test",
1387 1387 "desc": "modify foo",
1388 1388 "line": "bar\n",
1389 1389 "lineno": 1,
1390 1390 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1391 1391 "revdate": [
1392 1392 0.0,
1393 1393 0
1394 1394 ],
1395 1395 "targetline": 1
1396 1396 }
1397 1397 ],
1398 1398 "author": "test",
1399 1399 "children": [],
1400 1400 "date": [
1401 1401 0.0,
1402 1402 0
1403 1403 ],
1404 1404 "desc": "modify foo",
1405 1405 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1406 1406 "parents": [
1407 1407 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1408 1408 ],
1409 1409 "permissions": ""
1410 1410 }
1411 1411
1412 1412 filelog/{revision}/{path} shows history of a single file
1413 1413
1414 1414 $ request json-filelog/f8bbb9024b10/foo
1415 1415 200 Script output follows
1416 1416
1417 1417 {
1418 1418 "entries": [
1419 1419 {
1420 1420 "bookmarks": [],
1421 1421 "branch": "default",
1422 1422 "date": [
1423 1423 0.0,
1424 1424 0
1425 1425 ],
1426 1426 "desc": "modify foo",
1427 1427 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1428 1428 "parents": [
1429 1429 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1430 1430 ],
1431 1431 "phase": "public",
1432 1432 "tags": [],
1433 1433 "user": "test"
1434 1434 },
1435 1435 {
1436 1436 "bookmarks": [],
1437 1437 "branch": "default",
1438 1438 "date": [
1439 1439 0.0,
1440 1440 0
1441 1441 ],
1442 1442 "desc": "initial",
1443 1443 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1444 1444 "parents": [],
1445 1445 "phase": "public",
1446 1446 "tags": [],
1447 1447 "user": "test"
1448 1448 }
1449 1449 ]
1450 1450 }
1451 1451
1452 1452 $ request json-filelog/cc725e08502a/da/foo
1453 1453 200 Script output follows
1454 1454
1455 1455 {
1456 1456 "entries": [
1457 1457 {
1458 1458 "bookmarks": [],
1459 1459 "branch": "default",
1460 1460 "date": [
1461 1461 0.0,
1462 1462 0
1463 1463 ],
1464 1464 "desc": "another commit to da/foo",
1465 1465 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1466 1466 "parents": [
1467 1467 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
1468 1468 ],
1469 1469 "phase": "draft",
1470 1470 "tags": [
1471 1471 "tag2"
1472 1472 ],
1473 1473 "user": "test"
1474 1474 },
1475 1475 {
1476 1476 "bookmarks": [
1477 1477 "bookmark1"
1478 1478 ],
1479 1479 "branch": "default",
1480 1480 "date": [
1481 1481 0.0,
1482 1482 0
1483 1483 ],
1484 1484 "desc": "modify da/foo",
1485 1485 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
1486 1486 "parents": [
1487 1487 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1488 1488 ],
1489 1489 "phase": "public",
1490 1490 "tags": [],
1491 1491 "user": "test"
1492 1492 },
1493 1493 {
1494 1494 "bookmarks": [],
1495 1495 "branch": "default",
1496 1496 "date": [
1497 1497 0.0,
1498 1498 0
1499 1499 ],
1500 1500 "desc": "initial",
1501 1501 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1502 1502 "parents": [],
1503 1503 "phase": "public",
1504 1504 "tags": [],
1505 1505 "user": "test"
1506 1506 }
1507 1507 ]
1508 1508 }
1509 1509
1510 1510 (archive/ doesn't use templating, so ignore it)
1511 1511
1512 1512 (static/ doesn't use templating, so ignore it)
1513 1513
1514 1514 graph/ shows information that can be used to render a graph of the DAG
1515 1515
1516 1516 $ request json-graph
1517 1517 200 Script output follows
1518 1518
1519 1519 {
1520 1520 "changeset_count": 10,
1521 1521 "changesets": [
1522 1522 {
1523 1523 "bookmarks": [],
1524 1524 "branch": "default",
1525 1525 "col": 0,
1526 1526 "color": 1,
1527 1527 "date": [
1528 1528 0.0,
1529 1529 0
1530 1530 ],
1531 1531 "desc": "merge test-branch into default",
1532 1532 "edges": [
1533 1533 {
1534 1534 "bcolor": "",
1535 1535 "col": 0,
1536 1536 "color": 1,
1537 1537 "nextcol": 0,
1538 1538 "width": -1
1539 1539 },
1540 1540 {
1541 1541 "bcolor": "",
1542 1542 "col": 0,
1543 1543 "color": 1,
1544 1544 "nextcol": 1,
1545 1545 "width": -1
1546 1546 }
1547 1547 ],
1548 1548 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1549 1549 "parents": [
1550 1550 "ceed296fe500c3fac9541e31dad860cb49c89e45",
1551 1551 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
1552 1552 ],
1553 1553 "phase": "draft",
1554 1554 "row": 0,
1555 1555 "tags": [
1556 1556 "tip"
1557 1557 ],
1558 1558 "user": "test"
1559 1559 },
1560 1560 {
1561 1561 "bookmarks": [],
1562 1562 "branch": "test-branch",
1563 1563 "col": 1,
1564 1564 "color": 2,
1565 1565 "date": [
1566 1566 0.0,
1567 1567 0
1568 1568 ],
1569 1569 "desc": "another commit in test-branch",
1570 1570 "edges": [
1571 1571 {
1572 1572 "bcolor": "",
1573 1573 "col": 0,
1574 1574 "color": 1,
1575 1575 "nextcol": 0,
1576 1576 "width": -1
1577 1577 },
1578 1578 {
1579 1579 "bcolor": "",
1580 1580 "col": 1,
1581 1581 "color": 2,
1582 1582 "nextcol": 1,
1583 1583 "width": -1
1584 1584 }
1585 1585 ],
1586 1586 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
1587 1587 "parents": [
1588 1588 "6ab967a8ab3489227a83f80e920faa039a71819f"
1589 1589 ],
1590 1590 "phase": "draft",
1591 1591 "row": 1,
1592 1592 "tags": [],
1593 1593 "user": "test"
1594 1594 },
1595 1595 {
1596 1596 "bookmarks": [],
1597 1597 "branch": "test-branch",
1598 1598 "col": 1,
1599 1599 "color": 2,
1600 1600 "date": [
1601 1601 0.0,
1602 1602 0
1603 1603 ],
1604 1604 "desc": "create test branch",
1605 1605 "edges": [
1606 1606 {
1607 1607 "bcolor": "",
1608 1608 "col": 0,
1609 1609 "color": 1,
1610 1610 "nextcol": 0,
1611 1611 "width": -1
1612 1612 },
1613 1613 {
1614 1614 "bcolor": "",
1615 1615 "col": 1,
1616 1616 "color": 2,
1617 1617 "nextcol": 1,
1618 1618 "width": -1
1619 1619 }
1620 1620 ],
1621 1621 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
1622 1622 "parents": [
1623 1623 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1624 1624 ],
1625 1625 "phase": "draft",
1626 1626 "row": 2,
1627 1627 "tags": [],
1628 1628 "user": "test"
1629 1629 },
1630 1630 {
1631 1631 "bookmarks": [
1632 1632 "bookmark2"
1633 1633 ],
1634 1634 "branch": "default",
1635 1635 "col": 0,
1636 1636 "color": 1,
1637 1637 "date": [
1638 1638 0.0,
1639 1639 0
1640 1640 ],
1641 1641 "desc": "create tag2",
1642 1642 "edges": [
1643 1643 {
1644 1644 "bcolor": "",
1645 1645 "col": 0,
1646 1646 "color": 1,
1647 1647 "nextcol": 0,
1648 1648 "width": -1
1649 1649 },
1650 1650 {
1651 1651 "bcolor": "",
1652 1652 "col": 1,
1653 1653 "color": 2,
1654 1654 "nextcol": 1,
1655 1655 "width": -1
1656 1656 }
1657 1657 ],
1658 1658 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
1659 1659 "parents": [
1660 1660 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
1661 1661 ],
1662 1662 "phase": "draft",
1663 1663 "row": 3,
1664 1664 "tags": [],
1665 1665 "user": "test"
1666 1666 },
1667 1667 {
1668 1668 "bookmarks": [],
1669 1669 "branch": "default",
1670 1670 "col": 0,
1671 1671 "color": 1,
1672 1672 "date": [
1673 1673 0.0,
1674 1674 0
1675 1675 ],
1676 1676 "desc": "another commit to da/foo",
1677 1677 "edges": [
1678 1678 {
1679 1679 "bcolor": "",
1680 1680 "col": 0,
1681 1681 "color": 1,
1682 1682 "nextcol": 0,
1683 1683 "width": -1
1684 1684 },
1685 1685 {
1686 1686 "bcolor": "",
1687 1687 "col": 1,
1688 1688 "color": 2,
1689 1689 "nextcol": 1,
1690 1690 "width": -1
1691 1691 }
1692 1692 ],
1693 1693 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1694 1694 "parents": [
1695 1695 "93a8ce14f89156426b7fa981af8042da53f03aa0"
1696 1696 ],
1697 1697 "phase": "draft",
1698 1698 "row": 4,
1699 1699 "tags": [
1700 1700 "tag2"
1701 1701 ],
1702 1702 "user": "test"
1703 1703 },
1704 1704 {
1705 1705 "bookmarks": [],
1706 1706 "branch": "default",
1707 1707 "col": 0,
1708 1708 "color": 1,
1709 1709 "date": [
1710 1710 0.0,
1711 1711 0
1712 1712 ],
1713 1713 "desc": "create tag",
1714 1714 "edges": [
1715 1715 {
1716 1716 "bcolor": "",
1717 1717 "col": 0,
1718 1718 "color": 1,
1719 1719 "nextcol": 0,
1720 1720 "width": -1
1721 1721 },
1722 1722 {
1723 1723 "bcolor": "",
1724 1724 "col": 1,
1725 1725 "color": 2,
1726 1726 "nextcol": 1,
1727 1727 "width": -1
1728 1728 }
1729 1729 ],
1730 1730 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
1731 1731 "parents": [
1732 1732 "78896eb0e102174ce9278438a95e12543e4367a7"
1733 1733 ],
1734 1734 "phase": "public",
1735 1735 "row": 5,
1736 1736 "tags": [],
1737 1737 "user": "test"
1738 1738 },
1739 1739 {
1740 1740 "bookmarks": [],
1741 1741 "branch": "default",
1742 1742 "col": 0,
1743 1743 "color": 1,
1744 1744 "date": [
1745 1745 0.0,
1746 1746 0
1747 1747 ],
1748 1748 "desc": "move foo",
1749 1749 "edges": [
1750 1750 {
1751 1751 "bcolor": "",
1752 1752 "col": 0,
1753 1753 "color": 1,
1754 1754 "nextcol": 0,
1755 1755 "width": -1
1756 1756 },
1757 1757 {
1758 1758 "bcolor": "",
1759 1759 "col": 1,
1760 1760 "color": 2,
1761 1761 "nextcol": 1,
1762 1762 "width": -1
1763 1763 }
1764 1764 ],
1765 1765 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
1766 1766 "parents": [
1767 1767 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
1768 1768 ],
1769 1769 "phase": "public",
1770 1770 "row": 6,
1771 1771 "tags": [
1772 1772 "tag1"
1773 1773 ],
1774 1774 "user": "test"
1775 1775 },
1776 1776 {
1777 1777 "bookmarks": [
1778 1778 "bookmark1"
1779 1779 ],
1780 1780 "branch": "default",
1781 1781 "col": 0,
1782 1782 "color": 1,
1783 1783 "date": [
1784 1784 0.0,
1785 1785 0
1786 1786 ],
1787 1787 "desc": "modify da/foo",
1788 1788 "edges": [
1789 1789 {
1790 1790 "bcolor": "",
1791 1791 "col": 0,
1792 1792 "color": 1,
1793 1793 "nextcol": 0,
1794 1794 "width": -1
1795 1795 },
1796 1796 {
1797 1797 "bcolor": "",
1798 1798 "col": 1,
1799 1799 "color": 2,
1800 1800 "nextcol": 1,
1801 1801 "width": -1
1802 1802 }
1803 1803 ],
1804 1804 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
1805 1805 "parents": [
1806 1806 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
1807 1807 ],
1808 1808 "phase": "public",
1809 1809 "row": 7,
1810 1810 "tags": [],
1811 1811 "user": "test"
1812 1812 },
1813 1813 {
1814 1814 "bookmarks": [],
1815 1815 "branch": "default",
1816 1816 "col": 0,
1817 1817 "color": 1,
1818 1818 "date": [
1819 1819 0.0,
1820 1820 0
1821 1821 ],
1822 1822 "desc": "modify foo",
1823 1823 "edges": [
1824 1824 {
1825 1825 "bcolor": "",
1826 1826 "col": 0,
1827 1827 "color": 1,
1828 1828 "nextcol": 0,
1829 1829 "width": -1
1830 1830 },
1831 1831 {
1832 1832 "bcolor": "",
1833 1833 "col": 1,
1834 1834 "color": 2,
1835 1835 "nextcol": 0,
1836 1836 "width": -1
1837 1837 }
1838 1838 ],
1839 1839 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1840 1840 "parents": [
1841 1841 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1842 1842 ],
1843 1843 "phase": "public",
1844 1844 "row": 8,
1845 1845 "tags": [],
1846 1846 "user": "test"
1847 1847 },
1848 1848 {
1849 1849 "bookmarks": [],
1850 1850 "branch": "default",
1851 1851 "col": 0,
1852 1852 "color": 2,
1853 1853 "date": [
1854 1854 0.0,
1855 1855 0
1856 1856 ],
1857 1857 "desc": "initial",
1858 1858 "edges": [],
1859 1859 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1860 1860 "parents": [],
1861 1861 "phase": "public",
1862 1862 "row": 9,
1863 1863 "tags": [],
1864 1864 "user": "test"
1865 1865 }
1866 1866 ],
1867 1867 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
1868 1868 }
1869 1869
1870 1870 help/ shows help topics
1871 1871
1872 1872 $ request json-help
1873 1873 200 Script output follows
1874 1874
1875 1875 {
1876 1876 "earlycommands": [
1877 1877 {
1878 "summary": "abort an unfinished operation (EXPERIMENTAL)",
1879 "topic": "abort"
1880 },
1881 {
1878 1882 "summary": "add the specified files on the next commit",
1879 1883 "topic": "add"
1880 1884 },
1881 1885 {
1882 1886 "summary": "show changeset information by line for each file",
1883 1887 "topic": "annotate"
1884 1888 },
1885 1889 {
1886 1890 "summary": "make a copy of an existing repository",
1887 1891 "topic": "clone"
1888 1892 },
1889 1893 {
1890 1894 "summary": "commit the specified files or all outstanding changes",
1891 1895 "topic": "commit"
1892 1896 },
1893 1897 {
1894 1898 "summary": "diff repository (or selected files)",
1895 1899 "topic": "diff"
1896 1900 },
1897 1901 {
1898 1902 "summary": "dump the header and diffs for one or more changesets",
1899 1903 "topic": "export"
1900 1904 },
1901 1905 {
1902 1906 "summary": "forget the specified files on the next commit",
1903 1907 "topic": "forget"
1904 1908 },
1905 1909 {
1906 1910 "summary": "create a new repository in the given directory",
1907 1911 "topic": "init"
1908 1912 },
1909 1913 {
1910 1914 "summary": "show revision history of entire repository or files",
1911 1915 "topic": "log"
1912 1916 },
1913 1917 {
1914 1918 "summary": "merge another revision into working directory",
1915 1919 "topic": "merge"
1916 1920 },
1917 1921 {
1918 1922 "summary": "pull changes from the specified source",
1919 1923 "topic": "pull"
1920 1924 },
1921 1925 {
1922 1926 "summary": "push changes to the specified destination",
1923 1927 "topic": "push"
1924 1928 },
1925 1929 {
1926 1930 "summary": "remove the specified files on the next commit",
1927 1931 "topic": "remove"
1928 1932 },
1929 1933 {
1930 1934 "summary": "start stand-alone webserver",
1931 1935 "topic": "serve"
1932 1936 },
1933 1937 {
1934 1938 "summary": "show changed files in the working directory",
1935 1939 "topic": "status"
1936 1940 },
1937 1941 {
1938 1942 "summary": "summarize working directory state",
1939 1943 "topic": "summary"
1940 1944 },
1941 1945 {
1942 1946 "summary": "update working directory (or switch revisions)",
1943 1947 "topic": "update"
1944 1948 }
1945 1949 ],
1946 1950 "othercommands": [
1947 1951 {
1948 1952 "summary": "add all new files, delete all missing files",
1949 1953 "topic": "addremove"
1950 1954 },
1951 1955 {
1952 1956 "summary": "create an unversioned archive of a repository revision",
1953 1957 "topic": "archive"
1954 1958 },
1955 1959 {
1956 1960 "summary": "reverse effect of earlier changeset",
1957 1961 "topic": "backout"
1958 1962 },
1959 1963 {
1960 1964 "summary": "subdivision search of changesets",
1961 1965 "topic": "bisect"
1962 1966 },
1963 1967 {
1964 1968 "summary": "create a new bookmark or list existing bookmarks",
1965 1969 "topic": "bookmarks"
1966 1970 },
1967 1971 {
1968 1972 "summary": "set or show the current branch name",
1969 1973 "topic": "branch"
1970 1974 },
1971 1975 {
1972 1976 "summary": "list repository named branches",
1973 1977 "topic": "branches"
1974 1978 },
1975 1979 {
1976 1980 "summary": "create a bundle file",
1977 1981 "topic": "bundle"
1978 1982 },
1979 1983 {
1980 1984 "summary": "output the current or given revision of files",
1981 1985 "topic": "cat"
1982 1986 },
1983 1987 {
1984 1988 "summary": "show combined config settings from all hgrc files",
1985 1989 "topic": "config"
1986 1990 },
1987 1991 {
1988 1992 "summary": "mark files as copied for the next commit",
1989 1993 "topic": "copy"
1990 1994 },
1991 1995 {
1992 1996 "summary": "list tracked files",
1993 1997 "topic": "files"
1994 1998 },
1995 1999 {
1996 2000 "summary": "copy changes from other branches onto the current branch",
1997 2001 "topic": "graft"
1998 2002 },
1999 2003 {
2000 2004 "summary": "search revision history for a pattern in specified files",
2001 2005 "topic": "grep"
2002 2006 },
2003 2007 {
2004 2008 "summary": "show branch heads",
2005 2009 "topic": "heads"
2006 2010 },
2007 2011 {
2008 2012 "summary": "show help for a given topic or a help overview",
2009 2013 "topic": "help"
2010 2014 },
2011 2015 {
2012 2016 "summary": "identify the working directory or specified revision",
2013 2017 "topic": "identify"
2014 2018 },
2015 2019 {
2016 2020 "summary": "import an ordered set of patches",
2017 2021 "topic": "import"
2018 2022 },
2019 2023 {
2020 2024 "summary": "show new changesets found in source",
2021 2025 "topic": "incoming"
2022 2026 },
2023 2027 {
2024 2028 "summary": "output the current or given revision of the project manifest",
2025 2029 "topic": "manifest"
2026 2030 },
2027 2031 {
2028 2032 "summary": "show changesets not found in the destination",
2029 2033 "topic": "outgoing"
2030 2034 },
2031 2035 {
2032 2036 "summary": "show aliases for remote repositories",
2033 2037 "topic": "paths"
2034 2038 },
2035 2039 {
2036 2040 "summary": "set or show the current phase name",
2037 2041 "topic": "phase"
2038 2042 },
2039 2043 {
2040 2044 "summary": "roll back an interrupted transaction",
2041 2045 "topic": "recover"
2042 2046 },
2043 2047 {
2044 2048 "summary": "rename files; equivalent of copy + remove",
2045 2049 "topic": "rename"
2046 2050 },
2047 2051 {
2048 2052 "summary": "redo merges or set/view the merge status of files",
2049 2053 "topic": "resolve"
2050 2054 },
2051 2055 {
2052 2056 "summary": "restore files to their checkout state",
2053 2057 "topic": "revert"
2054 2058 },
2055 2059 {
2056 2060 "summary": "print the root (top) of the current working directory",
2057 2061 "topic": "root"
2058 2062 },
2059 2063 {
2060 2064 "summary": "save and set aside changes from the working directory",
2061 2065 "topic": "shelve"
2062 2066 },
2063 2067 {
2064 2068 "summary": "add one or more tags for the current or given revision",
2065 2069 "topic": "tag"
2066 2070 },
2067 2071 {
2068 2072 "summary": "list repository tags",
2069 2073 "topic": "tags"
2070 2074 },
2071 2075 {
2072 2076 "summary": "apply one or more bundle files",
2073 2077 "topic": "unbundle"
2074 2078 },
2075 2079 {
2076 2080 "summary": "restore a shelved change to the working directory",
2077 2081 "topic": "unshelve"
2078 2082 },
2079 2083 {
2080 2084 "summary": "verify the integrity of the repository",
2081 2085 "topic": "verify"
2082 2086 },
2083 2087 {
2084 2088 "summary": "output version and copyright information",
2085 2089 "topic": "version"
2086 2090 }
2087 2091 ],
2088 2092 "topics": [
2089 2093 {
2090 2094 "summary": "Bundle File Formats",
2091 2095 "topic": "bundlespec"
2092 2096 },
2093 2097 {
2094 2098 "summary": "Colorizing Outputs",
2095 2099 "topic": "color"
2096 2100 },
2097 2101 {
2098 2102 "summary": "Configuration Files",
2099 2103 "topic": "config"
2100 2104 },
2101 2105 {
2102 2106 "summary": "Date Formats",
2103 2107 "topic": "dates"
2104 2108 },
2105 2109 {
2106 2110 "summary": "Deprecated Features",
2107 2111 "topic": "deprecated"
2108 2112 },
2109 2113 {
2110 2114 "summary": "Diff Formats",
2111 2115 "topic": "diffs"
2112 2116 },
2113 2117 {
2114 2118 "summary": "Environment Variables",
2115 2119 "topic": "environment"
2116 2120 },
2117 2121 {
2118 2122 "summary": "Using Additional Features",
2119 2123 "topic": "extensions"
2120 2124 },
2121 2125 {
2122 2126 "summary": "Specifying File Sets",
2123 2127 "topic": "filesets"
2124 2128 },
2125 2129 {
2126 2130 "summary": "Command-line flags",
2127 2131 "topic": "flags"
2128 2132 },
2129 2133 {
2130 2134 "summary": "Glossary",
2131 2135 "topic": "glossary"
2132 2136 },
2133 2137 {
2134 2138 "summary": "Syntax for Mercurial Ignore Files",
2135 2139 "topic": "hgignore"
2136 2140 },
2137 2141 {
2138 2142 "summary": "Configuring hgweb",
2139 2143 "topic": "hgweb"
2140 2144 },
2141 2145 {
2142 2146 "summary": "Technical implementation topics",
2143 2147 "topic": "internals"
2144 2148 },
2145 2149 {
2146 2150 "summary": "Merge Tools",
2147 2151 "topic": "merge-tools"
2148 2152 },
2149 2153 {
2150 2154 "summary": "Pager Support",
2151 2155 "topic": "pager"
2152 2156 },
2153 2157 {
2154 2158 "summary": "File Name Patterns",
2155 2159 "topic": "patterns"
2156 2160 },
2157 2161 {
2158 2162 "summary": "Working with Phases",
2159 2163 "topic": "phases"
2160 2164 },
2161 2165 {
2162 2166 "summary": "Specifying Revisions",
2163 2167 "topic": "revisions"
2164 2168 },
2165 2169 {
2166 2170 "summary": "Using Mercurial from scripts and automation",
2167 2171 "topic": "scripting"
2168 2172 },
2169 2173 {
2170 2174 "summary": "Subrepositories",
2171 2175 "topic": "subrepos"
2172 2176 },
2173 2177 {
2174 2178 "summary": "Template Usage",
2175 2179 "topic": "templating"
2176 2180 },
2177 2181 {
2178 2182 "summary": "URL Paths",
2179 2183 "topic": "urls"
2180 2184 }
2181 2185 ]
2182 2186 }
2183 2187
2184 2188 help/{topic} shows an individual help topic
2185 2189
2186 2190 $ request json-help/phases
2187 2191 200 Script output follows
2188 2192
2189 2193 {
2190 2194 "rawdoc": "Working with Phases\n*", (glob)
2191 2195 "topic": "phases"
2192 2196 }
2193 2197
2194 2198 Error page shouldn't crash
2195 2199
2196 2200 $ request json-changeset/deadbeef
2197 2201 404 Not Found
2198 2202
2199 2203 {
2200 2204 "error": "unknown revision 'deadbeef'"
2201 2205 }
2202 2206 [1]
2203 2207
2204 2208 Commit message with Japanese Kanji 'Noh', which ends with '\x5c'
2205 2209
2206 2210 $ echo foo >> da/foo
2207 2211 >>> open('msg', 'wb').write(b'\x94\x5c\x0a') and None
2208 2212 $ HGENCODING=cp932 hg ci -l msg
2209 2213
2210 2214 Commit message with null character
2211 2215
2212 2216 $ echo foo >> da/foo
2213 2217 >>> open('msg', 'wb').write(b'commit with null character: \0\n') and None
2214 2218 $ hg ci -l msg
2215 2219 $ rm msg
2216 2220
2217 2221 Stop and restart with HGENCODING=cp932
2218 2222
2219 2223 $ killdaemons.py
2220 2224 $ HGENCODING=cp932 hg serve -p $HGPORT -d --pid-file=hg.pid \
2221 2225 > -A access.log -E error.log
2222 2226 $ cat hg.pid >> $DAEMON_PIDS
2223 2227
2224 2228 Test json escape of multibyte characters
2225 2229
2226 2230 $ request json-filelog/tip/da/foo?revcount=2 | grep '"desc":'
2227 2231 "desc": "commit with null character: \u0000",
2228 2232 "desc": "\u80fd",
General Comments 0
You need to be logged in to leave comments. Login now