##// END OF EJS Templates
commands: update help for "bundle"...
Gregory Szorc -
r31794:54b1af73 default
parent child Browse files
Show More
@@ -1,5469 +1,5467 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
15 15 from .i18n import _
16 16 from .node import (
17 17 hex,
18 18 nullid,
19 19 nullrev,
20 20 short,
21 21 )
22 22 from . import (
23 23 archival,
24 24 bookmarks,
25 25 bundle2,
26 26 changegroup,
27 27 cmdutil,
28 28 copies,
29 29 destutil,
30 30 dirstateguard,
31 31 discovery,
32 32 encoding,
33 33 error,
34 34 exchange,
35 35 extensions,
36 36 graphmod,
37 37 hbisect,
38 38 help,
39 39 hg,
40 40 lock as lockmod,
41 41 merge as mergemod,
42 42 obsolete,
43 43 patch,
44 44 phases,
45 45 pycompat,
46 46 rcutil,
47 47 revsetlang,
48 48 scmutil,
49 49 server,
50 50 sshserver,
51 51 streamclone,
52 52 tags as tagsmod,
53 53 templatekw,
54 54 ui as uimod,
55 55 util,
56 56 )
57 57
58 58 release = lockmod.release
59 59
60 60 table = {}
61 61
62 62 command = cmdutil.command(table)
63 63
64 64 # label constants
65 65 # until 3.5, bookmarks.current was the advertised name, not
66 66 # bookmarks.active, so we must use both to avoid breaking old
67 67 # custom styles
68 68 activebookmarklabel = 'bookmarks.active bookmarks.current'
69 69
70 70 # common command options
71 71
72 72 globalopts = [
73 73 ('R', 'repository', '',
74 74 _('repository root directory or name of overlay bundle file'),
75 75 _('REPO')),
76 76 ('', 'cwd', '',
77 77 _('change working directory'), _('DIR')),
78 78 ('y', 'noninteractive', None,
79 79 _('do not prompt, automatically pick the first choice for all prompts')),
80 80 ('q', 'quiet', None, _('suppress output')),
81 81 ('v', 'verbose', None, _('enable additional output')),
82 82 ('', 'color', '',
83 83 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
84 84 # and should not be translated
85 85 _("when to colorize (boolean, always, auto, never, or debug)"),
86 86 _('TYPE')),
87 87 ('', 'config', [],
88 88 _('set/override config option (use \'section.name=value\')'),
89 89 _('CONFIG')),
90 90 ('', 'debug', None, _('enable debugging output')),
91 91 ('', 'debugger', None, _('start debugger')),
92 92 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
93 93 _('ENCODE')),
94 94 ('', 'encodingmode', encoding.encodingmode,
95 95 _('set the charset encoding mode'), _('MODE')),
96 96 ('', 'traceback', None, _('always print a traceback on exception')),
97 97 ('', 'time', None, _('time how long the command takes')),
98 98 ('', 'profile', None, _('print command execution profile')),
99 99 ('', 'version', None, _('output version information and exit')),
100 100 ('h', 'help', None, _('display help and exit')),
101 101 ('', 'hidden', False, _('consider hidden changesets')),
102 102 ('', 'pager', 'auto',
103 103 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
104 104 ]
105 105
106 106 dryrunopts = [('n', 'dry-run', None,
107 107 _('do not perform actions, just print output'))]
108 108
109 109 remoteopts = [
110 110 ('e', 'ssh', '',
111 111 _('specify ssh command to use'), _('CMD')),
112 112 ('', 'remotecmd', '',
113 113 _('specify hg command to run on the remote side'), _('CMD')),
114 114 ('', 'insecure', None,
115 115 _('do not verify server certificate (ignoring web.cacerts config)')),
116 116 ]
117 117
118 118 walkopts = [
119 119 ('I', 'include', [],
120 120 _('include names matching the given patterns'), _('PATTERN')),
121 121 ('X', 'exclude', [],
122 122 _('exclude names matching the given patterns'), _('PATTERN')),
123 123 ]
124 124
125 125 commitopts = [
126 126 ('m', 'message', '',
127 127 _('use text as commit message'), _('TEXT')),
128 128 ('l', 'logfile', '',
129 129 _('read commit message from file'), _('FILE')),
130 130 ]
131 131
132 132 commitopts2 = [
133 133 ('d', 'date', '',
134 134 _('record the specified date as commit date'), _('DATE')),
135 135 ('u', 'user', '',
136 136 _('record the specified user as committer'), _('USER')),
137 137 ]
138 138
139 139 # hidden for now
140 140 formatteropts = [
141 141 ('T', 'template', '',
142 142 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
143 143 ]
144 144
145 145 templateopts = [
146 146 ('', 'style', '',
147 147 _('display using template map file (DEPRECATED)'), _('STYLE')),
148 148 ('T', 'template', '',
149 149 _('display with template'), _('TEMPLATE')),
150 150 ]
151 151
152 152 logopts = [
153 153 ('p', 'patch', None, _('show patch')),
154 154 ('g', 'git', None, _('use git extended diff format')),
155 155 ('l', 'limit', '',
156 156 _('limit number of changes displayed'), _('NUM')),
157 157 ('M', 'no-merges', None, _('do not show merges')),
158 158 ('', 'stat', None, _('output diffstat-style summary of changes')),
159 159 ('G', 'graph', None, _("show the revision DAG")),
160 160 ] + templateopts
161 161
162 162 diffopts = [
163 163 ('a', 'text', None, _('treat all files as text')),
164 164 ('g', 'git', None, _('use git extended diff format')),
165 165 ('', 'nodates', None, _('omit dates from diff headers'))
166 166 ]
167 167
168 168 diffwsopts = [
169 169 ('w', 'ignore-all-space', None,
170 170 _('ignore white space when comparing lines')),
171 171 ('b', 'ignore-space-change', None,
172 172 _('ignore changes in the amount of white space')),
173 173 ('B', 'ignore-blank-lines', None,
174 174 _('ignore changes whose lines are all blank')),
175 175 ]
176 176
177 177 diffopts2 = [
178 178 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
179 179 ('p', 'show-function', None, _('show which function each change is in')),
180 180 ('', 'reverse', None, _('produce a diff that undoes the changes')),
181 181 ] + diffwsopts + [
182 182 ('U', 'unified', '',
183 183 _('number of lines of context to show'), _('NUM')),
184 184 ('', 'stat', None, _('output diffstat-style summary of changes')),
185 185 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
186 186 ]
187 187
188 188 mergetoolopts = [
189 189 ('t', 'tool', '', _('specify merge tool')),
190 190 ]
191 191
192 192 similarityopts = [
193 193 ('s', 'similarity', '',
194 194 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
195 195 ]
196 196
197 197 subrepoopts = [
198 198 ('S', 'subrepos', None,
199 199 _('recurse into subrepositories'))
200 200 ]
201 201
202 202 debugrevlogopts = [
203 203 ('c', 'changelog', False, _('open changelog')),
204 204 ('m', 'manifest', False, _('open manifest')),
205 205 ('', 'dir', '', _('open directory manifest')),
206 206 ]
207 207
208 208 # Commands start here, listed alphabetically
209 209
210 210 @command('^add',
211 211 walkopts + subrepoopts + dryrunopts,
212 212 _('[OPTION]... [FILE]...'),
213 213 inferrepo=True)
214 214 def add(ui, repo, *pats, **opts):
215 215 """add the specified files on the next commit
216 216
217 217 Schedule files to be version controlled and added to the
218 218 repository.
219 219
220 220 The files will be added to the repository at the next commit. To
221 221 undo an add before that, see :hg:`forget`.
222 222
223 223 If no names are given, add all files to the repository (except
224 224 files matching ``.hgignore``).
225 225
226 226 .. container:: verbose
227 227
228 228 Examples:
229 229
230 230 - New (unknown) files are added
231 231 automatically by :hg:`add`::
232 232
233 233 $ ls
234 234 foo.c
235 235 $ hg status
236 236 ? foo.c
237 237 $ hg add
238 238 adding foo.c
239 239 $ hg status
240 240 A foo.c
241 241
242 242 - Specific files to be added can be specified::
243 243
244 244 $ ls
245 245 bar.c foo.c
246 246 $ hg status
247 247 ? bar.c
248 248 ? foo.c
249 249 $ hg add bar.c
250 250 $ hg status
251 251 A bar.c
252 252 ? foo.c
253 253
254 254 Returns 0 if all files are successfully added.
255 255 """
256 256
257 257 m = scmutil.match(repo[None], pats, opts)
258 258 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
259 259 return rejected and 1 or 0
260 260
261 261 @command('addremove',
262 262 similarityopts + subrepoopts + walkopts + dryrunopts,
263 263 _('[OPTION]... [FILE]...'),
264 264 inferrepo=True)
265 265 def addremove(ui, repo, *pats, **opts):
266 266 """add all new files, delete all missing files
267 267
268 268 Add all new files and remove all missing files from the
269 269 repository.
270 270
271 271 Unless names are given, new files are ignored if they match any of
272 272 the patterns in ``.hgignore``. As with add, these changes take
273 273 effect at the next commit.
274 274
275 275 Use the -s/--similarity option to detect renamed files. This
276 276 option takes a percentage between 0 (disabled) and 100 (files must
277 277 be identical) as its parameter. With a parameter greater than 0,
278 278 this compares every removed file with every added file and records
279 279 those similar enough as renames. Detecting renamed files this way
280 280 can be expensive. After using this option, :hg:`status -C` can be
281 281 used to check which files were identified as moved or renamed. If
282 282 not specified, -s/--similarity defaults to 100 and only renames of
283 283 identical files are detected.
284 284
285 285 .. container:: verbose
286 286
287 287 Examples:
288 288
289 289 - A number of files (bar.c and foo.c) are new,
290 290 while foobar.c has been removed (without using :hg:`remove`)
291 291 from the repository::
292 292
293 293 $ ls
294 294 bar.c foo.c
295 295 $ hg status
296 296 ! foobar.c
297 297 ? bar.c
298 298 ? foo.c
299 299 $ hg addremove
300 300 adding bar.c
301 301 adding foo.c
302 302 removing foobar.c
303 303 $ hg status
304 304 A bar.c
305 305 A foo.c
306 306 R foobar.c
307 307
308 308 - A file foobar.c was moved to foo.c without using :hg:`rename`.
309 309 Afterwards, it was edited slightly::
310 310
311 311 $ ls
312 312 foo.c
313 313 $ hg status
314 314 ! foobar.c
315 315 ? foo.c
316 316 $ hg addremove --similarity 90
317 317 removing foobar.c
318 318 adding foo.c
319 319 recording removal of foobar.c as rename to foo.c (94% similar)
320 320 $ hg status -C
321 321 A foo.c
322 322 foobar.c
323 323 R foobar.c
324 324
325 325 Returns 0 if all files are successfully added.
326 326 """
327 327 try:
328 328 sim = float(opts.get('similarity') or 100)
329 329 except ValueError:
330 330 raise error.Abort(_('similarity must be a number'))
331 331 if sim < 0 or sim > 100:
332 332 raise error.Abort(_('similarity must be between 0 and 100'))
333 333 matcher = scmutil.match(repo[None], pats, opts)
334 334 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
335 335
336 336 @command('^annotate|blame',
337 337 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
338 338 ('', 'follow', None,
339 339 _('follow copies/renames and list the filename (DEPRECATED)')),
340 340 ('', 'no-follow', None, _("don't follow copies and renames")),
341 341 ('a', 'text', None, _('treat all files as text')),
342 342 ('u', 'user', None, _('list the author (long with -v)')),
343 343 ('f', 'file', None, _('list the filename')),
344 344 ('d', 'date', None, _('list the date (short with -q)')),
345 345 ('n', 'number', None, _('list the revision number (default)')),
346 346 ('c', 'changeset', None, _('list the changeset')),
347 347 ('l', 'line-number', None, _('show line number at the first appearance'))
348 348 ] + diffwsopts + walkopts + formatteropts,
349 349 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
350 350 inferrepo=True)
351 351 def annotate(ui, repo, *pats, **opts):
352 352 """show changeset information by line for each file
353 353
354 354 List changes in files, showing the revision id responsible for
355 355 each line.
356 356
357 357 This command is useful for discovering when a change was made and
358 358 by whom.
359 359
360 360 If you include --file, --user, or --date, the revision number is
361 361 suppressed unless you also include --number.
362 362
363 363 Without the -a/--text option, annotate will avoid processing files
364 364 it detects as binary. With -a, annotate will annotate the file
365 365 anyway, although the results will probably be neither useful
366 366 nor desirable.
367 367
368 368 Returns 0 on success.
369 369 """
370 370 if not pats:
371 371 raise error.Abort(_('at least one filename or pattern is required'))
372 372
373 373 if opts.get('follow'):
374 374 # --follow is deprecated and now just an alias for -f/--file
375 375 # to mimic the behavior of Mercurial before version 1.5
376 376 opts['file'] = True
377 377
378 378 ctx = scmutil.revsingle(repo, opts.get('rev'))
379 379
380 380 fm = ui.formatter('annotate', opts)
381 381 if ui.quiet:
382 382 datefunc = util.shortdate
383 383 else:
384 384 datefunc = util.datestr
385 385 if ctx.rev() is None:
386 386 def hexfn(node):
387 387 if node is None:
388 388 return None
389 389 else:
390 390 return fm.hexfunc(node)
391 391 if opts.get('changeset'):
392 392 # omit "+" suffix which is appended to node hex
393 393 def formatrev(rev):
394 394 if rev is None:
395 395 return '%d' % ctx.p1().rev()
396 396 else:
397 397 return '%d' % rev
398 398 else:
399 399 def formatrev(rev):
400 400 if rev is None:
401 401 return '%d+' % ctx.p1().rev()
402 402 else:
403 403 return '%d ' % rev
404 404 def formathex(hex):
405 405 if hex is None:
406 406 return '%s+' % fm.hexfunc(ctx.p1().node())
407 407 else:
408 408 return '%s ' % hex
409 409 else:
410 410 hexfn = fm.hexfunc
411 411 formatrev = formathex = str
412 412
413 413 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
414 414 ('number', ' ', lambda x: x[0].rev(), formatrev),
415 415 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
416 416 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
417 417 ('file', ' ', lambda x: x[0].path(), str),
418 418 ('line_number', ':', lambda x: x[1], str),
419 419 ]
420 420 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
421 421
422 422 if (not opts.get('user') and not opts.get('changeset')
423 423 and not opts.get('date') and not opts.get('file')):
424 424 opts['number'] = True
425 425
426 426 linenumber = opts.get('line_number') is not None
427 427 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
428 428 raise error.Abort(_('at least one of -n/-c is required for -l'))
429 429
430 430 ui.pager('annotate')
431 431
432 432 if fm.isplain():
433 433 def makefunc(get, fmt):
434 434 return lambda x: fmt(get(x))
435 435 else:
436 436 def makefunc(get, fmt):
437 437 return get
438 438 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
439 439 if opts.get(op)]
440 440 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
441 441 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
442 442 if opts.get(op))
443 443
444 444 def bad(x, y):
445 445 raise error.Abort("%s: %s" % (x, y))
446 446
447 447 m = scmutil.match(ctx, pats, opts, badfn=bad)
448 448
449 449 follow = not opts.get('no_follow')
450 450 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
451 451 whitespace=True)
452 452 for abs in ctx.walk(m):
453 453 fctx = ctx[abs]
454 454 if not opts.get('text') and util.binary(fctx.data()):
455 455 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
456 456 continue
457 457
458 458 lines = fctx.annotate(follow=follow, linenumber=linenumber,
459 459 diffopts=diffopts)
460 460 if not lines:
461 461 continue
462 462 formats = []
463 463 pieces = []
464 464
465 465 for f, sep in funcmap:
466 466 l = [f(n) for n, dummy in lines]
467 467 if fm.isplain():
468 468 sizes = [encoding.colwidth(x) for x in l]
469 469 ml = max(sizes)
470 470 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
471 471 else:
472 472 formats.append(['%s' for x in l])
473 473 pieces.append(l)
474 474
475 475 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
476 476 fm.startitem()
477 477 fm.write(fields, "".join(f), *p)
478 478 fm.write('line', ": %s", l[1])
479 479
480 480 if not lines[-1][1].endswith('\n'):
481 481 fm.plain('\n')
482 482
483 483 fm.end()
484 484
485 485 @command('archive',
486 486 [('', 'no-decode', None, _('do not pass files through decoders')),
487 487 ('p', 'prefix', '', _('directory prefix for files in archive'),
488 488 _('PREFIX')),
489 489 ('r', 'rev', '', _('revision to distribute'), _('REV')),
490 490 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
491 491 ] + subrepoopts + walkopts,
492 492 _('[OPTION]... DEST'))
493 493 def archive(ui, repo, dest, **opts):
494 494 '''create an unversioned archive of a repository revision
495 495
496 496 By default, the revision used is the parent of the working
497 497 directory; use -r/--rev to specify a different revision.
498 498
499 499 The archive type is automatically detected based on file
500 500 extension (to override, use -t/--type).
501 501
502 502 .. container:: verbose
503 503
504 504 Examples:
505 505
506 506 - create a zip file containing the 1.0 release::
507 507
508 508 hg archive -r 1.0 project-1.0.zip
509 509
510 510 - create a tarball excluding .hg files::
511 511
512 512 hg archive project.tar.gz -X ".hg*"
513 513
514 514 Valid types are:
515 515
516 516 :``files``: a directory full of files (default)
517 517 :``tar``: tar archive, uncompressed
518 518 :``tbz2``: tar archive, compressed using bzip2
519 519 :``tgz``: tar archive, compressed using gzip
520 520 :``uzip``: zip archive, uncompressed
521 521 :``zip``: zip archive, compressed using deflate
522 522
523 523 The exact name of the destination archive or directory is given
524 524 using a format string; see :hg:`help export` for details.
525 525
526 526 Each member added to an archive file has a directory prefix
527 527 prepended. Use -p/--prefix to specify a format string for the
528 528 prefix. The default is the basename of the archive, with suffixes
529 529 removed.
530 530
531 531 Returns 0 on success.
532 532 '''
533 533
534 534 ctx = scmutil.revsingle(repo, opts.get('rev'))
535 535 if not ctx:
536 536 raise error.Abort(_('no working directory: please specify a revision'))
537 537 node = ctx.node()
538 538 dest = cmdutil.makefilename(repo, dest, node)
539 539 if os.path.realpath(dest) == repo.root:
540 540 raise error.Abort(_('repository root cannot be destination'))
541 541
542 542 kind = opts.get('type') or archival.guesskind(dest) or 'files'
543 543 prefix = opts.get('prefix')
544 544
545 545 if dest == '-':
546 546 if kind == 'files':
547 547 raise error.Abort(_('cannot archive plain files to stdout'))
548 548 dest = cmdutil.makefileobj(repo, dest)
549 549 if not prefix:
550 550 prefix = os.path.basename(repo.root) + '-%h'
551 551
552 552 prefix = cmdutil.makefilename(repo, prefix, node)
553 553 matchfn = scmutil.match(ctx, [], opts)
554 554 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
555 555 matchfn, prefix, subrepos=opts.get('subrepos'))
556 556
557 557 @command('backout',
558 558 [('', 'merge', None, _('merge with old dirstate parent after backout')),
559 559 ('', 'commit', None,
560 560 _('commit if no conflicts were encountered (DEPRECATED)')),
561 561 ('', 'no-commit', None, _('do not commit')),
562 562 ('', 'parent', '',
563 563 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
564 564 ('r', 'rev', '', _('revision to backout'), _('REV')),
565 565 ('e', 'edit', False, _('invoke editor on commit messages')),
566 566 ] + mergetoolopts + walkopts + commitopts + commitopts2,
567 567 _('[OPTION]... [-r] REV'))
568 568 def backout(ui, repo, node=None, rev=None, **opts):
569 569 '''reverse effect of earlier changeset
570 570
571 571 Prepare a new changeset with the effect of REV undone in the
572 572 current working directory. If no conflicts were encountered,
573 573 it will be committed immediately.
574 574
575 575 If REV is the parent of the working directory, then this new changeset
576 576 is committed automatically (unless --no-commit is specified).
577 577
578 578 .. note::
579 579
580 580 :hg:`backout` cannot be used to fix either an unwanted or
581 581 incorrect merge.
582 582
583 583 .. container:: verbose
584 584
585 585 Examples:
586 586
587 587 - Reverse the effect of the parent of the working directory.
588 588 This backout will be committed immediately::
589 589
590 590 hg backout -r .
591 591
592 592 - Reverse the effect of previous bad revision 23::
593 593
594 594 hg backout -r 23
595 595
596 596 - Reverse the effect of previous bad revision 23 and
597 597 leave changes uncommitted::
598 598
599 599 hg backout -r 23 --no-commit
600 600 hg commit -m "Backout revision 23"
601 601
602 602 By default, the pending changeset will have one parent,
603 603 maintaining a linear history. With --merge, the pending
604 604 changeset will instead have two parents: the old parent of the
605 605 working directory and a new child of REV that simply undoes REV.
606 606
607 607 Before version 1.7, the behavior without --merge was equivalent
608 608 to specifying --merge followed by :hg:`update --clean .` to
609 609 cancel the merge and leave the child of REV as a head to be
610 610 merged separately.
611 611
612 612 See :hg:`help dates` for a list of formats valid for -d/--date.
613 613
614 614 See :hg:`help revert` for a way to restore files to the state
615 615 of another revision.
616 616
617 617 Returns 0 on success, 1 if nothing to backout or there are unresolved
618 618 files.
619 619 '''
620 620 wlock = lock = None
621 621 try:
622 622 wlock = repo.wlock()
623 623 lock = repo.lock()
624 624 return _dobackout(ui, repo, node, rev, **opts)
625 625 finally:
626 626 release(lock, wlock)
627 627
628 628 def _dobackout(ui, repo, node=None, rev=None, **opts):
629 629 if opts.get('commit') and opts.get('no_commit'):
630 630 raise error.Abort(_("cannot use --commit with --no-commit"))
631 631 if opts.get('merge') and opts.get('no_commit'):
632 632 raise error.Abort(_("cannot use --merge with --no-commit"))
633 633
634 634 if rev and node:
635 635 raise error.Abort(_("please specify just one revision"))
636 636
637 637 if not rev:
638 638 rev = node
639 639
640 640 if not rev:
641 641 raise error.Abort(_("please specify a revision to backout"))
642 642
643 643 date = opts.get('date')
644 644 if date:
645 645 opts['date'] = util.parsedate(date)
646 646
647 647 cmdutil.checkunfinished(repo)
648 648 cmdutil.bailifchanged(repo)
649 649 node = scmutil.revsingle(repo, rev).node()
650 650
651 651 op1, op2 = repo.dirstate.parents()
652 652 if not repo.changelog.isancestor(node, op1):
653 653 raise error.Abort(_('cannot backout change that is not an ancestor'))
654 654
655 655 p1, p2 = repo.changelog.parents(node)
656 656 if p1 == nullid:
657 657 raise error.Abort(_('cannot backout a change with no parents'))
658 658 if p2 != nullid:
659 659 if not opts.get('parent'):
660 660 raise error.Abort(_('cannot backout a merge changeset'))
661 661 p = repo.lookup(opts['parent'])
662 662 if p not in (p1, p2):
663 663 raise error.Abort(_('%s is not a parent of %s') %
664 664 (short(p), short(node)))
665 665 parent = p
666 666 else:
667 667 if opts.get('parent'):
668 668 raise error.Abort(_('cannot use --parent on non-merge changeset'))
669 669 parent = p1
670 670
671 671 # the backout should appear on the same branch
672 672 branch = repo.dirstate.branch()
673 673 bheads = repo.branchheads(branch)
674 674 rctx = scmutil.revsingle(repo, hex(parent))
675 675 if not opts.get('merge') and op1 != node:
676 676 dsguard = dirstateguard.dirstateguard(repo, 'backout')
677 677 try:
678 678 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
679 679 'backout')
680 680 stats = mergemod.update(repo, parent, True, True, node, False)
681 681 repo.setparents(op1, op2)
682 682 dsguard.close()
683 683 hg._showstats(repo, stats)
684 684 if stats[3]:
685 685 repo.ui.status(_("use 'hg resolve' to retry unresolved "
686 686 "file merges\n"))
687 687 return 1
688 688 finally:
689 689 ui.setconfig('ui', 'forcemerge', '', '')
690 690 lockmod.release(dsguard)
691 691 else:
692 692 hg.clean(repo, node, show_stats=False)
693 693 repo.dirstate.setbranch(branch)
694 694 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
695 695
696 696 if opts.get('no_commit'):
697 697 msg = _("changeset %s backed out, "
698 698 "don't forget to commit.\n")
699 699 ui.status(msg % short(node))
700 700 return 0
701 701
702 702 def commitfunc(ui, repo, message, match, opts):
703 703 editform = 'backout'
704 704 e = cmdutil.getcommiteditor(editform=editform, **opts)
705 705 if not message:
706 706 # we don't translate commit messages
707 707 message = "Backed out changeset %s" % short(node)
708 708 e = cmdutil.getcommiteditor(edit=True, editform=editform)
709 709 return repo.commit(message, opts.get('user'), opts.get('date'),
710 710 match, editor=e)
711 711 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
712 712 if not newnode:
713 713 ui.status(_("nothing changed\n"))
714 714 return 1
715 715 cmdutil.commitstatus(repo, newnode, branch, bheads)
716 716
717 717 def nice(node):
718 718 return '%d:%s' % (repo.changelog.rev(node), short(node))
719 719 ui.status(_('changeset %s backs out changeset %s\n') %
720 720 (nice(repo.changelog.tip()), nice(node)))
721 721 if opts.get('merge') and op1 != node:
722 722 hg.clean(repo, op1, show_stats=False)
723 723 ui.status(_('merging with changeset %s\n')
724 724 % nice(repo.changelog.tip()))
725 725 try:
726 726 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
727 727 'backout')
728 728 return hg.merge(repo, hex(repo.changelog.tip()))
729 729 finally:
730 730 ui.setconfig('ui', 'forcemerge', '', '')
731 731 return 0
732 732
733 733 @command('bisect',
734 734 [('r', 'reset', False, _('reset bisect state')),
735 735 ('g', 'good', False, _('mark changeset good')),
736 736 ('b', 'bad', False, _('mark changeset bad')),
737 737 ('s', 'skip', False, _('skip testing changeset')),
738 738 ('e', 'extend', False, _('extend the bisect range')),
739 739 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
740 740 ('U', 'noupdate', False, _('do not update to target'))],
741 741 _("[-gbsr] [-U] [-c CMD] [REV]"))
742 742 def bisect(ui, repo, rev=None, extra=None, command=None,
743 743 reset=None, good=None, bad=None, skip=None, extend=None,
744 744 noupdate=None):
745 745 """subdivision search of changesets
746 746
747 747 This command helps to find changesets which introduce problems. To
748 748 use, mark the earliest changeset you know exhibits the problem as
749 749 bad, then mark the latest changeset which is free from the problem
750 750 as good. Bisect will update your working directory to a revision
751 751 for testing (unless the -U/--noupdate option is specified). Once
752 752 you have performed tests, mark the working directory as good or
753 753 bad, and bisect will either update to another candidate changeset
754 754 or announce that it has found the bad revision.
755 755
756 756 As a shortcut, you can also use the revision argument to mark a
757 757 revision as good or bad without checking it out first.
758 758
759 759 If you supply a command, it will be used for automatic bisection.
760 760 The environment variable HG_NODE will contain the ID of the
761 761 changeset being tested. The exit status of the command will be
762 762 used to mark revisions as good or bad: status 0 means good, 125
763 763 means to skip the revision, 127 (command not found) will abort the
764 764 bisection, and any other non-zero exit status means the revision
765 765 is bad.
766 766
767 767 .. container:: verbose
768 768
769 769 Some examples:
770 770
771 771 - start a bisection with known bad revision 34, and good revision 12::
772 772
773 773 hg bisect --bad 34
774 774 hg bisect --good 12
775 775
776 776 - advance the current bisection by marking current revision as good or
777 777 bad::
778 778
779 779 hg bisect --good
780 780 hg bisect --bad
781 781
782 782 - mark the current revision, or a known revision, to be skipped (e.g. if
783 783 that revision is not usable because of another issue)::
784 784
785 785 hg bisect --skip
786 786 hg bisect --skip 23
787 787
788 788 - skip all revisions that do not touch directories ``foo`` or ``bar``::
789 789
790 790 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
791 791
792 792 - forget the current bisection::
793 793
794 794 hg bisect --reset
795 795
796 796 - use 'make && make tests' to automatically find the first broken
797 797 revision::
798 798
799 799 hg bisect --reset
800 800 hg bisect --bad 34
801 801 hg bisect --good 12
802 802 hg bisect --command "make && make tests"
803 803
804 804 - see all changesets whose states are already known in the current
805 805 bisection::
806 806
807 807 hg log -r "bisect(pruned)"
808 808
809 809 - see the changeset currently being bisected (especially useful
810 810 if running with -U/--noupdate)::
811 811
812 812 hg log -r "bisect(current)"
813 813
814 814 - see all changesets that took part in the current bisection::
815 815
816 816 hg log -r "bisect(range)"
817 817
818 818 - you can even get a nice graph::
819 819
820 820 hg log --graph -r "bisect(range)"
821 821
822 822 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
823 823
824 824 Returns 0 on success.
825 825 """
826 826 # backward compatibility
827 827 if rev in "good bad reset init".split():
828 828 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
829 829 cmd, rev, extra = rev, extra, None
830 830 if cmd == "good":
831 831 good = True
832 832 elif cmd == "bad":
833 833 bad = True
834 834 else:
835 835 reset = True
836 836 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
837 837 raise error.Abort(_('incompatible arguments'))
838 838
839 839 cmdutil.checkunfinished(repo)
840 840
841 841 if reset:
842 842 hbisect.resetstate(repo)
843 843 return
844 844
845 845 state = hbisect.load_state(repo)
846 846
847 847 # update state
848 848 if good or bad or skip:
849 849 if rev:
850 850 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
851 851 else:
852 852 nodes = [repo.lookup('.')]
853 853 if good:
854 854 state['good'] += nodes
855 855 elif bad:
856 856 state['bad'] += nodes
857 857 elif skip:
858 858 state['skip'] += nodes
859 859 hbisect.save_state(repo, state)
860 860 if not (state['good'] and state['bad']):
861 861 return
862 862
863 863 def mayupdate(repo, node, show_stats=True):
864 864 """common used update sequence"""
865 865 if noupdate:
866 866 return
867 867 cmdutil.bailifchanged(repo)
868 868 return hg.clean(repo, node, show_stats=show_stats)
869 869
870 870 displayer = cmdutil.show_changeset(ui, repo, {})
871 871
872 872 if command:
873 873 changesets = 1
874 874 if noupdate:
875 875 try:
876 876 node = state['current'][0]
877 877 except LookupError:
878 878 raise error.Abort(_('current bisect revision is unknown - '
879 879 'start a new bisect to fix'))
880 880 else:
881 881 node, p2 = repo.dirstate.parents()
882 882 if p2 != nullid:
883 883 raise error.Abort(_('current bisect revision is a merge'))
884 884 if rev:
885 885 node = repo[scmutil.revsingle(repo, rev, node)].node()
886 886 try:
887 887 while changesets:
888 888 # update state
889 889 state['current'] = [node]
890 890 hbisect.save_state(repo, state)
891 891 status = ui.system(command, environ={'HG_NODE': hex(node)},
892 892 blockedtag='bisect_check')
893 893 if status == 125:
894 894 transition = "skip"
895 895 elif status == 0:
896 896 transition = "good"
897 897 # status < 0 means process was killed
898 898 elif status == 127:
899 899 raise error.Abort(_("failed to execute %s") % command)
900 900 elif status < 0:
901 901 raise error.Abort(_("%s killed") % command)
902 902 else:
903 903 transition = "bad"
904 904 state[transition].append(node)
905 905 ctx = repo[node]
906 906 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
907 907 hbisect.checkstate(state)
908 908 # bisect
909 909 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
910 910 # update to next check
911 911 node = nodes[0]
912 912 mayupdate(repo, node, show_stats=False)
913 913 finally:
914 914 state['current'] = [node]
915 915 hbisect.save_state(repo, state)
916 916 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
917 917 return
918 918
919 919 hbisect.checkstate(state)
920 920
921 921 # actually bisect
922 922 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
923 923 if extend:
924 924 if not changesets:
925 925 extendnode = hbisect.extendrange(repo, state, nodes, good)
926 926 if extendnode is not None:
927 927 ui.write(_("Extending search to changeset %d:%s\n")
928 928 % (extendnode.rev(), extendnode))
929 929 state['current'] = [extendnode.node()]
930 930 hbisect.save_state(repo, state)
931 931 return mayupdate(repo, extendnode.node())
932 932 raise error.Abort(_("nothing to extend"))
933 933
934 934 if changesets == 0:
935 935 hbisect.printresult(ui, repo, state, displayer, nodes, good)
936 936 else:
937 937 assert len(nodes) == 1 # only a single node can be tested next
938 938 node = nodes[0]
939 939 # compute the approximate number of remaining tests
940 940 tests, size = 0, 2
941 941 while size <= changesets:
942 942 tests, size = tests + 1, size * 2
943 943 rev = repo.changelog.rev(node)
944 944 ui.write(_("Testing changeset %d:%s "
945 945 "(%d changesets remaining, ~%d tests)\n")
946 946 % (rev, short(node), changesets, tests))
947 947 state['current'] = [node]
948 948 hbisect.save_state(repo, state)
949 949 return mayupdate(repo, node)
950 950
951 951 @command('bookmarks|bookmark',
952 952 [('f', 'force', False, _('force')),
953 953 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
954 954 ('d', 'delete', False, _('delete a given bookmark')),
955 955 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
956 956 ('i', 'inactive', False, _('mark a bookmark inactive')),
957 957 ] + formatteropts,
958 958 _('hg bookmarks [OPTIONS]... [NAME]...'))
959 959 def bookmark(ui, repo, *names, **opts):
960 960 '''create a new bookmark or list existing bookmarks
961 961
962 962 Bookmarks are labels on changesets to help track lines of development.
963 963 Bookmarks are unversioned and can be moved, renamed and deleted.
964 964 Deleting or moving a bookmark has no effect on the associated changesets.
965 965
966 966 Creating or updating to a bookmark causes it to be marked as 'active'.
967 967 The active bookmark is indicated with a '*'.
968 968 When a commit is made, the active bookmark will advance to the new commit.
969 969 A plain :hg:`update` will also advance an active bookmark, if possible.
970 970 Updating away from a bookmark will cause it to be deactivated.
971 971
972 972 Bookmarks can be pushed and pulled between repositories (see
973 973 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
974 974 diverged, a new 'divergent bookmark' of the form 'name@path' will
975 975 be created. Using :hg:`merge` will resolve the divergence.
976 976
977 977 A bookmark named '@' has the special property that :hg:`clone` will
978 978 check it out by default if it exists.
979 979
980 980 .. container:: verbose
981 981
982 982 Examples:
983 983
984 984 - create an active bookmark for a new line of development::
985 985
986 986 hg book new-feature
987 987
988 988 - create an inactive bookmark as a place marker::
989 989
990 990 hg book -i reviewed
991 991
992 992 - create an inactive bookmark on another changeset::
993 993
994 994 hg book -r .^ tested
995 995
996 996 - rename bookmark turkey to dinner::
997 997
998 998 hg book -m turkey dinner
999 999
1000 1000 - move the '@' bookmark from another branch::
1001 1001
1002 1002 hg book -f @
1003 1003 '''
1004 1004 force = opts.get('force')
1005 1005 rev = opts.get('rev')
1006 1006 delete = opts.get('delete')
1007 1007 rename = opts.get('rename')
1008 1008 inactive = opts.get('inactive')
1009 1009
1010 1010 def checkformat(mark):
1011 1011 mark = mark.strip()
1012 1012 if not mark:
1013 1013 raise error.Abort(_("bookmark names cannot consist entirely of "
1014 1014 "whitespace"))
1015 1015 scmutil.checknewlabel(repo, mark, 'bookmark')
1016 1016 return mark
1017 1017
1018 1018 def checkconflict(repo, mark, cur, force=False, target=None):
1019 1019 if mark in marks and not force:
1020 1020 if target:
1021 1021 if marks[mark] == target and target == cur:
1022 1022 # re-activating a bookmark
1023 1023 return
1024 1024 anc = repo.changelog.ancestors([repo[target].rev()])
1025 1025 bmctx = repo[marks[mark]]
1026 1026 divs = [repo[b].node() for b in marks
1027 1027 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1028 1028
1029 1029 # allow resolving a single divergent bookmark even if moving
1030 1030 # the bookmark across branches when a revision is specified
1031 1031 # that contains a divergent bookmark
1032 1032 if bmctx.rev() not in anc and target in divs:
1033 1033 bookmarks.deletedivergent(repo, [target], mark)
1034 1034 return
1035 1035
1036 1036 deletefrom = [b for b in divs
1037 1037 if repo[b].rev() in anc or b == target]
1038 1038 bookmarks.deletedivergent(repo, deletefrom, mark)
1039 1039 if bookmarks.validdest(repo, bmctx, repo[target]):
1040 1040 ui.status(_("moving bookmark '%s' forward from %s\n") %
1041 1041 (mark, short(bmctx.node())))
1042 1042 return
1043 1043 raise error.Abort(_("bookmark '%s' already exists "
1044 1044 "(use -f to force)") % mark)
1045 1045 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1046 1046 and not force):
1047 1047 raise error.Abort(
1048 1048 _("a bookmark cannot have the name of an existing branch"))
1049 1049
1050 1050 if delete and rename:
1051 1051 raise error.Abort(_("--delete and --rename are incompatible"))
1052 1052 if delete and rev:
1053 1053 raise error.Abort(_("--rev is incompatible with --delete"))
1054 1054 if rename and rev:
1055 1055 raise error.Abort(_("--rev is incompatible with --rename"))
1056 1056 if not names and (delete or rev):
1057 1057 raise error.Abort(_("bookmark name required"))
1058 1058
1059 1059 if delete or rename or names or inactive:
1060 1060 wlock = lock = tr = None
1061 1061 try:
1062 1062 wlock = repo.wlock()
1063 1063 lock = repo.lock()
1064 1064 cur = repo.changectx('.').node()
1065 1065 marks = repo._bookmarks
1066 1066 if delete:
1067 1067 tr = repo.transaction('bookmark')
1068 1068 for mark in names:
1069 1069 if mark not in marks:
1070 1070 raise error.Abort(_("bookmark '%s' does not exist") %
1071 1071 mark)
1072 1072 if mark == repo._activebookmark:
1073 1073 bookmarks.deactivate(repo)
1074 1074 del marks[mark]
1075 1075
1076 1076 elif rename:
1077 1077 tr = repo.transaction('bookmark')
1078 1078 if not names:
1079 1079 raise error.Abort(_("new bookmark name required"))
1080 1080 elif len(names) > 1:
1081 1081 raise error.Abort(_("only one new bookmark name allowed"))
1082 1082 mark = checkformat(names[0])
1083 1083 if rename not in marks:
1084 1084 raise error.Abort(_("bookmark '%s' does not exist")
1085 1085 % rename)
1086 1086 checkconflict(repo, mark, cur, force)
1087 1087 marks[mark] = marks[rename]
1088 1088 if repo._activebookmark == rename and not inactive:
1089 1089 bookmarks.activate(repo, mark)
1090 1090 del marks[rename]
1091 1091 elif names:
1092 1092 tr = repo.transaction('bookmark')
1093 1093 newact = None
1094 1094 for mark in names:
1095 1095 mark = checkformat(mark)
1096 1096 if newact is None:
1097 1097 newact = mark
1098 1098 if inactive and mark == repo._activebookmark:
1099 1099 bookmarks.deactivate(repo)
1100 1100 return
1101 1101 tgt = cur
1102 1102 if rev:
1103 1103 tgt = scmutil.revsingle(repo, rev).node()
1104 1104 checkconflict(repo, mark, cur, force, tgt)
1105 1105 marks[mark] = tgt
1106 1106 if not inactive and cur == marks[newact] and not rev:
1107 1107 bookmarks.activate(repo, newact)
1108 1108 elif cur != tgt and newact == repo._activebookmark:
1109 1109 bookmarks.deactivate(repo)
1110 1110 elif inactive:
1111 1111 if len(marks) == 0:
1112 1112 ui.status(_("no bookmarks set\n"))
1113 1113 elif not repo._activebookmark:
1114 1114 ui.status(_("no active bookmark\n"))
1115 1115 else:
1116 1116 bookmarks.deactivate(repo)
1117 1117 if tr is not None:
1118 1118 marks.recordchange(tr)
1119 1119 tr.close()
1120 1120 finally:
1121 1121 lockmod.release(tr, lock, wlock)
1122 1122 else: # show bookmarks
1123 1123 fm = ui.formatter('bookmarks', opts)
1124 1124 hexfn = fm.hexfunc
1125 1125 marks = repo._bookmarks
1126 1126 if len(marks) == 0 and fm.isplain():
1127 1127 ui.status(_("no bookmarks set\n"))
1128 1128 for bmark, n in sorted(marks.iteritems()):
1129 1129 active = repo._activebookmark
1130 1130 if bmark == active:
1131 1131 prefix, label = '*', activebookmarklabel
1132 1132 else:
1133 1133 prefix, label = ' ', ''
1134 1134
1135 1135 fm.startitem()
1136 1136 if not ui.quiet:
1137 1137 fm.plain(' %s ' % prefix, label=label)
1138 1138 fm.write('bookmark', '%s', bmark, label=label)
1139 1139 pad = " " * (25 - encoding.colwidth(bmark))
1140 1140 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1141 1141 repo.changelog.rev(n), hexfn(n), label=label)
1142 1142 fm.data(active=(bmark == active))
1143 1143 fm.plain('\n')
1144 1144 fm.end()
1145 1145
1146 1146 @command('branch',
1147 1147 [('f', 'force', None,
1148 1148 _('set branch name even if it shadows an existing branch')),
1149 1149 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1150 1150 _('[-fC] [NAME]'))
1151 1151 def branch(ui, repo, label=None, **opts):
1152 1152 """set or show the current branch name
1153 1153
1154 1154 .. note::
1155 1155
1156 1156 Branch names are permanent and global. Use :hg:`bookmark` to create a
1157 1157 light-weight bookmark instead. See :hg:`help glossary` for more
1158 1158 information about named branches and bookmarks.
1159 1159
1160 1160 With no argument, show the current branch name. With one argument,
1161 1161 set the working directory branch name (the branch will not exist
1162 1162 in the repository until the next commit). Standard practice
1163 1163 recommends that primary development take place on the 'default'
1164 1164 branch.
1165 1165
1166 1166 Unless -f/--force is specified, branch will not let you set a
1167 1167 branch name that already exists.
1168 1168
1169 1169 Use -C/--clean to reset the working directory branch to that of
1170 1170 the parent of the working directory, negating a previous branch
1171 1171 change.
1172 1172
1173 1173 Use the command :hg:`update` to switch to an existing branch. Use
1174 1174 :hg:`commit --close-branch` to mark this branch head as closed.
1175 1175 When all heads of a branch are closed, the branch will be
1176 1176 considered closed.
1177 1177
1178 1178 Returns 0 on success.
1179 1179 """
1180 1180 if label:
1181 1181 label = label.strip()
1182 1182
1183 1183 if not opts.get('clean') and not label:
1184 1184 ui.write("%s\n" % repo.dirstate.branch())
1185 1185 return
1186 1186
1187 1187 with repo.wlock():
1188 1188 if opts.get('clean'):
1189 1189 label = repo[None].p1().branch()
1190 1190 repo.dirstate.setbranch(label)
1191 1191 ui.status(_('reset working directory to branch %s\n') % label)
1192 1192 elif label:
1193 1193 if not opts.get('force') and label in repo.branchmap():
1194 1194 if label not in [p.branch() for p in repo[None].parents()]:
1195 1195 raise error.Abort(_('a branch of the same name already'
1196 1196 ' exists'),
1197 1197 # i18n: "it" refers to an existing branch
1198 1198 hint=_("use 'hg update' to switch to it"))
1199 1199 scmutil.checknewlabel(repo, label, 'branch')
1200 1200 repo.dirstate.setbranch(label)
1201 1201 ui.status(_('marked working directory as branch %s\n') % label)
1202 1202
1203 1203 # find any open named branches aside from default
1204 1204 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1205 1205 if n != "default" and not c]
1206 1206 if not others:
1207 1207 ui.status(_('(branches are permanent and global, '
1208 1208 'did you want a bookmark?)\n'))
1209 1209
1210 1210 @command('branches',
1211 1211 [('a', 'active', False,
1212 1212 _('show only branches that have unmerged heads (DEPRECATED)')),
1213 1213 ('c', 'closed', False, _('show normal and closed branches')),
1214 1214 ] + formatteropts,
1215 1215 _('[-c]'))
1216 1216 def branches(ui, repo, active=False, closed=False, **opts):
1217 1217 """list repository named branches
1218 1218
1219 1219 List the repository's named branches, indicating which ones are
1220 1220 inactive. If -c/--closed is specified, also list branches which have
1221 1221 been marked closed (see :hg:`commit --close-branch`).
1222 1222
1223 1223 Use the command :hg:`update` to switch to an existing branch.
1224 1224
1225 1225 Returns 0.
1226 1226 """
1227 1227
1228 1228 ui.pager('branches')
1229 1229 fm = ui.formatter('branches', opts)
1230 1230 hexfunc = fm.hexfunc
1231 1231
1232 1232 allheads = set(repo.heads())
1233 1233 branches = []
1234 1234 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1235 1235 isactive = not isclosed and bool(set(heads) & allheads)
1236 1236 branches.append((tag, repo[tip], isactive, not isclosed))
1237 1237 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1238 1238 reverse=True)
1239 1239
1240 1240 for tag, ctx, isactive, isopen in branches:
1241 1241 if active and not isactive:
1242 1242 continue
1243 1243 if isactive:
1244 1244 label = 'branches.active'
1245 1245 notice = ''
1246 1246 elif not isopen:
1247 1247 if not closed:
1248 1248 continue
1249 1249 label = 'branches.closed'
1250 1250 notice = _(' (closed)')
1251 1251 else:
1252 1252 label = 'branches.inactive'
1253 1253 notice = _(' (inactive)')
1254 1254 current = (tag == repo.dirstate.branch())
1255 1255 if current:
1256 1256 label = 'branches.current'
1257 1257
1258 1258 fm.startitem()
1259 1259 fm.write('branch', '%s', tag, label=label)
1260 1260 rev = ctx.rev()
1261 1261 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1262 1262 fmt = ' ' * padsize + ' %d:%s'
1263 1263 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1264 1264 label='log.changeset changeset.%s' % ctx.phasestr())
1265 1265 fm.context(ctx=ctx)
1266 1266 fm.data(active=isactive, closed=not isopen, current=current)
1267 1267 if not ui.quiet:
1268 1268 fm.plain(notice)
1269 1269 fm.plain('\n')
1270 1270 fm.end()
1271 1271
1272 1272 @command('bundle',
1273 1273 [('f', 'force', None, _('run even when the destination is unrelated')),
1274 1274 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1275 1275 _('REV')),
1276 1276 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1277 1277 _('BRANCH')),
1278 1278 ('', 'base', [],
1279 1279 _('a base changeset assumed to be available at the destination'),
1280 1280 _('REV')),
1281 1281 ('a', 'all', None, _('bundle all changesets in the repository')),
1282 1282 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1283 1283 ] + remoteopts,
1284 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1284 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1285 1285 def bundle(ui, repo, fname, dest=None, **opts):
1286 """create a changegroup file
1287
1288 Generate a changegroup file collecting changesets to be added
1289 to a repository.
1286 """create a bundle file
1287
1288 Generate a bundle file containing data to be added to a repository.
1290 1289
1291 1290 To create a bundle containing all changesets, use -a/--all
1292 1291 (or --base null). Otherwise, hg assumes the destination will have
1293 1292 all the nodes you specify with --base parameters. Otherwise, hg
1294 1293 will assume the repository has all the nodes in destination, or
1295 1294 default-push/default if no destination is specified.
1296 1295
1297 You can change bundle format with the -t/--type option. You can
1298 specify a compression, a bundle version or both using a dash
1299 (comp-version). The available compression methods are: none, bzip2,
1300 and gzip (by default, bundles are compressed using bzip2). The
1301 available formats are: v1, v2 (default to most suitable).
1296 You can change bundle format with the -t/--type option. See
1297 :hg:`help bundlespec` for documentation on this format. By default,
1298 the most appropriate format is used and compression defaults to
1299 bzip2.
1302 1300
1303 1301 The bundle file can then be transferred using conventional means
1304 1302 and applied to another repository with the unbundle or pull
1305 1303 command. This is useful when direct push and pull are not
1306 1304 available or when exporting an entire repository is undesirable.
1307 1305
1308 1306 Applying bundles preserves all changeset contents including
1309 1307 permissions, copy/rename information, and revision history.
1310 1308
1311 1309 Returns 0 on success, 1 if no changes found.
1312 1310 """
1313 1311 revs = None
1314 1312 if 'rev' in opts:
1315 1313 revstrings = opts['rev']
1316 1314 revs = scmutil.revrange(repo, revstrings)
1317 1315 if revstrings and not revs:
1318 1316 raise error.Abort(_('no commits to bundle'))
1319 1317
1320 1318 bundletype = opts.get('type', 'bzip2').lower()
1321 1319 try:
1322 1320 bcompression, cgversion, params = exchange.parsebundlespec(
1323 1321 repo, bundletype, strict=False)
1324 1322 except error.UnsupportedBundleSpecification as e:
1325 1323 raise error.Abort(str(e),
1326 hint=_("see 'hg help bundle' for supported "
1324 hint=_("see 'hg help bundlespec' for supported "
1327 1325 "values for --type"))
1328 1326
1329 1327 # Packed bundles are a pseudo bundle format for now.
1330 1328 if cgversion == 's1':
1331 1329 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1332 1330 hint=_("use 'hg debugcreatestreamclonebundle'"))
1333 1331
1334 1332 if opts.get('all'):
1335 1333 if dest:
1336 1334 raise error.Abort(_("--all is incompatible with specifying "
1337 1335 "a destination"))
1338 1336 if opts.get('base'):
1339 1337 ui.warn(_("ignoring --base because --all was specified\n"))
1340 1338 base = ['null']
1341 1339 else:
1342 1340 base = scmutil.revrange(repo, opts.get('base'))
1343 1341 # TODO: get desired bundlecaps from command line.
1344 1342 bundlecaps = None
1345 1343 if cgversion not in changegroup.supportedoutgoingversions(repo):
1346 1344 raise error.Abort(_("repository does not support bundle version %s") %
1347 1345 cgversion)
1348 1346
1349 1347 if base:
1350 1348 if dest:
1351 1349 raise error.Abort(_("--base is incompatible with specifying "
1352 1350 "a destination"))
1353 1351 common = [repo.lookup(rev) for rev in base]
1354 1352 heads = revs and map(repo.lookup, revs) or None
1355 1353 outgoing = discovery.outgoing(repo, common, heads)
1356 1354 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1357 1355 bundlecaps=bundlecaps,
1358 1356 version=cgversion)
1359 1357 outgoing = None
1360 1358 else:
1361 1359 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1362 1360 dest, branches = hg.parseurl(dest, opts.get('branch'))
1363 1361 other = hg.peer(repo, opts, dest)
1364 1362 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1365 1363 heads = revs and map(repo.lookup, revs) or revs
1366 1364 outgoing = discovery.findcommonoutgoing(repo, other,
1367 1365 onlyheads=heads,
1368 1366 force=opts.get('force'),
1369 1367 portable=True)
1370 1368 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1371 1369 bundlecaps, version=cgversion)
1372 1370 if not cg:
1373 1371 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1374 1372 return 1
1375 1373
1376 1374 if cgversion == '01': #bundle1
1377 1375 if bcompression is None:
1378 1376 bcompression = 'UN'
1379 1377 bversion = 'HG10' + bcompression
1380 1378 bcompression = None
1381 1379 else:
1382 1380 assert cgversion == '02'
1383 1381 bversion = 'HG20'
1384 1382
1385 1383 # TODO compression options should be derived from bundlespec parsing.
1386 1384 # This is a temporary hack to allow adjusting bundle compression
1387 1385 # level without a) formalizing the bundlespec changes to declare it
1388 1386 # b) introducing a command flag.
1389 1387 compopts = {}
1390 1388 complevel = ui.configint('experimental', 'bundlecomplevel')
1391 1389 if complevel is not None:
1392 1390 compopts['level'] = complevel
1393 1391
1394 1392 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1395 1393 compopts=compopts)
1396 1394
1397 1395 @command('cat',
1398 1396 [('o', 'output', '',
1399 1397 _('print output to file with formatted name'), _('FORMAT')),
1400 1398 ('r', 'rev', '', _('print the given revision'), _('REV')),
1401 1399 ('', 'decode', None, _('apply any matching decode filter')),
1402 1400 ] + walkopts,
1403 1401 _('[OPTION]... FILE...'),
1404 1402 inferrepo=True)
1405 1403 def cat(ui, repo, file1, *pats, **opts):
1406 1404 """output the current or given revision of files
1407 1405
1408 1406 Print the specified files as they were at the given revision. If
1409 1407 no revision is given, the parent of the working directory is used.
1410 1408
1411 1409 Output may be to a file, in which case the name of the file is
1412 1410 given using a format string. The formatting rules as follows:
1413 1411
1414 1412 :``%%``: literal "%" character
1415 1413 :``%s``: basename of file being printed
1416 1414 :``%d``: dirname of file being printed, or '.' if in repository root
1417 1415 :``%p``: root-relative path name of file being printed
1418 1416 :``%H``: changeset hash (40 hexadecimal digits)
1419 1417 :``%R``: changeset revision number
1420 1418 :``%h``: short-form changeset hash (12 hexadecimal digits)
1421 1419 :``%r``: zero-padded changeset revision number
1422 1420 :``%b``: basename of the exporting repository
1423 1421
1424 1422 Returns 0 on success.
1425 1423 """
1426 1424 ctx = scmutil.revsingle(repo, opts.get('rev'))
1427 1425 m = scmutil.match(ctx, (file1,) + pats, opts)
1428 1426
1429 1427 ui.pager('cat')
1430 1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1431 1429
1432 1430 @command('^clone',
1433 1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1434 1432 'directory (only a repository)')),
1435 1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1436 1434 _('REV')),
1437 1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1438 1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1439 1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1440 1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1441 1439 ] + remoteopts,
1442 1440 _('[OPTION]... SOURCE [DEST]'),
1443 1441 norepo=True)
1444 1442 def clone(ui, source, dest=None, **opts):
1445 1443 """make a copy of an existing repository
1446 1444
1447 1445 Create a copy of an existing repository in a new directory.
1448 1446
1449 1447 If no destination directory name is specified, it defaults to the
1450 1448 basename of the source.
1451 1449
1452 1450 The location of the source is added to the new repository's
1453 1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1454 1452
1455 1453 Only local paths and ``ssh://`` URLs are supported as
1456 1454 destinations. For ``ssh://`` destinations, no working directory or
1457 1455 ``.hg/hgrc`` will be created on the remote side.
1458 1456
1459 1457 If the source repository has a bookmark called '@' set, that
1460 1458 revision will be checked out in the new repository by default.
1461 1459
1462 1460 To check out a particular version, use -u/--update, or
1463 1461 -U/--noupdate to create a clone with no working directory.
1464 1462
1465 1463 To pull only a subset of changesets, specify one or more revisions
1466 1464 identifiers with -r/--rev or branches with -b/--branch. The
1467 1465 resulting clone will contain only the specified changesets and
1468 1466 their ancestors. These options (or 'clone src#rev dest') imply
1469 1467 --pull, even for local source repositories.
1470 1468
1471 1469 .. note::
1472 1470
1473 1471 Specifying a tag will include the tagged changeset but not the
1474 1472 changeset containing the tag.
1475 1473
1476 1474 .. container:: verbose
1477 1475
1478 1476 For efficiency, hardlinks are used for cloning whenever the
1479 1477 source and destination are on the same filesystem (note this
1480 1478 applies only to the repository data, not to the working
1481 1479 directory). Some filesystems, such as AFS, implement hardlinking
1482 1480 incorrectly, but do not report errors. In these cases, use the
1483 1481 --pull option to avoid hardlinking.
1484 1482
1485 1483 In some cases, you can clone repositories and the working
1486 1484 directory using full hardlinks with ::
1487 1485
1488 1486 $ cp -al REPO REPOCLONE
1489 1487
1490 1488 This is the fastest way to clone, but it is not always safe. The
1491 1489 operation is not atomic (making sure REPO is not modified during
1492 1490 the operation is up to you) and you have to make sure your
1493 1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1494 1492 so). Also, this is not compatible with certain extensions that
1495 1493 place their metadata under the .hg directory, such as mq.
1496 1494
1497 1495 Mercurial will update the working directory to the first applicable
1498 1496 revision from this list:
1499 1497
1500 1498 a) null if -U or the source repository has no changesets
1501 1499 b) if -u . and the source repository is local, the first parent of
1502 1500 the source repository's working directory
1503 1501 c) the changeset specified with -u (if a branch name, this means the
1504 1502 latest head of that branch)
1505 1503 d) the changeset specified with -r
1506 1504 e) the tipmost head specified with -b
1507 1505 f) the tipmost head specified with the url#branch source syntax
1508 1506 g) the revision marked with the '@' bookmark, if present
1509 1507 h) the tipmost head of the default branch
1510 1508 i) tip
1511 1509
1512 1510 When cloning from servers that support it, Mercurial may fetch
1513 1511 pre-generated data from a server-advertised URL. When this is done,
1514 1512 hooks operating on incoming changesets and changegroups may fire twice,
1515 1513 once for the bundle fetched from the URL and another for any additional
1516 1514 data not fetched from this URL. In addition, if an error occurs, the
1517 1515 repository may be rolled back to a partial clone. This behavior may
1518 1516 change in future releases. See :hg:`help -e clonebundles` for more.
1519 1517
1520 1518 Examples:
1521 1519
1522 1520 - clone a remote repository to a new directory named hg/::
1523 1521
1524 1522 hg clone https://www.mercurial-scm.org/repo/hg/
1525 1523
1526 1524 - create a lightweight local clone::
1527 1525
1528 1526 hg clone project/ project-feature/
1529 1527
1530 1528 - clone from an absolute path on an ssh server (note double-slash)::
1531 1529
1532 1530 hg clone ssh://user@server//home/projects/alpha/
1533 1531
1534 1532 - do a high-speed clone over a LAN while checking out a
1535 1533 specified version::
1536 1534
1537 1535 hg clone --uncompressed http://server/repo -u 1.5
1538 1536
1539 1537 - create a repository without changesets after a particular revision::
1540 1538
1541 1539 hg clone -r 04e544 experimental/ good/
1542 1540
1543 1541 - clone (and track) a particular named branch::
1544 1542
1545 1543 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1546 1544
1547 1545 See :hg:`help urls` for details on specifying URLs.
1548 1546
1549 1547 Returns 0 on success.
1550 1548 """
1551 1549 if opts.get('noupdate') and opts.get('updaterev'):
1552 1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1553 1551
1554 1552 r = hg.clone(ui, opts, source, dest,
1555 1553 pull=opts.get('pull'),
1556 1554 stream=opts.get('uncompressed'),
1557 1555 rev=opts.get('rev'),
1558 1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1559 1557 branch=opts.get('branch'),
1560 1558 shareopts=opts.get('shareopts'))
1561 1559
1562 1560 return r is None
1563 1561
1564 1562 @command('^commit|ci',
1565 1563 [('A', 'addremove', None,
1566 1564 _('mark new/missing files as added/removed before committing')),
1567 1565 ('', 'close-branch', None,
1568 1566 _('mark a branch head as closed')),
1569 1567 ('', 'amend', None, _('amend the parent of the working directory')),
1570 1568 ('s', 'secret', None, _('use the secret phase for committing')),
1571 1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1572 1570 ('i', 'interactive', None, _('use interactive mode')),
1573 1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1574 1572 _('[OPTION]... [FILE]...'),
1575 1573 inferrepo=True)
1576 1574 def commit(ui, repo, *pats, **opts):
1577 1575 """commit the specified files or all outstanding changes
1578 1576
1579 1577 Commit changes to the given files into the repository. Unlike a
1580 1578 centralized SCM, this operation is a local operation. See
1581 1579 :hg:`push` for a way to actively distribute your changes.
1582 1580
1583 1581 If a list of files is omitted, all changes reported by :hg:`status`
1584 1582 will be committed.
1585 1583
1586 1584 If you are committing the result of a merge, do not provide any
1587 1585 filenames or -I/-X filters.
1588 1586
1589 1587 If no commit message is specified, Mercurial starts your
1590 1588 configured editor where you can enter a message. In case your
1591 1589 commit fails, you will find a backup of your message in
1592 1590 ``.hg/last-message.txt``.
1593 1591
1594 1592 The --close-branch flag can be used to mark the current branch
1595 1593 head closed. When all heads of a branch are closed, the branch
1596 1594 will be considered closed and no longer listed.
1597 1595
1598 1596 The --amend flag can be used to amend the parent of the
1599 1597 working directory with a new commit that contains the changes
1600 1598 in the parent in addition to those currently reported by :hg:`status`,
1601 1599 if there are any. The old commit is stored in a backup bundle in
1602 1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1603 1601 on how to restore it).
1604 1602
1605 1603 Message, user and date are taken from the amended commit unless
1606 1604 specified. When a message isn't specified on the command line,
1607 1605 the editor will open with the message of the amended commit.
1608 1606
1609 1607 It is not possible to amend public changesets (see :hg:`help phases`)
1610 1608 or changesets that have children.
1611 1609
1612 1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1613 1611
1614 1612 Returns 0 on success, 1 if nothing changed.
1615 1613
1616 1614 .. container:: verbose
1617 1615
1618 1616 Examples:
1619 1617
1620 1618 - commit all files ending in .py::
1621 1619
1622 1620 hg commit --include "set:**.py"
1623 1621
1624 1622 - commit all non-binary files::
1625 1623
1626 1624 hg commit --exclude "set:binary()"
1627 1625
1628 1626 - amend the current commit and set the date to now::
1629 1627
1630 1628 hg commit --amend --date now
1631 1629 """
1632 1630 wlock = lock = None
1633 1631 try:
1634 1632 wlock = repo.wlock()
1635 1633 lock = repo.lock()
1636 1634 return _docommit(ui, repo, *pats, **opts)
1637 1635 finally:
1638 1636 release(lock, wlock)
1639 1637
1640 1638 def _docommit(ui, repo, *pats, **opts):
1641 1639 opts = pycompat.byteskwargs(opts)
1642 1640 if opts.get('interactive'):
1643 1641 opts.pop('interactive')
1644 1642 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1645 1643 cmdutil.recordfilter, *pats,
1646 1644 **pycompat.strkwargs(opts))
1647 1645 # ret can be 0 (no changes to record) or the value returned by
1648 1646 # commit(), 1 if nothing changed or None on success.
1649 1647 return 1 if ret == 0 else ret
1650 1648
1651 1649 if opts.get('subrepos'):
1652 1650 if opts.get('amend'):
1653 1651 raise error.Abort(_('cannot amend with --subrepos'))
1654 1652 # Let --subrepos on the command line override config setting.
1655 1653 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1656 1654
1657 1655 cmdutil.checkunfinished(repo, commit=True)
1658 1656
1659 1657 branch = repo[None].branch()
1660 1658 bheads = repo.branchheads(branch)
1661 1659
1662 1660 extra = {}
1663 1661 if opts.get('close_branch'):
1664 1662 extra['close'] = 1
1665 1663
1666 1664 if not bheads:
1667 1665 raise error.Abort(_('can only close branch heads'))
1668 1666 elif opts.get('amend'):
1669 1667 if repo[None].parents()[0].p1().branch() != branch and \
1670 1668 repo[None].parents()[0].p2().branch() != branch:
1671 1669 raise error.Abort(_('can only close branch heads'))
1672 1670
1673 1671 if opts.get('amend'):
1674 1672 if ui.configbool('ui', 'commitsubrepos'):
1675 1673 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1676 1674
1677 1675 old = repo['.']
1678 1676 if not old.mutable():
1679 1677 raise error.Abort(_('cannot amend public changesets'))
1680 1678 if len(repo[None].parents()) > 1:
1681 1679 raise error.Abort(_('cannot amend while merging'))
1682 1680 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1683 1681 if not allowunstable and old.children():
1684 1682 raise error.Abort(_('cannot amend changeset with children'))
1685 1683
1686 1684 # Currently histedit gets confused if an amend happens while histedit
1687 1685 # is in progress. Since we have a checkunfinished command, we are
1688 1686 # temporarily honoring it.
1689 1687 #
1690 1688 # Note: eventually this guard will be removed. Please do not expect
1691 1689 # this behavior to remain.
1692 1690 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1693 1691 cmdutil.checkunfinished(repo)
1694 1692
1695 1693 # commitfunc is used only for temporary amend commit by cmdutil.amend
1696 1694 def commitfunc(ui, repo, message, match, opts):
1697 1695 return repo.commit(message,
1698 1696 opts.get('user') or old.user(),
1699 1697 opts.get('date') or old.date(),
1700 1698 match,
1701 1699 extra=extra)
1702 1700
1703 1701 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1704 1702 if node == old.node():
1705 1703 ui.status(_("nothing changed\n"))
1706 1704 return 1
1707 1705 else:
1708 1706 def commitfunc(ui, repo, message, match, opts):
1709 1707 overrides = {}
1710 1708 if opts.get('secret'):
1711 1709 overrides[('phases', 'new-commit')] = 'secret'
1712 1710
1713 1711 baseui = repo.baseui
1714 1712 with baseui.configoverride(overrides, 'commit'):
1715 1713 with ui.configoverride(overrides, 'commit'):
1716 1714 editform = cmdutil.mergeeditform(repo[None],
1717 1715 'commit.normal')
1718 1716 editor = cmdutil.getcommiteditor(
1719 1717 editform=editform, **pycompat.strkwargs(opts))
1720 1718 return repo.commit(message,
1721 1719 opts.get('user'),
1722 1720 opts.get('date'),
1723 1721 match,
1724 1722 editor=editor,
1725 1723 extra=extra)
1726 1724
1727 1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1728 1726
1729 1727 if not node:
1730 1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1731 1729 if stat[3]:
1732 1730 ui.status(_("nothing changed (%d missing files, see "
1733 1731 "'hg status')\n") % len(stat[3]))
1734 1732 else:
1735 1733 ui.status(_("nothing changed\n"))
1736 1734 return 1
1737 1735
1738 1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1739 1737
1740 1738 @command('config|showconfig|debugconfig',
1741 1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1742 1740 ('e', 'edit', None, _('edit user config')),
1743 1741 ('l', 'local', None, _('edit repository config')),
1744 1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1745 1743 _('[-u] [NAME]...'),
1746 1744 optionalrepo=True)
1747 1745 def config(ui, repo, *values, **opts):
1748 1746 """show combined config settings from all hgrc files
1749 1747
1750 1748 With no arguments, print names and values of all config items.
1751 1749
1752 1750 With one argument of the form section.name, print just the value
1753 1751 of that config item.
1754 1752
1755 1753 With multiple arguments, print names and values of all config
1756 1754 items with matching section names.
1757 1755
1758 1756 With --edit, start an editor on the user-level config file. With
1759 1757 --global, edit the system-wide config file. With --local, edit the
1760 1758 repository-level config file.
1761 1759
1762 1760 With --debug, the source (filename and line number) is printed
1763 1761 for each config item.
1764 1762
1765 1763 See :hg:`help config` for more information about config files.
1766 1764
1767 1765 Returns 0 on success, 1 if NAME does not exist.
1768 1766
1769 1767 """
1770 1768
1771 1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1772 1770 if opts.get('local') and opts.get('global'):
1773 1771 raise error.Abort(_("can't use --local and --global together"))
1774 1772
1775 1773 if opts.get('local'):
1776 1774 if not repo:
1777 1775 raise error.Abort(_("can't use --local outside a repository"))
1778 1776 paths = [repo.vfs.join('hgrc')]
1779 1777 elif opts.get('global'):
1780 1778 paths = rcutil.systemrcpath()
1781 1779 else:
1782 1780 paths = rcutil.userrcpath()
1783 1781
1784 1782 for f in paths:
1785 1783 if os.path.exists(f):
1786 1784 break
1787 1785 else:
1788 1786 if opts.get('global'):
1789 1787 samplehgrc = uimod.samplehgrcs['global']
1790 1788 elif opts.get('local'):
1791 1789 samplehgrc = uimod.samplehgrcs['local']
1792 1790 else:
1793 1791 samplehgrc = uimod.samplehgrcs['user']
1794 1792
1795 1793 f = paths[0]
1796 1794 fp = open(f, "w")
1797 1795 fp.write(samplehgrc)
1798 1796 fp.close()
1799 1797
1800 1798 editor = ui.geteditor()
1801 1799 ui.system("%s \"%s\"" % (editor, f),
1802 1800 onerr=error.Abort, errprefix=_("edit failed"),
1803 1801 blockedtag='config_edit')
1804 1802 return
1805 1803 ui.pager('config')
1806 1804 fm = ui.formatter('config', opts)
1807 1805 for t, f in rcutil.rccomponents():
1808 1806 if t == 'path':
1809 1807 ui.debug('read config from: %s\n' % f)
1810 1808 elif t == 'items':
1811 1809 for section, name, value, source in f:
1812 1810 ui.debug('set config by: %s\n' % source)
1813 1811 else:
1814 1812 raise error.ProgrammingError('unknown rctype: %s' % t)
1815 1813 untrusted = bool(opts.get('untrusted'))
1816 1814 if values:
1817 1815 sections = [v for v in values if '.' not in v]
1818 1816 items = [v for v in values if '.' in v]
1819 1817 if len(items) > 1 or items and sections:
1820 1818 raise error.Abort(_('only one config item permitted'))
1821 1819 matched = False
1822 1820 for section, name, value in ui.walkconfig(untrusted=untrusted):
1823 1821 source = ui.configsource(section, name, untrusted)
1824 1822 value = pycompat.bytestr(value)
1825 1823 if fm.isplain():
1826 1824 source = source or 'none'
1827 1825 value = value.replace('\n', '\\n')
1828 1826 entryname = section + '.' + name
1829 1827 if values:
1830 1828 for v in values:
1831 1829 if v == section:
1832 1830 fm.startitem()
1833 1831 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1834 1832 fm.write('name value', '%s=%s\n', entryname, value)
1835 1833 matched = True
1836 1834 elif v == entryname:
1837 1835 fm.startitem()
1838 1836 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1839 1837 fm.write('value', '%s\n', value)
1840 1838 fm.data(name=entryname)
1841 1839 matched = True
1842 1840 else:
1843 1841 fm.startitem()
1844 1842 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1845 1843 fm.write('name value', '%s=%s\n', entryname, value)
1846 1844 matched = True
1847 1845 fm.end()
1848 1846 if matched:
1849 1847 return 0
1850 1848 return 1
1851 1849
1852 1850 @command('copy|cp',
1853 1851 [('A', 'after', None, _('record a copy that has already occurred')),
1854 1852 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1855 1853 ] + walkopts + dryrunopts,
1856 1854 _('[OPTION]... [SOURCE]... DEST'))
1857 1855 def copy(ui, repo, *pats, **opts):
1858 1856 """mark files as copied for the next commit
1859 1857
1860 1858 Mark dest as having copies of source files. If dest is a
1861 1859 directory, copies are put in that directory. If dest is a file,
1862 1860 the source must be a single file.
1863 1861
1864 1862 By default, this command copies the contents of files as they
1865 1863 exist in the working directory. If invoked with -A/--after, the
1866 1864 operation is recorded, but no copying is performed.
1867 1865
1868 1866 This command takes effect with the next commit. To undo a copy
1869 1867 before that, see :hg:`revert`.
1870 1868
1871 1869 Returns 0 on success, 1 if errors are encountered.
1872 1870 """
1873 1871 with repo.wlock(False):
1874 1872 return cmdutil.copy(ui, repo, pats, opts)
1875 1873
1876 1874 @command('^diff',
1877 1875 [('r', 'rev', [], _('revision'), _('REV')),
1878 1876 ('c', 'change', '', _('change made by revision'), _('REV'))
1879 1877 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1880 1878 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1881 1879 inferrepo=True)
1882 1880 def diff(ui, repo, *pats, **opts):
1883 1881 """diff repository (or selected files)
1884 1882
1885 1883 Show differences between revisions for the specified files.
1886 1884
1887 1885 Differences between files are shown using the unified diff format.
1888 1886
1889 1887 .. note::
1890 1888
1891 1889 :hg:`diff` may generate unexpected results for merges, as it will
1892 1890 default to comparing against the working directory's first
1893 1891 parent changeset if no revisions are specified.
1894 1892
1895 1893 When two revision arguments are given, then changes are shown
1896 1894 between those revisions. If only one revision is specified then
1897 1895 that revision is compared to the working directory, and, when no
1898 1896 revisions are specified, the working directory files are compared
1899 1897 to its first parent.
1900 1898
1901 1899 Alternatively you can specify -c/--change with a revision to see
1902 1900 the changes in that changeset relative to its first parent.
1903 1901
1904 1902 Without the -a/--text option, diff will avoid generating diffs of
1905 1903 files it detects as binary. With -a, diff will generate a diff
1906 1904 anyway, probably with undesirable results.
1907 1905
1908 1906 Use the -g/--git option to generate diffs in the git extended diff
1909 1907 format. For more information, read :hg:`help diffs`.
1910 1908
1911 1909 .. container:: verbose
1912 1910
1913 1911 Examples:
1914 1912
1915 1913 - compare a file in the current working directory to its parent::
1916 1914
1917 1915 hg diff foo.c
1918 1916
1919 1917 - compare two historical versions of a directory, with rename info::
1920 1918
1921 1919 hg diff --git -r 1.0:1.2 lib/
1922 1920
1923 1921 - get change stats relative to the last change on some date::
1924 1922
1925 1923 hg diff --stat -r "date('may 2')"
1926 1924
1927 1925 - diff all newly-added files that contain a keyword::
1928 1926
1929 1927 hg diff "set:added() and grep(GNU)"
1930 1928
1931 1929 - compare a revision and its parents::
1932 1930
1933 1931 hg diff -c 9353 # compare against first parent
1934 1932 hg diff -r 9353^:9353 # same using revset syntax
1935 1933 hg diff -r 9353^2:9353 # compare against the second parent
1936 1934
1937 1935 Returns 0 on success.
1938 1936 """
1939 1937
1940 1938 revs = opts.get('rev')
1941 1939 change = opts.get('change')
1942 1940 stat = opts.get('stat')
1943 1941 reverse = opts.get('reverse')
1944 1942
1945 1943 if revs and change:
1946 1944 msg = _('cannot specify --rev and --change at the same time')
1947 1945 raise error.Abort(msg)
1948 1946 elif change:
1949 1947 node2 = scmutil.revsingle(repo, change, None).node()
1950 1948 node1 = repo[node2].p1().node()
1951 1949 else:
1952 1950 node1, node2 = scmutil.revpair(repo, revs)
1953 1951
1954 1952 if reverse:
1955 1953 node1, node2 = node2, node1
1956 1954
1957 1955 diffopts = patch.diffallopts(ui, opts)
1958 1956 m = scmutil.match(repo[node2], pats, opts)
1959 1957 ui.pager('diff')
1960 1958 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1961 1959 listsubrepos=opts.get('subrepos'),
1962 1960 root=opts.get('root'))
1963 1961
1964 1962 @command('^export',
1965 1963 [('o', 'output', '',
1966 1964 _('print output to file with formatted name'), _('FORMAT')),
1967 1965 ('', 'switch-parent', None, _('diff against the second parent')),
1968 1966 ('r', 'rev', [], _('revisions to export'), _('REV')),
1969 1967 ] + diffopts,
1970 1968 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1971 1969 def export(ui, repo, *changesets, **opts):
1972 1970 """dump the header and diffs for one or more changesets
1973 1971
1974 1972 Print the changeset header and diffs for one or more revisions.
1975 1973 If no revision is given, the parent of the working directory is used.
1976 1974
1977 1975 The information shown in the changeset header is: author, date,
1978 1976 branch name (if non-default), changeset hash, parent(s) and commit
1979 1977 comment.
1980 1978
1981 1979 .. note::
1982 1980
1983 1981 :hg:`export` may generate unexpected diff output for merge
1984 1982 changesets, as it will compare the merge changeset against its
1985 1983 first parent only.
1986 1984
1987 1985 Output may be to a file, in which case the name of the file is
1988 1986 given using a format string. The formatting rules are as follows:
1989 1987
1990 1988 :``%%``: literal "%" character
1991 1989 :``%H``: changeset hash (40 hexadecimal digits)
1992 1990 :``%N``: number of patches being generated
1993 1991 :``%R``: changeset revision number
1994 1992 :``%b``: basename of the exporting repository
1995 1993 :``%h``: short-form changeset hash (12 hexadecimal digits)
1996 1994 :``%m``: first line of the commit message (only alphanumeric characters)
1997 1995 :``%n``: zero-padded sequence number, starting at 1
1998 1996 :``%r``: zero-padded changeset revision number
1999 1997
2000 1998 Without the -a/--text option, export will avoid generating diffs
2001 1999 of files it detects as binary. With -a, export will generate a
2002 2000 diff anyway, probably with undesirable results.
2003 2001
2004 2002 Use the -g/--git option to generate diffs in the git extended diff
2005 2003 format. See :hg:`help diffs` for more information.
2006 2004
2007 2005 With the --switch-parent option, the diff will be against the
2008 2006 second parent. It can be useful to review a merge.
2009 2007
2010 2008 .. container:: verbose
2011 2009
2012 2010 Examples:
2013 2011
2014 2012 - use export and import to transplant a bugfix to the current
2015 2013 branch::
2016 2014
2017 2015 hg export -r 9353 | hg import -
2018 2016
2019 2017 - export all the changesets between two revisions to a file with
2020 2018 rename information::
2021 2019
2022 2020 hg export --git -r 123:150 > changes.txt
2023 2021
2024 2022 - split outgoing changes into a series of patches with
2025 2023 descriptive names::
2026 2024
2027 2025 hg export -r "outgoing()" -o "%n-%m.patch"
2028 2026
2029 2027 Returns 0 on success.
2030 2028 """
2031 2029 changesets += tuple(opts.get('rev', []))
2032 2030 if not changesets:
2033 2031 changesets = ['.']
2034 2032 revs = scmutil.revrange(repo, changesets)
2035 2033 if not revs:
2036 2034 raise error.Abort(_("export requires at least one changeset"))
2037 2035 if len(revs) > 1:
2038 2036 ui.note(_('exporting patches:\n'))
2039 2037 else:
2040 2038 ui.note(_('exporting patch:\n'))
2041 2039 ui.pager('export')
2042 2040 cmdutil.export(repo, revs, template=opts.get('output'),
2043 2041 switch_parent=opts.get('switch_parent'),
2044 2042 opts=patch.diffallopts(ui, opts))
2045 2043
2046 2044 @command('files',
2047 2045 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2048 2046 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2049 2047 ] + walkopts + formatteropts + subrepoopts,
2050 2048 _('[OPTION]... [FILE]...'))
2051 2049 def files(ui, repo, *pats, **opts):
2052 2050 """list tracked files
2053 2051
2054 2052 Print files under Mercurial control in the working directory or
2055 2053 specified revision for given files (excluding removed files).
2056 2054 Files can be specified as filenames or filesets.
2057 2055
2058 2056 If no files are given to match, this command prints the names
2059 2057 of all files under Mercurial control.
2060 2058
2061 2059 .. container:: verbose
2062 2060
2063 2061 Examples:
2064 2062
2065 2063 - list all files under the current directory::
2066 2064
2067 2065 hg files .
2068 2066
2069 2067 - shows sizes and flags for current revision::
2070 2068
2071 2069 hg files -vr .
2072 2070
2073 2071 - list all files named README::
2074 2072
2075 2073 hg files -I "**/README"
2076 2074
2077 2075 - list all binary files::
2078 2076
2079 2077 hg files "set:binary()"
2080 2078
2081 2079 - find files containing a regular expression::
2082 2080
2083 2081 hg files "set:grep('bob')"
2084 2082
2085 2083 - search tracked file contents with xargs and grep::
2086 2084
2087 2085 hg files -0 | xargs -0 grep foo
2088 2086
2089 2087 See :hg:`help patterns` and :hg:`help filesets` for more information
2090 2088 on specifying file patterns.
2091 2089
2092 2090 Returns 0 if a match is found, 1 otherwise.
2093 2091
2094 2092 """
2095 2093 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
2096 2094
2097 2095 end = '\n'
2098 2096 if opts.get('print0'):
2099 2097 end = '\0'
2100 2098 fmt = '%s' + end
2101 2099
2102 2100 m = scmutil.match(ctx, pats, opts)
2103 2101 ui.pager('files')
2104 2102 with ui.formatter('files', opts) as fm:
2105 2103 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2106 2104
2107 2105 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2108 2106 def forget(ui, repo, *pats, **opts):
2109 2107 """forget the specified files on the next commit
2110 2108
2111 2109 Mark the specified files so they will no longer be tracked
2112 2110 after the next commit.
2113 2111
2114 2112 This only removes files from the current branch, not from the
2115 2113 entire project history, and it does not delete them from the
2116 2114 working directory.
2117 2115
2118 2116 To delete the file from the working directory, see :hg:`remove`.
2119 2117
2120 2118 To undo a forget before the next commit, see :hg:`add`.
2121 2119
2122 2120 .. container:: verbose
2123 2121
2124 2122 Examples:
2125 2123
2126 2124 - forget newly-added binary files::
2127 2125
2128 2126 hg forget "set:added() and binary()"
2129 2127
2130 2128 - forget files that would be excluded by .hgignore::
2131 2129
2132 2130 hg forget "set:hgignore()"
2133 2131
2134 2132 Returns 0 on success.
2135 2133 """
2136 2134
2137 2135 if not pats:
2138 2136 raise error.Abort(_('no files specified'))
2139 2137
2140 2138 m = scmutil.match(repo[None], pats, opts)
2141 2139 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2142 2140 return rejected and 1 or 0
2143 2141
2144 2142 @command(
2145 2143 'graft',
2146 2144 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2147 2145 ('c', 'continue', False, _('resume interrupted graft')),
2148 2146 ('e', 'edit', False, _('invoke editor on commit messages')),
2149 2147 ('', 'log', None, _('append graft info to log message')),
2150 2148 ('f', 'force', False, _('force graft')),
2151 2149 ('D', 'currentdate', False,
2152 2150 _('record the current date as commit date')),
2153 2151 ('U', 'currentuser', False,
2154 2152 _('record the current user as committer'), _('DATE'))]
2155 2153 + commitopts2 + mergetoolopts + dryrunopts,
2156 2154 _('[OPTION]... [-r REV]... REV...'))
2157 2155 def graft(ui, repo, *revs, **opts):
2158 2156 '''copy changes from other branches onto the current branch
2159 2157
2160 2158 This command uses Mercurial's merge logic to copy individual
2161 2159 changes from other branches without merging branches in the
2162 2160 history graph. This is sometimes known as 'backporting' or
2163 2161 'cherry-picking'. By default, graft will copy user, date, and
2164 2162 description from the source changesets.
2165 2163
2166 2164 Changesets that are ancestors of the current revision, that have
2167 2165 already been grafted, or that are merges will be skipped.
2168 2166
2169 2167 If --log is specified, log messages will have a comment appended
2170 2168 of the form::
2171 2169
2172 2170 (grafted from CHANGESETHASH)
2173 2171
2174 2172 If --force is specified, revisions will be grafted even if they
2175 2173 are already ancestors of or have been grafted to the destination.
2176 2174 This is useful when the revisions have since been backed out.
2177 2175
2178 2176 If a graft merge results in conflicts, the graft process is
2179 2177 interrupted so that the current merge can be manually resolved.
2180 2178 Once all conflicts are addressed, the graft process can be
2181 2179 continued with the -c/--continue option.
2182 2180
2183 2181 .. note::
2184 2182
2185 2183 The -c/--continue option does not reapply earlier options, except
2186 2184 for --force.
2187 2185
2188 2186 .. container:: verbose
2189 2187
2190 2188 Examples:
2191 2189
2192 2190 - copy a single change to the stable branch and edit its description::
2193 2191
2194 2192 hg update stable
2195 2193 hg graft --edit 9393
2196 2194
2197 2195 - graft a range of changesets with one exception, updating dates::
2198 2196
2199 2197 hg graft -D "2085::2093 and not 2091"
2200 2198
2201 2199 - continue a graft after resolving conflicts::
2202 2200
2203 2201 hg graft -c
2204 2202
2205 2203 - show the source of a grafted changeset::
2206 2204
2207 2205 hg log --debug -r .
2208 2206
2209 2207 - show revisions sorted by date::
2210 2208
2211 2209 hg log -r "sort(all(), date)"
2212 2210
2213 2211 See :hg:`help revisions` for more about specifying revisions.
2214 2212
2215 2213 Returns 0 on successful completion.
2216 2214 '''
2217 2215 with repo.wlock():
2218 2216 return _dograft(ui, repo, *revs, **opts)
2219 2217
2220 2218 def _dograft(ui, repo, *revs, **opts):
2221 2219 if revs and opts.get('rev'):
2222 2220 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2223 2221 'revision ordering!\n'))
2224 2222
2225 2223 revs = list(revs)
2226 2224 revs.extend(opts.get('rev'))
2227 2225
2228 2226 if not opts.get('user') and opts.get('currentuser'):
2229 2227 opts['user'] = ui.username()
2230 2228 if not opts.get('date') and opts.get('currentdate'):
2231 2229 opts['date'] = "%d %d" % util.makedate()
2232 2230
2233 2231 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2234 2232
2235 2233 cont = False
2236 2234 if opts.get('continue'):
2237 2235 cont = True
2238 2236 if revs:
2239 2237 raise error.Abort(_("can't specify --continue and revisions"))
2240 2238 # read in unfinished revisions
2241 2239 try:
2242 2240 nodes = repo.vfs.read('graftstate').splitlines()
2243 2241 revs = [repo[node].rev() for node in nodes]
2244 2242 except IOError as inst:
2245 2243 if inst.errno != errno.ENOENT:
2246 2244 raise
2247 2245 cmdutil.wrongtooltocontinue(repo, _('graft'))
2248 2246 else:
2249 2247 cmdutil.checkunfinished(repo)
2250 2248 cmdutil.bailifchanged(repo)
2251 2249 if not revs:
2252 2250 raise error.Abort(_('no revisions specified'))
2253 2251 revs = scmutil.revrange(repo, revs)
2254 2252
2255 2253 skipped = set()
2256 2254 # check for merges
2257 2255 for rev in repo.revs('%ld and merge()', revs):
2258 2256 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2259 2257 skipped.add(rev)
2260 2258 revs = [r for r in revs if r not in skipped]
2261 2259 if not revs:
2262 2260 return -1
2263 2261
2264 2262 # Don't check in the --continue case, in effect retaining --force across
2265 2263 # --continues. That's because without --force, any revisions we decided to
2266 2264 # skip would have been filtered out here, so they wouldn't have made their
2267 2265 # way to the graftstate. With --force, any revisions we would have otherwise
2268 2266 # skipped would not have been filtered out, and if they hadn't been applied
2269 2267 # already, they'd have been in the graftstate.
2270 2268 if not (cont or opts.get('force')):
2271 2269 # check for ancestors of dest branch
2272 2270 crev = repo['.'].rev()
2273 2271 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2274 2272 # XXX make this lazy in the future
2275 2273 # don't mutate while iterating, create a copy
2276 2274 for rev in list(revs):
2277 2275 if rev in ancestors:
2278 2276 ui.warn(_('skipping ancestor revision %d:%s\n') %
2279 2277 (rev, repo[rev]))
2280 2278 # XXX remove on list is slow
2281 2279 revs.remove(rev)
2282 2280 if not revs:
2283 2281 return -1
2284 2282
2285 2283 # analyze revs for earlier grafts
2286 2284 ids = {}
2287 2285 for ctx in repo.set("%ld", revs):
2288 2286 ids[ctx.hex()] = ctx.rev()
2289 2287 n = ctx.extra().get('source')
2290 2288 if n:
2291 2289 ids[n] = ctx.rev()
2292 2290
2293 2291 # check ancestors for earlier grafts
2294 2292 ui.debug('scanning for duplicate grafts\n')
2295 2293
2296 2294 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2297 2295 ctx = repo[rev]
2298 2296 n = ctx.extra().get('source')
2299 2297 if n in ids:
2300 2298 try:
2301 2299 r = repo[n].rev()
2302 2300 except error.RepoLookupError:
2303 2301 r = None
2304 2302 if r in revs:
2305 2303 ui.warn(_('skipping revision %d:%s '
2306 2304 '(already grafted to %d:%s)\n')
2307 2305 % (r, repo[r], rev, ctx))
2308 2306 revs.remove(r)
2309 2307 elif ids[n] in revs:
2310 2308 if r is None:
2311 2309 ui.warn(_('skipping already grafted revision %d:%s '
2312 2310 '(%d:%s also has unknown origin %s)\n')
2313 2311 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2314 2312 else:
2315 2313 ui.warn(_('skipping already grafted revision %d:%s '
2316 2314 '(%d:%s also has origin %d:%s)\n')
2317 2315 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2318 2316 revs.remove(ids[n])
2319 2317 elif ctx.hex() in ids:
2320 2318 r = ids[ctx.hex()]
2321 2319 ui.warn(_('skipping already grafted revision %d:%s '
2322 2320 '(was grafted from %d:%s)\n') %
2323 2321 (r, repo[r], rev, ctx))
2324 2322 revs.remove(r)
2325 2323 if not revs:
2326 2324 return -1
2327 2325
2328 2326 for pos, ctx in enumerate(repo.set("%ld", revs)):
2329 2327 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2330 2328 ctx.description().split('\n', 1)[0])
2331 2329 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2332 2330 if names:
2333 2331 desc += ' (%s)' % ' '.join(names)
2334 2332 ui.status(_('grafting %s\n') % desc)
2335 2333 if opts.get('dry_run'):
2336 2334 continue
2337 2335
2338 2336 source = ctx.extra().get('source')
2339 2337 extra = {}
2340 2338 if source:
2341 2339 extra['source'] = source
2342 2340 extra['intermediate-source'] = ctx.hex()
2343 2341 else:
2344 2342 extra['source'] = ctx.hex()
2345 2343 user = ctx.user()
2346 2344 if opts.get('user'):
2347 2345 user = opts['user']
2348 2346 date = ctx.date()
2349 2347 if opts.get('date'):
2350 2348 date = opts['date']
2351 2349 message = ctx.description()
2352 2350 if opts.get('log'):
2353 2351 message += '\n(grafted from %s)' % ctx.hex()
2354 2352
2355 2353 # we don't merge the first commit when continuing
2356 2354 if not cont:
2357 2355 # perform the graft merge with p1(rev) as 'ancestor'
2358 2356 try:
2359 2357 # ui.forcemerge is an internal variable, do not document
2360 2358 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2361 2359 'graft')
2362 2360 stats = mergemod.graft(repo, ctx, ctx.p1(),
2363 2361 ['local', 'graft'])
2364 2362 finally:
2365 2363 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2366 2364 # report any conflicts
2367 2365 if stats and stats[3] > 0:
2368 2366 # write out state for --continue
2369 2367 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2370 2368 repo.vfs.write('graftstate', ''.join(nodelines))
2371 2369 extra = ''
2372 2370 if opts.get('user'):
2373 2371 extra += ' --user %s' % util.shellquote(opts['user'])
2374 2372 if opts.get('date'):
2375 2373 extra += ' --date %s' % util.shellquote(opts['date'])
2376 2374 if opts.get('log'):
2377 2375 extra += ' --log'
2378 2376 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2379 2377 raise error.Abort(
2380 2378 _("unresolved conflicts, can't continue"),
2381 2379 hint=hint)
2382 2380 else:
2383 2381 cont = False
2384 2382
2385 2383 # commit
2386 2384 node = repo.commit(text=message, user=user,
2387 2385 date=date, extra=extra, editor=editor)
2388 2386 if node is None:
2389 2387 ui.warn(
2390 2388 _('note: graft of %d:%s created no changes to commit\n') %
2391 2389 (ctx.rev(), ctx))
2392 2390
2393 2391 # remove state when we complete successfully
2394 2392 if not opts.get('dry_run'):
2395 2393 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2396 2394
2397 2395 return 0
2398 2396
2399 2397 @command('grep',
2400 2398 [('0', 'print0', None, _('end fields with NUL')),
2401 2399 ('', 'all', None, _('print all revisions that match')),
2402 2400 ('a', 'text', None, _('treat all files as text')),
2403 2401 ('f', 'follow', None,
2404 2402 _('follow changeset history,'
2405 2403 ' or file history across copies and renames')),
2406 2404 ('i', 'ignore-case', None, _('ignore case when matching')),
2407 2405 ('l', 'files-with-matches', None,
2408 2406 _('print only filenames and revisions that match')),
2409 2407 ('n', 'line-number', None, _('print matching line numbers')),
2410 2408 ('r', 'rev', [],
2411 2409 _('only search files changed within revision range'), _('REV')),
2412 2410 ('u', 'user', None, _('list the author (long with -v)')),
2413 2411 ('d', 'date', None, _('list the date (short with -q)')),
2414 2412 ] + formatteropts + walkopts,
2415 2413 _('[OPTION]... PATTERN [FILE]...'),
2416 2414 inferrepo=True)
2417 2415 def grep(ui, repo, pattern, *pats, **opts):
2418 2416 """search revision history for a pattern in specified files
2419 2417
2420 2418 Search revision history for a regular expression in the specified
2421 2419 files or the entire project.
2422 2420
2423 2421 By default, grep prints the most recent revision number for each
2424 2422 file in which it finds a match. To get it to print every revision
2425 2423 that contains a change in match status ("-" for a match that becomes
2426 2424 a non-match, or "+" for a non-match that becomes a match), use the
2427 2425 --all flag.
2428 2426
2429 2427 PATTERN can be any Python (roughly Perl-compatible) regular
2430 2428 expression.
2431 2429
2432 2430 If no FILEs are specified (and -f/--follow isn't set), all files in
2433 2431 the repository are searched, including those that don't exist in the
2434 2432 current branch or have been deleted in a prior changeset.
2435 2433
2436 2434 Returns 0 if a match is found, 1 otherwise.
2437 2435 """
2438 2436 reflags = re.M
2439 2437 if opts.get('ignore_case'):
2440 2438 reflags |= re.I
2441 2439 try:
2442 2440 regexp = util.re.compile(pattern, reflags)
2443 2441 except re.error as inst:
2444 2442 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2445 2443 return 1
2446 2444 sep, eol = ':', '\n'
2447 2445 if opts.get('print0'):
2448 2446 sep = eol = '\0'
2449 2447
2450 2448 getfile = util.lrucachefunc(repo.file)
2451 2449
2452 2450 def matchlines(body):
2453 2451 begin = 0
2454 2452 linenum = 0
2455 2453 while begin < len(body):
2456 2454 match = regexp.search(body, begin)
2457 2455 if not match:
2458 2456 break
2459 2457 mstart, mend = match.span()
2460 2458 linenum += body.count('\n', begin, mstart) + 1
2461 2459 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2462 2460 begin = body.find('\n', mend) + 1 or len(body) + 1
2463 2461 lend = begin - 1
2464 2462 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2465 2463
2466 2464 class linestate(object):
2467 2465 def __init__(self, line, linenum, colstart, colend):
2468 2466 self.line = line
2469 2467 self.linenum = linenum
2470 2468 self.colstart = colstart
2471 2469 self.colend = colend
2472 2470
2473 2471 def __hash__(self):
2474 2472 return hash((self.linenum, self.line))
2475 2473
2476 2474 def __eq__(self, other):
2477 2475 return self.line == other.line
2478 2476
2479 2477 def findpos(self):
2480 2478 """Iterate all (start, end) indices of matches"""
2481 2479 yield self.colstart, self.colend
2482 2480 p = self.colend
2483 2481 while p < len(self.line):
2484 2482 m = regexp.search(self.line, p)
2485 2483 if not m:
2486 2484 break
2487 2485 yield m.span()
2488 2486 p = m.end()
2489 2487
2490 2488 matches = {}
2491 2489 copies = {}
2492 2490 def grepbody(fn, rev, body):
2493 2491 matches[rev].setdefault(fn, [])
2494 2492 m = matches[rev][fn]
2495 2493 for lnum, cstart, cend, line in matchlines(body):
2496 2494 s = linestate(line, lnum, cstart, cend)
2497 2495 m.append(s)
2498 2496
2499 2497 def difflinestates(a, b):
2500 2498 sm = difflib.SequenceMatcher(None, a, b)
2501 2499 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2502 2500 if tag == 'insert':
2503 2501 for i in xrange(blo, bhi):
2504 2502 yield ('+', b[i])
2505 2503 elif tag == 'delete':
2506 2504 for i in xrange(alo, ahi):
2507 2505 yield ('-', a[i])
2508 2506 elif tag == 'replace':
2509 2507 for i in xrange(alo, ahi):
2510 2508 yield ('-', a[i])
2511 2509 for i in xrange(blo, bhi):
2512 2510 yield ('+', b[i])
2513 2511
2514 2512 def display(fm, fn, ctx, pstates, states):
2515 2513 rev = ctx.rev()
2516 2514 if fm.isplain():
2517 2515 formatuser = ui.shortuser
2518 2516 else:
2519 2517 formatuser = str
2520 2518 if ui.quiet:
2521 2519 datefmt = '%Y-%m-%d'
2522 2520 else:
2523 2521 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2524 2522 found = False
2525 2523 @util.cachefunc
2526 2524 def binary():
2527 2525 flog = getfile(fn)
2528 2526 return util.binary(flog.read(ctx.filenode(fn)))
2529 2527
2530 2528 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2531 2529 if opts.get('all'):
2532 2530 iter = difflinestates(pstates, states)
2533 2531 else:
2534 2532 iter = [('', l) for l in states]
2535 2533 for change, l in iter:
2536 2534 fm.startitem()
2537 2535 fm.data(node=fm.hexfunc(ctx.node()))
2538 2536 cols = [
2539 2537 ('filename', fn, True),
2540 2538 ('rev', rev, True),
2541 2539 ('linenumber', l.linenum, opts.get('line_number')),
2542 2540 ]
2543 2541 if opts.get('all'):
2544 2542 cols.append(('change', change, True))
2545 2543 cols.extend([
2546 2544 ('user', formatuser(ctx.user()), opts.get('user')),
2547 2545 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2548 2546 ])
2549 2547 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2550 2548 for name, data, cond in cols:
2551 2549 field = fieldnamemap.get(name, name)
2552 2550 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2553 2551 if cond and name != lastcol:
2554 2552 fm.plain(sep, label='grep.sep')
2555 2553 if not opts.get('files_with_matches'):
2556 2554 fm.plain(sep, label='grep.sep')
2557 2555 if not opts.get('text') and binary():
2558 2556 fm.plain(_(" Binary file matches"))
2559 2557 else:
2560 2558 displaymatches(fm.nested('texts'), l)
2561 2559 fm.plain(eol)
2562 2560 found = True
2563 2561 if opts.get('files_with_matches'):
2564 2562 break
2565 2563 return found
2566 2564
2567 2565 def displaymatches(fm, l):
2568 2566 p = 0
2569 2567 for s, e in l.findpos():
2570 2568 if p < s:
2571 2569 fm.startitem()
2572 2570 fm.write('text', '%s', l.line[p:s])
2573 2571 fm.data(matched=False)
2574 2572 fm.startitem()
2575 2573 fm.write('text', '%s', l.line[s:e], label='grep.match')
2576 2574 fm.data(matched=True)
2577 2575 p = e
2578 2576 if p < len(l.line):
2579 2577 fm.startitem()
2580 2578 fm.write('text', '%s', l.line[p:])
2581 2579 fm.data(matched=False)
2582 2580 fm.end()
2583 2581
2584 2582 skip = {}
2585 2583 revfiles = {}
2586 2584 matchfn = scmutil.match(repo[None], pats, opts)
2587 2585 found = False
2588 2586 follow = opts.get('follow')
2589 2587
2590 2588 def prep(ctx, fns):
2591 2589 rev = ctx.rev()
2592 2590 pctx = ctx.p1()
2593 2591 parent = pctx.rev()
2594 2592 matches.setdefault(rev, {})
2595 2593 matches.setdefault(parent, {})
2596 2594 files = revfiles.setdefault(rev, [])
2597 2595 for fn in fns:
2598 2596 flog = getfile(fn)
2599 2597 try:
2600 2598 fnode = ctx.filenode(fn)
2601 2599 except error.LookupError:
2602 2600 continue
2603 2601
2604 2602 copied = flog.renamed(fnode)
2605 2603 copy = follow and copied and copied[0]
2606 2604 if copy:
2607 2605 copies.setdefault(rev, {})[fn] = copy
2608 2606 if fn in skip:
2609 2607 if copy:
2610 2608 skip[copy] = True
2611 2609 continue
2612 2610 files.append(fn)
2613 2611
2614 2612 if fn not in matches[rev]:
2615 2613 grepbody(fn, rev, flog.read(fnode))
2616 2614
2617 2615 pfn = copy or fn
2618 2616 if pfn not in matches[parent]:
2619 2617 try:
2620 2618 fnode = pctx.filenode(pfn)
2621 2619 grepbody(pfn, parent, flog.read(fnode))
2622 2620 except error.LookupError:
2623 2621 pass
2624 2622
2625 2623 ui.pager('grep')
2626 2624 fm = ui.formatter('grep', opts)
2627 2625 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2628 2626 rev = ctx.rev()
2629 2627 parent = ctx.p1().rev()
2630 2628 for fn in sorted(revfiles.get(rev, [])):
2631 2629 states = matches[rev][fn]
2632 2630 copy = copies.get(rev, {}).get(fn)
2633 2631 if fn in skip:
2634 2632 if copy:
2635 2633 skip[copy] = True
2636 2634 continue
2637 2635 pstates = matches.get(parent, {}).get(copy or fn, [])
2638 2636 if pstates or states:
2639 2637 r = display(fm, fn, ctx, pstates, states)
2640 2638 found = found or r
2641 2639 if r and not opts.get('all'):
2642 2640 skip[fn] = True
2643 2641 if copy:
2644 2642 skip[copy] = True
2645 2643 del matches[rev]
2646 2644 del revfiles[rev]
2647 2645 fm.end()
2648 2646
2649 2647 return not found
2650 2648
2651 2649 @command('heads',
2652 2650 [('r', 'rev', '',
2653 2651 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2654 2652 ('t', 'topo', False, _('show topological heads only')),
2655 2653 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2656 2654 ('c', 'closed', False, _('show normal and closed branch heads')),
2657 2655 ] + templateopts,
2658 2656 _('[-ct] [-r STARTREV] [REV]...'))
2659 2657 def heads(ui, repo, *branchrevs, **opts):
2660 2658 """show branch heads
2661 2659
2662 2660 With no arguments, show all open branch heads in the repository.
2663 2661 Branch heads are changesets that have no descendants on the
2664 2662 same branch. They are where development generally takes place and
2665 2663 are the usual targets for update and merge operations.
2666 2664
2667 2665 If one or more REVs are given, only open branch heads on the
2668 2666 branches associated with the specified changesets are shown. This
2669 2667 means that you can use :hg:`heads .` to see the heads on the
2670 2668 currently checked-out branch.
2671 2669
2672 2670 If -c/--closed is specified, also show branch heads marked closed
2673 2671 (see :hg:`commit --close-branch`).
2674 2672
2675 2673 If STARTREV is specified, only those heads that are descendants of
2676 2674 STARTREV will be displayed.
2677 2675
2678 2676 If -t/--topo is specified, named branch mechanics will be ignored and only
2679 2677 topological heads (changesets with no children) will be shown.
2680 2678
2681 2679 Returns 0 if matching heads are found, 1 if not.
2682 2680 """
2683 2681
2684 2682 start = None
2685 2683 if 'rev' in opts:
2686 2684 start = scmutil.revsingle(repo, opts['rev'], None).node()
2687 2685
2688 2686 if opts.get('topo'):
2689 2687 heads = [repo[h] for h in repo.heads(start)]
2690 2688 else:
2691 2689 heads = []
2692 2690 for branch in repo.branchmap():
2693 2691 heads += repo.branchheads(branch, start, opts.get('closed'))
2694 2692 heads = [repo[h] for h in heads]
2695 2693
2696 2694 if branchrevs:
2697 2695 branches = set(repo[br].branch() for br in branchrevs)
2698 2696 heads = [h for h in heads if h.branch() in branches]
2699 2697
2700 2698 if opts.get('active') and branchrevs:
2701 2699 dagheads = repo.heads(start)
2702 2700 heads = [h for h in heads if h.node() in dagheads]
2703 2701
2704 2702 if branchrevs:
2705 2703 haveheads = set(h.branch() for h in heads)
2706 2704 if branches - haveheads:
2707 2705 headless = ', '.join(b for b in branches - haveheads)
2708 2706 msg = _('no open branch heads found on branches %s')
2709 2707 if opts.get('rev'):
2710 2708 msg += _(' (started at %s)') % opts['rev']
2711 2709 ui.warn((msg + '\n') % headless)
2712 2710
2713 2711 if not heads:
2714 2712 return 1
2715 2713
2716 2714 ui.pager('heads')
2717 2715 heads = sorted(heads, key=lambda x: -x.rev())
2718 2716 displayer = cmdutil.show_changeset(ui, repo, opts)
2719 2717 for ctx in heads:
2720 2718 displayer.show(ctx)
2721 2719 displayer.close()
2722 2720
2723 2721 @command('help',
2724 2722 [('e', 'extension', None, _('show only help for extensions')),
2725 2723 ('c', 'command', None, _('show only help for commands')),
2726 2724 ('k', 'keyword', None, _('show topics matching keyword')),
2727 2725 ('s', 'system', [], _('show help for specific platform(s)')),
2728 2726 ],
2729 2727 _('[-ecks] [TOPIC]'),
2730 2728 norepo=True)
2731 2729 def help_(ui, name=None, **opts):
2732 2730 """show help for a given topic or a help overview
2733 2731
2734 2732 With no arguments, print a list of commands with short help messages.
2735 2733
2736 2734 Given a topic, extension, or command name, print help for that
2737 2735 topic.
2738 2736
2739 2737 Returns 0 if successful.
2740 2738 """
2741 2739
2742 2740 keep = opts.get('system') or []
2743 2741 if len(keep) == 0:
2744 2742 if pycompat.sysplatform.startswith('win'):
2745 2743 keep.append('windows')
2746 2744 elif pycompat.sysplatform == 'OpenVMS':
2747 2745 keep.append('vms')
2748 2746 elif pycompat.sysplatform == 'plan9':
2749 2747 keep.append('plan9')
2750 2748 else:
2751 2749 keep.append('unix')
2752 2750 keep.append(pycompat.sysplatform.lower())
2753 2751 if ui.verbose:
2754 2752 keep.append('verbose')
2755 2753
2756 2754 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2757 2755 ui.pager('help')
2758 2756 ui.write(formatted)
2759 2757
2760 2758
2761 2759 @command('identify|id',
2762 2760 [('r', 'rev', '',
2763 2761 _('identify the specified revision'), _('REV')),
2764 2762 ('n', 'num', None, _('show local revision number')),
2765 2763 ('i', 'id', None, _('show global revision id')),
2766 2764 ('b', 'branch', None, _('show branch')),
2767 2765 ('t', 'tags', None, _('show tags')),
2768 2766 ('B', 'bookmarks', None, _('show bookmarks')),
2769 2767 ] + remoteopts,
2770 2768 _('[-nibtB] [-r REV] [SOURCE]'),
2771 2769 optionalrepo=True)
2772 2770 def identify(ui, repo, source=None, rev=None,
2773 2771 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2774 2772 """identify the working directory or specified revision
2775 2773
2776 2774 Print a summary identifying the repository state at REV using one or
2777 2775 two parent hash identifiers, followed by a "+" if the working
2778 2776 directory has uncommitted changes, the branch name (if not default),
2779 2777 a list of tags, and a list of bookmarks.
2780 2778
2781 2779 When REV is not given, print a summary of the current state of the
2782 2780 repository.
2783 2781
2784 2782 Specifying a path to a repository root or Mercurial bundle will
2785 2783 cause lookup to operate on that repository/bundle.
2786 2784
2787 2785 .. container:: verbose
2788 2786
2789 2787 Examples:
2790 2788
2791 2789 - generate a build identifier for the working directory::
2792 2790
2793 2791 hg id --id > build-id.dat
2794 2792
2795 2793 - find the revision corresponding to a tag::
2796 2794
2797 2795 hg id -n -r 1.3
2798 2796
2799 2797 - check the most recent revision of a remote repository::
2800 2798
2801 2799 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2802 2800
2803 2801 See :hg:`log` for generating more information about specific revisions,
2804 2802 including full hash identifiers.
2805 2803
2806 2804 Returns 0 if successful.
2807 2805 """
2808 2806
2809 2807 if not repo and not source:
2810 2808 raise error.Abort(_("there is no Mercurial repository here "
2811 2809 "(.hg not found)"))
2812 2810
2813 2811 if ui.debugflag:
2814 2812 hexfunc = hex
2815 2813 else:
2816 2814 hexfunc = short
2817 2815 default = not (num or id or branch or tags or bookmarks)
2818 2816 output = []
2819 2817 revs = []
2820 2818
2821 2819 if source:
2822 2820 source, branches = hg.parseurl(ui.expandpath(source))
2823 2821 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2824 2822 repo = peer.local()
2825 2823 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2826 2824
2827 2825 if not repo:
2828 2826 if num or branch or tags:
2829 2827 raise error.Abort(
2830 2828 _("can't query remote revision number, branch, or tags"))
2831 2829 if not rev and revs:
2832 2830 rev = revs[0]
2833 2831 if not rev:
2834 2832 rev = "tip"
2835 2833
2836 2834 remoterev = peer.lookup(rev)
2837 2835 if default or id:
2838 2836 output = [hexfunc(remoterev)]
2839 2837
2840 2838 def getbms():
2841 2839 bms = []
2842 2840
2843 2841 if 'bookmarks' in peer.listkeys('namespaces'):
2844 2842 hexremoterev = hex(remoterev)
2845 2843 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2846 2844 if bmr == hexremoterev]
2847 2845
2848 2846 return sorted(bms)
2849 2847
2850 2848 if bookmarks:
2851 2849 output.extend(getbms())
2852 2850 elif default and not ui.quiet:
2853 2851 # multiple bookmarks for a single parent separated by '/'
2854 2852 bm = '/'.join(getbms())
2855 2853 if bm:
2856 2854 output.append(bm)
2857 2855 else:
2858 2856 ctx = scmutil.revsingle(repo, rev, None)
2859 2857
2860 2858 if ctx.rev() is None:
2861 2859 ctx = repo[None]
2862 2860 parents = ctx.parents()
2863 2861 taglist = []
2864 2862 for p in parents:
2865 2863 taglist.extend(p.tags())
2866 2864
2867 2865 changed = ""
2868 2866 if default or id or num:
2869 2867 if (any(repo.status())
2870 2868 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2871 2869 changed = '+'
2872 2870 if default or id:
2873 2871 output = ["%s%s" %
2874 2872 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2875 2873 if num:
2876 2874 output.append("%s%s" %
2877 2875 ('+'.join([str(p.rev()) for p in parents]), changed))
2878 2876 else:
2879 2877 if default or id:
2880 2878 output = [hexfunc(ctx.node())]
2881 2879 if num:
2882 2880 output.append(str(ctx.rev()))
2883 2881 taglist = ctx.tags()
2884 2882
2885 2883 if default and not ui.quiet:
2886 2884 b = ctx.branch()
2887 2885 if b != 'default':
2888 2886 output.append("(%s)" % b)
2889 2887
2890 2888 # multiple tags for a single parent separated by '/'
2891 2889 t = '/'.join(taglist)
2892 2890 if t:
2893 2891 output.append(t)
2894 2892
2895 2893 # multiple bookmarks for a single parent separated by '/'
2896 2894 bm = '/'.join(ctx.bookmarks())
2897 2895 if bm:
2898 2896 output.append(bm)
2899 2897 else:
2900 2898 if branch:
2901 2899 output.append(ctx.branch())
2902 2900
2903 2901 if tags:
2904 2902 output.extend(taglist)
2905 2903
2906 2904 if bookmarks:
2907 2905 output.extend(ctx.bookmarks())
2908 2906
2909 2907 ui.write("%s\n" % ' '.join(output))
2910 2908
2911 2909 @command('import|patch',
2912 2910 [('p', 'strip', 1,
2913 2911 _('directory strip option for patch. This has the same '
2914 2912 'meaning as the corresponding patch option'), _('NUM')),
2915 2913 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2916 2914 ('e', 'edit', False, _('invoke editor on commit messages')),
2917 2915 ('f', 'force', None,
2918 2916 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2919 2917 ('', 'no-commit', None,
2920 2918 _("don't commit, just update the working directory")),
2921 2919 ('', 'bypass', None,
2922 2920 _("apply patch without touching the working directory")),
2923 2921 ('', 'partial', None,
2924 2922 _('commit even if some hunks fail')),
2925 2923 ('', 'exact', None,
2926 2924 _('abort if patch would apply lossily')),
2927 2925 ('', 'prefix', '',
2928 2926 _('apply patch to subdirectory'), _('DIR')),
2929 2927 ('', 'import-branch', None,
2930 2928 _('use any branch information in patch (implied by --exact)'))] +
2931 2929 commitopts + commitopts2 + similarityopts,
2932 2930 _('[OPTION]... PATCH...'))
2933 2931 def import_(ui, repo, patch1=None, *patches, **opts):
2934 2932 """import an ordered set of patches
2935 2933
2936 2934 Import a list of patches and commit them individually (unless
2937 2935 --no-commit is specified).
2938 2936
2939 2937 To read a patch from standard input (stdin), use "-" as the patch
2940 2938 name. If a URL is specified, the patch will be downloaded from
2941 2939 there.
2942 2940
2943 2941 Import first applies changes to the working directory (unless
2944 2942 --bypass is specified), import will abort if there are outstanding
2945 2943 changes.
2946 2944
2947 2945 Use --bypass to apply and commit patches directly to the
2948 2946 repository, without affecting the working directory. Without
2949 2947 --exact, patches will be applied on top of the working directory
2950 2948 parent revision.
2951 2949
2952 2950 You can import a patch straight from a mail message. Even patches
2953 2951 as attachments work (to use the body part, it must have type
2954 2952 text/plain or text/x-patch). From and Subject headers of email
2955 2953 message are used as default committer and commit message. All
2956 2954 text/plain body parts before first diff are added to the commit
2957 2955 message.
2958 2956
2959 2957 If the imported patch was generated by :hg:`export`, user and
2960 2958 description from patch override values from message headers and
2961 2959 body. Values given on command line with -m/--message and -u/--user
2962 2960 override these.
2963 2961
2964 2962 If --exact is specified, import will set the working directory to
2965 2963 the parent of each patch before applying it, and will abort if the
2966 2964 resulting changeset has a different ID than the one recorded in
2967 2965 the patch. This will guard against various ways that portable
2968 2966 patch formats and mail systems might fail to transfer Mercurial
2969 2967 data or metadata. See :hg:`bundle` for lossless transmission.
2970 2968
2971 2969 Use --partial to ensure a changeset will be created from the patch
2972 2970 even if some hunks fail to apply. Hunks that fail to apply will be
2973 2971 written to a <target-file>.rej file. Conflicts can then be resolved
2974 2972 by hand before :hg:`commit --amend` is run to update the created
2975 2973 changeset. This flag exists to let people import patches that
2976 2974 partially apply without losing the associated metadata (author,
2977 2975 date, description, ...).
2978 2976
2979 2977 .. note::
2980 2978
2981 2979 When no hunks apply cleanly, :hg:`import --partial` will create
2982 2980 an empty changeset, importing only the patch metadata.
2983 2981
2984 2982 With -s/--similarity, hg will attempt to discover renames and
2985 2983 copies in the patch in the same way as :hg:`addremove`.
2986 2984
2987 2985 It is possible to use external patch programs to perform the patch
2988 2986 by setting the ``ui.patch`` configuration option. For the default
2989 2987 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2990 2988 See :hg:`help config` for more information about configuration
2991 2989 files and how to use these options.
2992 2990
2993 2991 See :hg:`help dates` for a list of formats valid for -d/--date.
2994 2992
2995 2993 .. container:: verbose
2996 2994
2997 2995 Examples:
2998 2996
2999 2997 - import a traditional patch from a website and detect renames::
3000 2998
3001 2999 hg import -s 80 http://example.com/bugfix.patch
3002 3000
3003 3001 - import a changeset from an hgweb server::
3004 3002
3005 3003 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3006 3004
3007 3005 - import all the patches in an Unix-style mbox::
3008 3006
3009 3007 hg import incoming-patches.mbox
3010 3008
3011 3009 - import patches from stdin::
3012 3010
3013 3011 hg import -
3014 3012
3015 3013 - attempt to exactly restore an exported changeset (not always
3016 3014 possible)::
3017 3015
3018 3016 hg import --exact proposed-fix.patch
3019 3017
3020 3018 - use an external tool to apply a patch which is too fuzzy for
3021 3019 the default internal tool.
3022 3020
3023 3021 hg import --config ui.patch="patch --merge" fuzzy.patch
3024 3022
3025 3023 - change the default fuzzing from 2 to a less strict 7
3026 3024
3027 3025 hg import --config ui.fuzz=7 fuzz.patch
3028 3026
3029 3027 Returns 0 on success, 1 on partial success (see --partial).
3030 3028 """
3031 3029
3032 3030 if not patch1:
3033 3031 raise error.Abort(_('need at least one patch to import'))
3034 3032
3035 3033 patches = (patch1,) + patches
3036 3034
3037 3035 date = opts.get('date')
3038 3036 if date:
3039 3037 opts['date'] = util.parsedate(date)
3040 3038
3041 3039 exact = opts.get('exact')
3042 3040 update = not opts.get('bypass')
3043 3041 if not update and opts.get('no_commit'):
3044 3042 raise error.Abort(_('cannot use --no-commit with --bypass'))
3045 3043 try:
3046 3044 sim = float(opts.get('similarity') or 0)
3047 3045 except ValueError:
3048 3046 raise error.Abort(_('similarity must be a number'))
3049 3047 if sim < 0 or sim > 100:
3050 3048 raise error.Abort(_('similarity must be between 0 and 100'))
3051 3049 if sim and not update:
3052 3050 raise error.Abort(_('cannot use --similarity with --bypass'))
3053 3051 if exact:
3054 3052 if opts.get('edit'):
3055 3053 raise error.Abort(_('cannot use --exact with --edit'))
3056 3054 if opts.get('prefix'):
3057 3055 raise error.Abort(_('cannot use --exact with --prefix'))
3058 3056
3059 3057 base = opts["base"]
3060 3058 wlock = dsguard = lock = tr = None
3061 3059 msgs = []
3062 3060 ret = 0
3063 3061
3064 3062
3065 3063 try:
3066 3064 wlock = repo.wlock()
3067 3065
3068 3066 if update:
3069 3067 cmdutil.checkunfinished(repo)
3070 3068 if (exact or not opts.get('force')):
3071 3069 cmdutil.bailifchanged(repo)
3072 3070
3073 3071 if not opts.get('no_commit'):
3074 3072 lock = repo.lock()
3075 3073 tr = repo.transaction('import')
3076 3074 else:
3077 3075 dsguard = dirstateguard.dirstateguard(repo, 'import')
3078 3076 parents = repo[None].parents()
3079 3077 for patchurl in patches:
3080 3078 if patchurl == '-':
3081 3079 ui.status(_('applying patch from stdin\n'))
3082 3080 patchfile = ui.fin
3083 3081 patchurl = 'stdin' # for error message
3084 3082 else:
3085 3083 patchurl = os.path.join(base, patchurl)
3086 3084 ui.status(_('applying %s\n') % patchurl)
3087 3085 patchfile = hg.openpath(ui, patchurl)
3088 3086
3089 3087 haspatch = False
3090 3088 for hunk in patch.split(patchfile):
3091 3089 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3092 3090 parents, opts,
3093 3091 msgs, hg.clean)
3094 3092 if msg:
3095 3093 haspatch = True
3096 3094 ui.note(msg + '\n')
3097 3095 if update or exact:
3098 3096 parents = repo[None].parents()
3099 3097 else:
3100 3098 parents = [repo[node]]
3101 3099 if rej:
3102 3100 ui.write_err(_("patch applied partially\n"))
3103 3101 ui.write_err(_("(fix the .rej files and run "
3104 3102 "`hg commit --amend`)\n"))
3105 3103 ret = 1
3106 3104 break
3107 3105
3108 3106 if not haspatch:
3109 3107 raise error.Abort(_('%s: no diffs found') % patchurl)
3110 3108
3111 3109 if tr:
3112 3110 tr.close()
3113 3111 if msgs:
3114 3112 repo.savecommitmessage('\n* * *\n'.join(msgs))
3115 3113 if dsguard:
3116 3114 dsguard.close()
3117 3115 return ret
3118 3116 finally:
3119 3117 if tr:
3120 3118 tr.release()
3121 3119 release(lock, dsguard, wlock)
3122 3120
3123 3121 @command('incoming|in',
3124 3122 [('f', 'force', None,
3125 3123 _('run even if remote repository is unrelated')),
3126 3124 ('n', 'newest-first', None, _('show newest record first')),
3127 3125 ('', 'bundle', '',
3128 3126 _('file to store the bundles into'), _('FILE')),
3129 3127 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3130 3128 ('B', 'bookmarks', False, _("compare bookmarks")),
3131 3129 ('b', 'branch', [],
3132 3130 _('a specific branch you would like to pull'), _('BRANCH')),
3133 3131 ] + logopts + remoteopts + subrepoopts,
3134 3132 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3135 3133 def incoming(ui, repo, source="default", **opts):
3136 3134 """show new changesets found in source
3137 3135
3138 3136 Show new changesets found in the specified path/URL or the default
3139 3137 pull location. These are the changesets that would have been pulled
3140 3138 if a pull at the time you issued this command.
3141 3139
3142 3140 See pull for valid source format details.
3143 3141
3144 3142 .. container:: verbose
3145 3143
3146 3144 With -B/--bookmarks, the result of bookmark comparison between
3147 3145 local and remote repositories is displayed. With -v/--verbose,
3148 3146 status is also displayed for each bookmark like below::
3149 3147
3150 3148 BM1 01234567890a added
3151 3149 BM2 1234567890ab advanced
3152 3150 BM3 234567890abc diverged
3153 3151 BM4 34567890abcd changed
3154 3152
3155 3153 The action taken locally when pulling depends on the
3156 3154 status of each bookmark:
3157 3155
3158 3156 :``added``: pull will create it
3159 3157 :``advanced``: pull will update it
3160 3158 :``diverged``: pull will create a divergent bookmark
3161 3159 :``changed``: result depends on remote changesets
3162 3160
3163 3161 From the point of view of pulling behavior, bookmark
3164 3162 existing only in the remote repository are treated as ``added``,
3165 3163 even if it is in fact locally deleted.
3166 3164
3167 3165 .. container:: verbose
3168 3166
3169 3167 For remote repository, using --bundle avoids downloading the
3170 3168 changesets twice if the incoming is followed by a pull.
3171 3169
3172 3170 Examples:
3173 3171
3174 3172 - show incoming changes with patches and full description::
3175 3173
3176 3174 hg incoming -vp
3177 3175
3178 3176 - show incoming changes excluding merges, store a bundle::
3179 3177
3180 3178 hg in -vpM --bundle incoming.hg
3181 3179 hg pull incoming.hg
3182 3180
3183 3181 - briefly list changes inside a bundle::
3184 3182
3185 3183 hg in changes.hg -T "{desc|firstline}\\n"
3186 3184
3187 3185 Returns 0 if there are incoming changes, 1 otherwise.
3188 3186 """
3189 3187 if opts.get('graph'):
3190 3188 cmdutil.checkunsupportedgraphflags([], opts)
3191 3189 def display(other, chlist, displayer):
3192 3190 revdag = cmdutil.graphrevs(other, chlist, opts)
3193 3191 cmdutil.displaygraph(ui, repo, revdag, displayer,
3194 3192 graphmod.asciiedges)
3195 3193
3196 3194 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3197 3195 return 0
3198 3196
3199 3197 if opts.get('bundle') and opts.get('subrepos'):
3200 3198 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3201 3199
3202 3200 if opts.get('bookmarks'):
3203 3201 source, branches = hg.parseurl(ui.expandpath(source),
3204 3202 opts.get('branch'))
3205 3203 other = hg.peer(repo, opts, source)
3206 3204 if 'bookmarks' not in other.listkeys('namespaces'):
3207 3205 ui.warn(_("remote doesn't support bookmarks\n"))
3208 3206 return 0
3209 3207 ui.pager('incoming')
3210 3208 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3211 3209 return bookmarks.incoming(ui, repo, other)
3212 3210
3213 3211 repo._subtoppath = ui.expandpath(source)
3214 3212 try:
3215 3213 return hg.incoming(ui, repo, source, opts)
3216 3214 finally:
3217 3215 del repo._subtoppath
3218 3216
3219 3217
3220 3218 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3221 3219 norepo=True)
3222 3220 def init(ui, dest=".", **opts):
3223 3221 """create a new repository in the given directory
3224 3222
3225 3223 Initialize a new repository in the given directory. If the given
3226 3224 directory does not exist, it will be created.
3227 3225
3228 3226 If no directory is given, the current directory is used.
3229 3227
3230 3228 It is possible to specify an ``ssh://`` URL as the destination.
3231 3229 See :hg:`help urls` for more information.
3232 3230
3233 3231 Returns 0 on success.
3234 3232 """
3235 3233 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3236 3234
3237 3235 @command('locate',
3238 3236 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3239 3237 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3240 3238 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3241 3239 ] + walkopts,
3242 3240 _('[OPTION]... [PATTERN]...'))
3243 3241 def locate(ui, repo, *pats, **opts):
3244 3242 """locate files matching specific patterns (DEPRECATED)
3245 3243
3246 3244 Print files under Mercurial control in the working directory whose
3247 3245 names match the given patterns.
3248 3246
3249 3247 By default, this command searches all directories in the working
3250 3248 directory. To search just the current directory and its
3251 3249 subdirectories, use "--include .".
3252 3250
3253 3251 If no patterns are given to match, this command prints the names
3254 3252 of all files under Mercurial control in the working directory.
3255 3253
3256 3254 If you want to feed the output of this command into the "xargs"
3257 3255 command, use the -0 option to both this command and "xargs". This
3258 3256 will avoid the problem of "xargs" treating single filenames that
3259 3257 contain whitespace as multiple filenames.
3260 3258
3261 3259 See :hg:`help files` for a more versatile command.
3262 3260
3263 3261 Returns 0 if a match is found, 1 otherwise.
3264 3262 """
3265 3263 if opts.get('print0'):
3266 3264 end = '\0'
3267 3265 else:
3268 3266 end = '\n'
3269 3267 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3270 3268
3271 3269 ret = 1
3272 3270 ctx = repo[rev]
3273 3271 m = scmutil.match(ctx, pats, opts, default='relglob',
3274 3272 badfn=lambda x, y: False)
3275 3273
3276 3274 ui.pager('locate')
3277 3275 for abs in ctx.matches(m):
3278 3276 if opts.get('fullpath'):
3279 3277 ui.write(repo.wjoin(abs), end)
3280 3278 else:
3281 3279 ui.write(((pats and m.rel(abs)) or abs), end)
3282 3280 ret = 0
3283 3281
3284 3282 return ret
3285 3283
3286 3284 @command('^log|history',
3287 3285 [('f', 'follow', None,
3288 3286 _('follow changeset history, or file history across copies and renames')),
3289 3287 ('', 'follow-first', None,
3290 3288 _('only follow the first parent of merge changesets (DEPRECATED)')),
3291 3289 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3292 3290 ('C', 'copies', None, _('show copied files')),
3293 3291 ('k', 'keyword', [],
3294 3292 _('do case-insensitive search for a given text'), _('TEXT')),
3295 3293 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3296 3294 ('', 'removed', None, _('include revisions where files were removed')),
3297 3295 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3298 3296 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3299 3297 ('', 'only-branch', [],
3300 3298 _('show only changesets within the given named branch (DEPRECATED)'),
3301 3299 _('BRANCH')),
3302 3300 ('b', 'branch', [],
3303 3301 _('show changesets within the given named branch'), _('BRANCH')),
3304 3302 ('P', 'prune', [],
3305 3303 _('do not display revision or any of its ancestors'), _('REV')),
3306 3304 ] + logopts + walkopts,
3307 3305 _('[OPTION]... [FILE]'),
3308 3306 inferrepo=True)
3309 3307 def log(ui, repo, *pats, **opts):
3310 3308 """show revision history of entire repository or files
3311 3309
3312 3310 Print the revision history of the specified files or the entire
3313 3311 project.
3314 3312
3315 3313 If no revision range is specified, the default is ``tip:0`` unless
3316 3314 --follow is set, in which case the working directory parent is
3317 3315 used as the starting revision.
3318 3316
3319 3317 File history is shown without following rename or copy history of
3320 3318 files. Use -f/--follow with a filename to follow history across
3321 3319 renames and copies. --follow without a filename will only show
3322 3320 ancestors or descendants of the starting revision.
3323 3321
3324 3322 By default this command prints revision number and changeset id,
3325 3323 tags, non-trivial parents, user, date and time, and a summary for
3326 3324 each commit. When the -v/--verbose switch is used, the list of
3327 3325 changed files and full commit message are shown.
3328 3326
3329 3327 With --graph the revisions are shown as an ASCII art DAG with the most
3330 3328 recent changeset at the top.
3331 3329 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3332 3330 and '+' represents a fork where the changeset from the lines below is a
3333 3331 parent of the 'o' merge on the same line.
3334 3332
3335 3333 .. note::
3336 3334
3337 3335 :hg:`log --patch` may generate unexpected diff output for merge
3338 3336 changesets, as it will only compare the merge changeset against
3339 3337 its first parent. Also, only files different from BOTH parents
3340 3338 will appear in files:.
3341 3339
3342 3340 .. note::
3343 3341
3344 3342 For performance reasons, :hg:`log FILE` may omit duplicate changes
3345 3343 made on branches and will not show removals or mode changes. To
3346 3344 see all such changes, use the --removed switch.
3347 3345
3348 3346 .. container:: verbose
3349 3347
3350 3348 Some examples:
3351 3349
3352 3350 - changesets with full descriptions and file lists::
3353 3351
3354 3352 hg log -v
3355 3353
3356 3354 - changesets ancestral to the working directory::
3357 3355
3358 3356 hg log -f
3359 3357
3360 3358 - last 10 commits on the current branch::
3361 3359
3362 3360 hg log -l 10 -b .
3363 3361
3364 3362 - changesets showing all modifications of a file, including removals::
3365 3363
3366 3364 hg log --removed file.c
3367 3365
3368 3366 - all changesets that touch a directory, with diffs, excluding merges::
3369 3367
3370 3368 hg log -Mp lib/
3371 3369
3372 3370 - all revision numbers that match a keyword::
3373 3371
3374 3372 hg log -k bug --template "{rev}\\n"
3375 3373
3376 3374 - the full hash identifier of the working directory parent::
3377 3375
3378 3376 hg log -r . --template "{node}\\n"
3379 3377
3380 3378 - list available log templates::
3381 3379
3382 3380 hg log -T list
3383 3381
3384 3382 - check if a given changeset is included in a tagged release::
3385 3383
3386 3384 hg log -r "a21ccf and ancestor(1.9)"
3387 3385
3388 3386 - find all changesets by some user in a date range::
3389 3387
3390 3388 hg log -k alice -d "may 2008 to jul 2008"
3391 3389
3392 3390 - summary of all changesets after the last tag::
3393 3391
3394 3392 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3395 3393
3396 3394 See :hg:`help dates` for a list of formats valid for -d/--date.
3397 3395
3398 3396 See :hg:`help revisions` for more about specifying and ordering
3399 3397 revisions.
3400 3398
3401 3399 See :hg:`help templates` for more about pre-packaged styles and
3402 3400 specifying custom templates.
3403 3401
3404 3402 Returns 0 on success.
3405 3403
3406 3404 """
3407 3405 opts = pycompat.byteskwargs(opts)
3408 3406 if opts.get('follow') and opts.get('rev'):
3409 3407 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3410 3408 del opts['follow']
3411 3409
3412 3410 if opts.get('graph'):
3413 3411 return cmdutil.graphlog(ui, repo, pats, opts)
3414 3412
3415 3413 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3416 3414 limit = cmdutil.loglimit(opts)
3417 3415 count = 0
3418 3416
3419 3417 getrenamed = None
3420 3418 if opts.get('copies'):
3421 3419 endrev = None
3422 3420 if opts.get('rev'):
3423 3421 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3424 3422 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3425 3423
3426 3424 ui.pager('log')
3427 3425 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3428 3426 for rev in revs:
3429 3427 if count == limit:
3430 3428 break
3431 3429 ctx = repo[rev]
3432 3430 copies = None
3433 3431 if getrenamed is not None and rev:
3434 3432 copies = []
3435 3433 for fn in ctx.files():
3436 3434 rename = getrenamed(fn, rev)
3437 3435 if rename:
3438 3436 copies.append((fn, rename[0]))
3439 3437 if filematcher:
3440 3438 revmatchfn = filematcher(ctx.rev())
3441 3439 else:
3442 3440 revmatchfn = None
3443 3441 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3444 3442 if displayer.flush(ctx):
3445 3443 count += 1
3446 3444
3447 3445 displayer.close()
3448 3446
3449 3447 @command('manifest',
3450 3448 [('r', 'rev', '', _('revision to display'), _('REV')),
3451 3449 ('', 'all', False, _("list files from all revisions"))]
3452 3450 + formatteropts,
3453 3451 _('[-r REV]'))
3454 3452 def manifest(ui, repo, node=None, rev=None, **opts):
3455 3453 """output the current or given revision of the project manifest
3456 3454
3457 3455 Print a list of version controlled files for the given revision.
3458 3456 If no revision is given, the first parent of the working directory
3459 3457 is used, or the null revision if no revision is checked out.
3460 3458
3461 3459 With -v, print file permissions, symlink and executable bits.
3462 3460 With --debug, print file revision hashes.
3463 3461
3464 3462 If option --all is specified, the list of all files from all revisions
3465 3463 is printed. This includes deleted and renamed files.
3466 3464
3467 3465 Returns 0 on success.
3468 3466 """
3469 3467 fm = ui.formatter('manifest', opts)
3470 3468
3471 3469 if opts.get('all'):
3472 3470 if rev or node:
3473 3471 raise error.Abort(_("can't specify a revision with --all"))
3474 3472
3475 3473 res = []
3476 3474 prefix = "data/"
3477 3475 suffix = ".i"
3478 3476 plen = len(prefix)
3479 3477 slen = len(suffix)
3480 3478 with repo.lock():
3481 3479 for fn, b, size in repo.store.datafiles():
3482 3480 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3483 3481 res.append(fn[plen:-slen])
3484 3482 ui.pager('manifest')
3485 3483 for f in res:
3486 3484 fm.startitem()
3487 3485 fm.write("path", '%s\n', f)
3488 3486 fm.end()
3489 3487 return
3490 3488
3491 3489 if rev and node:
3492 3490 raise error.Abort(_("please specify just one revision"))
3493 3491
3494 3492 if not node:
3495 3493 node = rev
3496 3494
3497 3495 char = {'l': '@', 'x': '*', '': ''}
3498 3496 mode = {'l': '644', 'x': '755', '': '644'}
3499 3497 ctx = scmutil.revsingle(repo, node)
3500 3498 mf = ctx.manifest()
3501 3499 ui.pager('manifest')
3502 3500 for f in ctx:
3503 3501 fm.startitem()
3504 3502 fl = ctx[f].flags()
3505 3503 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3506 3504 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3507 3505 fm.write('path', '%s\n', f)
3508 3506 fm.end()
3509 3507
3510 3508 @command('^merge',
3511 3509 [('f', 'force', None,
3512 3510 _('force a merge including outstanding changes (DEPRECATED)')),
3513 3511 ('r', 'rev', '', _('revision to merge'), _('REV')),
3514 3512 ('P', 'preview', None,
3515 3513 _('review revisions to merge (no merge is performed)'))
3516 3514 ] + mergetoolopts,
3517 3515 _('[-P] [[-r] REV]'))
3518 3516 def merge(ui, repo, node=None, **opts):
3519 3517 """merge another revision into working directory
3520 3518
3521 3519 The current working directory is updated with all changes made in
3522 3520 the requested revision since the last common predecessor revision.
3523 3521
3524 3522 Files that changed between either parent are marked as changed for
3525 3523 the next commit and a commit must be performed before any further
3526 3524 updates to the repository are allowed. The next commit will have
3527 3525 two parents.
3528 3526
3529 3527 ``--tool`` can be used to specify the merge tool used for file
3530 3528 merges. It overrides the HGMERGE environment variable and your
3531 3529 configuration files. See :hg:`help merge-tools` for options.
3532 3530
3533 3531 If no revision is specified, the working directory's parent is a
3534 3532 head revision, and the current branch contains exactly one other
3535 3533 head, the other head is merged with by default. Otherwise, an
3536 3534 explicit revision with which to merge with must be provided.
3537 3535
3538 3536 See :hg:`help resolve` for information on handling file conflicts.
3539 3537
3540 3538 To undo an uncommitted merge, use :hg:`update --clean .` which
3541 3539 will check out a clean copy of the original merge parent, losing
3542 3540 all changes.
3543 3541
3544 3542 Returns 0 on success, 1 if there are unresolved files.
3545 3543 """
3546 3544
3547 3545 if opts.get('rev') and node:
3548 3546 raise error.Abort(_("please specify just one revision"))
3549 3547 if not node:
3550 3548 node = opts.get('rev')
3551 3549
3552 3550 if node:
3553 3551 node = scmutil.revsingle(repo, node).node()
3554 3552
3555 3553 if not node:
3556 3554 node = repo[destutil.destmerge(repo)].node()
3557 3555
3558 3556 if opts.get('preview'):
3559 3557 # find nodes that are ancestors of p2 but not of p1
3560 3558 p1 = repo.lookup('.')
3561 3559 p2 = repo.lookup(node)
3562 3560 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3563 3561
3564 3562 displayer = cmdutil.show_changeset(ui, repo, opts)
3565 3563 for node in nodes:
3566 3564 displayer.show(repo[node])
3567 3565 displayer.close()
3568 3566 return 0
3569 3567
3570 3568 try:
3571 3569 # ui.forcemerge is an internal variable, do not document
3572 3570 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3573 3571 force = opts.get('force')
3574 3572 labels = ['working copy', 'merge rev']
3575 3573 return hg.merge(repo, node, force=force, mergeforce=force,
3576 3574 labels=labels)
3577 3575 finally:
3578 3576 ui.setconfig('ui', 'forcemerge', '', 'merge')
3579 3577
3580 3578 @command('outgoing|out',
3581 3579 [('f', 'force', None, _('run even when the destination is unrelated')),
3582 3580 ('r', 'rev', [],
3583 3581 _('a changeset intended to be included in the destination'), _('REV')),
3584 3582 ('n', 'newest-first', None, _('show newest record first')),
3585 3583 ('B', 'bookmarks', False, _('compare bookmarks')),
3586 3584 ('b', 'branch', [], _('a specific branch you would like to push'),
3587 3585 _('BRANCH')),
3588 3586 ] + logopts + remoteopts + subrepoopts,
3589 3587 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3590 3588 def outgoing(ui, repo, dest=None, **opts):
3591 3589 """show changesets not found in the destination
3592 3590
3593 3591 Show changesets not found in the specified destination repository
3594 3592 or the default push location. These are the changesets that would
3595 3593 be pushed if a push was requested.
3596 3594
3597 3595 See pull for details of valid destination formats.
3598 3596
3599 3597 .. container:: verbose
3600 3598
3601 3599 With -B/--bookmarks, the result of bookmark comparison between
3602 3600 local and remote repositories is displayed. With -v/--verbose,
3603 3601 status is also displayed for each bookmark like below::
3604 3602
3605 3603 BM1 01234567890a added
3606 3604 BM2 deleted
3607 3605 BM3 234567890abc advanced
3608 3606 BM4 34567890abcd diverged
3609 3607 BM5 4567890abcde changed
3610 3608
3611 3609 The action taken when pushing depends on the
3612 3610 status of each bookmark:
3613 3611
3614 3612 :``added``: push with ``-B`` will create it
3615 3613 :``deleted``: push with ``-B`` will delete it
3616 3614 :``advanced``: push will update it
3617 3615 :``diverged``: push with ``-B`` will update it
3618 3616 :``changed``: push with ``-B`` will update it
3619 3617
3620 3618 From the point of view of pushing behavior, bookmarks
3621 3619 existing only in the remote repository are treated as
3622 3620 ``deleted``, even if it is in fact added remotely.
3623 3621
3624 3622 Returns 0 if there are outgoing changes, 1 otherwise.
3625 3623 """
3626 3624 if opts.get('graph'):
3627 3625 cmdutil.checkunsupportedgraphflags([], opts)
3628 3626 o, other = hg._outgoing(ui, repo, dest, opts)
3629 3627 if not o:
3630 3628 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3631 3629 return
3632 3630
3633 3631 revdag = cmdutil.graphrevs(repo, o, opts)
3634 3632 ui.pager('outgoing')
3635 3633 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3636 3634 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3637 3635 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3638 3636 return 0
3639 3637
3640 3638 if opts.get('bookmarks'):
3641 3639 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3642 3640 dest, branches = hg.parseurl(dest, opts.get('branch'))
3643 3641 other = hg.peer(repo, opts, dest)
3644 3642 if 'bookmarks' not in other.listkeys('namespaces'):
3645 3643 ui.warn(_("remote doesn't support bookmarks\n"))
3646 3644 return 0
3647 3645 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3648 3646 ui.pager('outgoing')
3649 3647 return bookmarks.outgoing(ui, repo, other)
3650 3648
3651 3649 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3652 3650 try:
3653 3651 return hg.outgoing(ui, repo, dest, opts)
3654 3652 finally:
3655 3653 del repo._subtoppath
3656 3654
3657 3655 @command('parents',
3658 3656 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3659 3657 ] + templateopts,
3660 3658 _('[-r REV] [FILE]'),
3661 3659 inferrepo=True)
3662 3660 def parents(ui, repo, file_=None, **opts):
3663 3661 """show the parents of the working directory or revision (DEPRECATED)
3664 3662
3665 3663 Print the working directory's parent revisions. If a revision is
3666 3664 given via -r/--rev, the parent of that revision will be printed.
3667 3665 If a file argument is given, the revision in which the file was
3668 3666 last changed (before the working directory revision or the
3669 3667 argument to --rev if given) is printed.
3670 3668
3671 3669 This command is equivalent to::
3672 3670
3673 3671 hg log -r "p1()+p2()" or
3674 3672 hg log -r "p1(REV)+p2(REV)" or
3675 3673 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3676 3674 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3677 3675
3678 3676 See :hg:`summary` and :hg:`help revsets` for related information.
3679 3677
3680 3678 Returns 0 on success.
3681 3679 """
3682 3680
3683 3681 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3684 3682
3685 3683 if file_:
3686 3684 m = scmutil.match(ctx, (file_,), opts)
3687 3685 if m.anypats() or len(m.files()) != 1:
3688 3686 raise error.Abort(_('can only specify an explicit filename'))
3689 3687 file_ = m.files()[0]
3690 3688 filenodes = []
3691 3689 for cp in ctx.parents():
3692 3690 if not cp:
3693 3691 continue
3694 3692 try:
3695 3693 filenodes.append(cp.filenode(file_))
3696 3694 except error.LookupError:
3697 3695 pass
3698 3696 if not filenodes:
3699 3697 raise error.Abort(_("'%s' not found in manifest!") % file_)
3700 3698 p = []
3701 3699 for fn in filenodes:
3702 3700 fctx = repo.filectx(file_, fileid=fn)
3703 3701 p.append(fctx.node())
3704 3702 else:
3705 3703 p = [cp.node() for cp in ctx.parents()]
3706 3704
3707 3705 displayer = cmdutil.show_changeset(ui, repo, opts)
3708 3706 for n in p:
3709 3707 if n != nullid:
3710 3708 displayer.show(repo[n])
3711 3709 displayer.close()
3712 3710
3713 3711 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3714 3712 def paths(ui, repo, search=None, **opts):
3715 3713 """show aliases for remote repositories
3716 3714
3717 3715 Show definition of symbolic path name NAME. If no name is given,
3718 3716 show definition of all available names.
3719 3717
3720 3718 Option -q/--quiet suppresses all output when searching for NAME
3721 3719 and shows only the path names when listing all definitions.
3722 3720
3723 3721 Path names are defined in the [paths] section of your
3724 3722 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3725 3723 repository, ``.hg/hgrc`` is used, too.
3726 3724
3727 3725 The path names ``default`` and ``default-push`` have a special
3728 3726 meaning. When performing a push or pull operation, they are used
3729 3727 as fallbacks if no location is specified on the command-line.
3730 3728 When ``default-push`` is set, it will be used for push and
3731 3729 ``default`` will be used for pull; otherwise ``default`` is used
3732 3730 as the fallback for both. When cloning a repository, the clone
3733 3731 source is written as ``default`` in ``.hg/hgrc``.
3734 3732
3735 3733 .. note::
3736 3734
3737 3735 ``default`` and ``default-push`` apply to all inbound (e.g.
3738 3736 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3739 3737 and :hg:`bundle`) operations.
3740 3738
3741 3739 See :hg:`help urls` for more information.
3742 3740
3743 3741 Returns 0 on success.
3744 3742 """
3745 3743 ui.pager('paths')
3746 3744 if search:
3747 3745 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3748 3746 if name == search]
3749 3747 else:
3750 3748 pathitems = sorted(ui.paths.iteritems())
3751 3749
3752 3750 fm = ui.formatter('paths', opts)
3753 3751 if fm.isplain():
3754 3752 hidepassword = util.hidepassword
3755 3753 else:
3756 3754 hidepassword = str
3757 3755 if ui.quiet:
3758 3756 namefmt = '%s\n'
3759 3757 else:
3760 3758 namefmt = '%s = '
3761 3759 showsubopts = not search and not ui.quiet
3762 3760
3763 3761 for name, path in pathitems:
3764 3762 fm.startitem()
3765 3763 fm.condwrite(not search, 'name', namefmt, name)
3766 3764 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3767 3765 for subopt, value in sorted(path.suboptions.items()):
3768 3766 assert subopt not in ('name', 'url')
3769 3767 if showsubopts:
3770 3768 fm.plain('%s:%s = ' % (name, subopt))
3771 3769 fm.condwrite(showsubopts, subopt, '%s\n', value)
3772 3770
3773 3771 fm.end()
3774 3772
3775 3773 if search and not pathitems:
3776 3774 if not ui.quiet:
3777 3775 ui.warn(_("not found!\n"))
3778 3776 return 1
3779 3777 else:
3780 3778 return 0
3781 3779
3782 3780 @command('phase',
3783 3781 [('p', 'public', False, _('set changeset phase to public')),
3784 3782 ('d', 'draft', False, _('set changeset phase to draft')),
3785 3783 ('s', 'secret', False, _('set changeset phase to secret')),
3786 3784 ('f', 'force', False, _('allow to move boundary backward')),
3787 3785 ('r', 'rev', [], _('target revision'), _('REV')),
3788 3786 ],
3789 3787 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3790 3788 def phase(ui, repo, *revs, **opts):
3791 3789 """set or show the current phase name
3792 3790
3793 3791 With no argument, show the phase name of the current revision(s).
3794 3792
3795 3793 With one of -p/--public, -d/--draft or -s/--secret, change the
3796 3794 phase value of the specified revisions.
3797 3795
3798 3796 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3799 3797 lower phase to an higher phase. Phases are ordered as follows::
3800 3798
3801 3799 public < draft < secret
3802 3800
3803 3801 Returns 0 on success, 1 if some phases could not be changed.
3804 3802
3805 3803 (For more information about the phases concept, see :hg:`help phases`.)
3806 3804 """
3807 3805 # search for a unique phase argument
3808 3806 targetphase = None
3809 3807 for idx, name in enumerate(phases.phasenames):
3810 3808 if opts[name]:
3811 3809 if targetphase is not None:
3812 3810 raise error.Abort(_('only one phase can be specified'))
3813 3811 targetphase = idx
3814 3812
3815 3813 # look for specified revision
3816 3814 revs = list(revs)
3817 3815 revs.extend(opts['rev'])
3818 3816 if not revs:
3819 3817 # display both parents as the second parent phase can influence
3820 3818 # the phase of a merge commit
3821 3819 revs = [c.rev() for c in repo[None].parents()]
3822 3820
3823 3821 revs = scmutil.revrange(repo, revs)
3824 3822
3825 3823 lock = None
3826 3824 ret = 0
3827 3825 if targetphase is None:
3828 3826 # display
3829 3827 for r in revs:
3830 3828 ctx = repo[r]
3831 3829 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3832 3830 else:
3833 3831 tr = None
3834 3832 lock = repo.lock()
3835 3833 try:
3836 3834 tr = repo.transaction("phase")
3837 3835 # set phase
3838 3836 if not revs:
3839 3837 raise error.Abort(_('empty revision set'))
3840 3838 nodes = [repo[r].node() for r in revs]
3841 3839 # moving revision from public to draft may hide them
3842 3840 # We have to check result on an unfiltered repository
3843 3841 unfi = repo.unfiltered()
3844 3842 getphase = unfi._phasecache.phase
3845 3843 olddata = [getphase(unfi, r) for r in unfi]
3846 3844 phases.advanceboundary(repo, tr, targetphase, nodes)
3847 3845 if opts['force']:
3848 3846 phases.retractboundary(repo, tr, targetphase, nodes)
3849 3847 tr.close()
3850 3848 finally:
3851 3849 if tr is not None:
3852 3850 tr.release()
3853 3851 lock.release()
3854 3852 getphase = unfi._phasecache.phase
3855 3853 newdata = [getphase(unfi, r) for r in unfi]
3856 3854 changes = sum(newdata[r] != olddata[r] for r in unfi)
3857 3855 cl = unfi.changelog
3858 3856 rejected = [n for n in nodes
3859 3857 if newdata[cl.rev(n)] < targetphase]
3860 3858 if rejected:
3861 3859 ui.warn(_('cannot move %i changesets to a higher '
3862 3860 'phase, use --force\n') % len(rejected))
3863 3861 ret = 1
3864 3862 if changes:
3865 3863 msg = _('phase changed for %i changesets\n') % changes
3866 3864 if ret:
3867 3865 ui.status(msg)
3868 3866 else:
3869 3867 ui.note(msg)
3870 3868 else:
3871 3869 ui.warn(_('no phases changed\n'))
3872 3870 return ret
3873 3871
3874 3872 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3875 3873 """Run after a changegroup has been added via pull/unbundle
3876 3874
3877 3875 This takes arguments below:
3878 3876
3879 3877 :modheads: change of heads by pull/unbundle
3880 3878 :optupdate: updating working directory is needed or not
3881 3879 :checkout: update destination revision (or None to default destination)
3882 3880 :brev: a name, which might be a bookmark to be activated after updating
3883 3881 """
3884 3882 if modheads == 0:
3885 3883 return
3886 3884 if optupdate:
3887 3885 try:
3888 3886 return hg.updatetotally(ui, repo, checkout, brev)
3889 3887 except error.UpdateAbort as inst:
3890 3888 msg = _("not updating: %s") % str(inst)
3891 3889 hint = inst.hint
3892 3890 raise error.UpdateAbort(msg, hint=hint)
3893 3891 if modheads > 1:
3894 3892 currentbranchheads = len(repo.branchheads())
3895 3893 if currentbranchheads == modheads:
3896 3894 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3897 3895 elif currentbranchheads > 1:
3898 3896 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3899 3897 "merge)\n"))
3900 3898 else:
3901 3899 ui.status(_("(run 'hg heads' to see heads)\n"))
3902 3900 else:
3903 3901 ui.status(_("(run 'hg update' to get a working copy)\n"))
3904 3902
3905 3903 @command('^pull',
3906 3904 [('u', 'update', None,
3907 3905 _('update to new branch head if changesets were pulled')),
3908 3906 ('f', 'force', None, _('run even when remote repository is unrelated')),
3909 3907 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3910 3908 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3911 3909 ('b', 'branch', [], _('a specific branch you would like to pull'),
3912 3910 _('BRANCH')),
3913 3911 ] + remoteopts,
3914 3912 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3915 3913 def pull(ui, repo, source="default", **opts):
3916 3914 """pull changes from the specified source
3917 3915
3918 3916 Pull changes from a remote repository to a local one.
3919 3917
3920 3918 This finds all changes from the repository at the specified path
3921 3919 or URL and adds them to a local repository (the current one unless
3922 3920 -R is specified). By default, this does not update the copy of the
3923 3921 project in the working directory.
3924 3922
3925 3923 Use :hg:`incoming` if you want to see what would have been added
3926 3924 by a pull at the time you issued this command. If you then decide
3927 3925 to add those changes to the repository, you should use :hg:`pull
3928 3926 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3929 3927
3930 3928 If SOURCE is omitted, the 'default' path will be used.
3931 3929 See :hg:`help urls` for more information.
3932 3930
3933 3931 Specifying bookmark as ``.`` is equivalent to specifying the active
3934 3932 bookmark's name.
3935 3933
3936 3934 Returns 0 on success, 1 if an update had unresolved files.
3937 3935 """
3938 3936 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3939 3937 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3940 3938 other = hg.peer(repo, opts, source)
3941 3939 try:
3942 3940 revs, checkout = hg.addbranchrevs(repo, other, branches,
3943 3941 opts.get('rev'))
3944 3942
3945 3943
3946 3944 pullopargs = {}
3947 3945 if opts.get('bookmark'):
3948 3946 if not revs:
3949 3947 revs = []
3950 3948 # The list of bookmark used here is not the one used to actually
3951 3949 # update the bookmark name. This can result in the revision pulled
3952 3950 # not ending up with the name of the bookmark because of a race
3953 3951 # condition on the server. (See issue 4689 for details)
3954 3952 remotebookmarks = other.listkeys('bookmarks')
3955 3953 pullopargs['remotebookmarks'] = remotebookmarks
3956 3954 for b in opts['bookmark']:
3957 3955 b = repo._bookmarks.expandname(b)
3958 3956 if b not in remotebookmarks:
3959 3957 raise error.Abort(_('remote bookmark %s not found!') % b)
3960 3958 revs.append(remotebookmarks[b])
3961 3959
3962 3960 if revs:
3963 3961 try:
3964 3962 # When 'rev' is a bookmark name, we cannot guarantee that it
3965 3963 # will be updated with that name because of a race condition
3966 3964 # server side. (See issue 4689 for details)
3967 3965 oldrevs = revs
3968 3966 revs = [] # actually, nodes
3969 3967 for r in oldrevs:
3970 3968 node = other.lookup(r)
3971 3969 revs.append(node)
3972 3970 if r == checkout:
3973 3971 checkout = node
3974 3972 except error.CapabilityError:
3975 3973 err = _("other repository doesn't support revision lookup, "
3976 3974 "so a rev cannot be specified.")
3977 3975 raise error.Abort(err)
3978 3976
3979 3977 pullopargs.update(opts.get('opargs', {}))
3980 3978 modheads = exchange.pull(repo, other, heads=revs,
3981 3979 force=opts.get('force'),
3982 3980 bookmarks=opts.get('bookmark', ()),
3983 3981 opargs=pullopargs).cgresult
3984 3982
3985 3983 # brev is a name, which might be a bookmark to be activated at
3986 3984 # the end of the update. In other words, it is an explicit
3987 3985 # destination of the update
3988 3986 brev = None
3989 3987
3990 3988 if checkout:
3991 3989 checkout = str(repo.changelog.rev(checkout))
3992 3990
3993 3991 # order below depends on implementation of
3994 3992 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3995 3993 # because 'checkout' is determined without it.
3996 3994 if opts.get('rev'):
3997 3995 brev = opts['rev'][0]
3998 3996 elif opts.get('branch'):
3999 3997 brev = opts['branch'][0]
4000 3998 else:
4001 3999 brev = branches[0]
4002 4000 repo._subtoppath = source
4003 4001 try:
4004 4002 ret = postincoming(ui, repo, modheads, opts.get('update'),
4005 4003 checkout, brev)
4006 4004
4007 4005 finally:
4008 4006 del repo._subtoppath
4009 4007
4010 4008 finally:
4011 4009 other.close()
4012 4010 return ret
4013 4011
4014 4012 @command('^push',
4015 4013 [('f', 'force', None, _('force push')),
4016 4014 ('r', 'rev', [],
4017 4015 _('a changeset intended to be included in the destination'),
4018 4016 _('REV')),
4019 4017 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4020 4018 ('b', 'branch', [],
4021 4019 _('a specific branch you would like to push'), _('BRANCH')),
4022 4020 ('', 'new-branch', False, _('allow pushing a new branch')),
4023 4021 ] + remoteopts,
4024 4022 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4025 4023 def push(ui, repo, dest=None, **opts):
4026 4024 """push changes to the specified destination
4027 4025
4028 4026 Push changesets from the local repository to the specified
4029 4027 destination.
4030 4028
4031 4029 This operation is symmetrical to pull: it is identical to a pull
4032 4030 in the destination repository from the current one.
4033 4031
4034 4032 By default, push will not allow creation of new heads at the
4035 4033 destination, since multiple heads would make it unclear which head
4036 4034 to use. In this situation, it is recommended to pull and merge
4037 4035 before pushing.
4038 4036
4039 4037 Use --new-branch if you want to allow push to create a new named
4040 4038 branch that is not present at the destination. This allows you to
4041 4039 only create a new branch without forcing other changes.
4042 4040
4043 4041 .. note::
4044 4042
4045 4043 Extra care should be taken with the -f/--force option,
4046 4044 which will push all new heads on all branches, an action which will
4047 4045 almost always cause confusion for collaborators.
4048 4046
4049 4047 If -r/--rev is used, the specified revision and all its ancestors
4050 4048 will be pushed to the remote repository.
4051 4049
4052 4050 If -B/--bookmark is used, the specified bookmarked revision, its
4053 4051 ancestors, and the bookmark will be pushed to the remote
4054 4052 repository. Specifying ``.`` is equivalent to specifying the active
4055 4053 bookmark's name.
4056 4054
4057 4055 Please see :hg:`help urls` for important details about ``ssh://``
4058 4056 URLs. If DESTINATION is omitted, a default path will be used.
4059 4057
4060 4058 Returns 0 if push was successful, 1 if nothing to push.
4061 4059 """
4062 4060
4063 4061 if opts.get('bookmark'):
4064 4062 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4065 4063 for b in opts['bookmark']:
4066 4064 # translate -B options to -r so changesets get pushed
4067 4065 b = repo._bookmarks.expandname(b)
4068 4066 if b in repo._bookmarks:
4069 4067 opts.setdefault('rev', []).append(b)
4070 4068 else:
4071 4069 # if we try to push a deleted bookmark, translate it to null
4072 4070 # this lets simultaneous -r, -b options continue working
4073 4071 opts.setdefault('rev', []).append("null")
4074 4072
4075 4073 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4076 4074 if not path:
4077 4075 raise error.Abort(_('default repository not configured!'),
4078 4076 hint=_("see 'hg help config.paths'"))
4079 4077 dest = path.pushloc or path.loc
4080 4078 branches = (path.branch, opts.get('branch') or [])
4081 4079 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4082 4080 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4083 4081 other = hg.peer(repo, opts, dest)
4084 4082
4085 4083 if revs:
4086 4084 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4087 4085 if not revs:
4088 4086 raise error.Abort(_("specified revisions evaluate to an empty set"),
4089 4087 hint=_("use different revision arguments"))
4090 4088 elif path.pushrev:
4091 4089 # It doesn't make any sense to specify ancestor revisions. So limit
4092 4090 # to DAG heads to make discovery simpler.
4093 4091 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4094 4092 revs = scmutil.revrange(repo, [expr])
4095 4093 revs = [repo[rev].node() for rev in revs]
4096 4094 if not revs:
4097 4095 raise error.Abort(_('default push revset for path evaluates to an '
4098 4096 'empty set'))
4099 4097
4100 4098 repo._subtoppath = dest
4101 4099 try:
4102 4100 # push subrepos depth-first for coherent ordering
4103 4101 c = repo['']
4104 4102 subs = c.substate # only repos that are committed
4105 4103 for s in sorted(subs):
4106 4104 result = c.sub(s).push(opts)
4107 4105 if result == 0:
4108 4106 return not result
4109 4107 finally:
4110 4108 del repo._subtoppath
4111 4109 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4112 4110 newbranch=opts.get('new_branch'),
4113 4111 bookmarks=opts.get('bookmark', ()),
4114 4112 opargs=opts.get('opargs'))
4115 4113
4116 4114 result = not pushop.cgresult
4117 4115
4118 4116 if pushop.bkresult is not None:
4119 4117 if pushop.bkresult == 2:
4120 4118 result = 2
4121 4119 elif not result and pushop.bkresult:
4122 4120 result = 2
4123 4121
4124 4122 return result
4125 4123
4126 4124 @command('recover', [])
4127 4125 def recover(ui, repo):
4128 4126 """roll back an interrupted transaction
4129 4127
4130 4128 Recover from an interrupted commit or pull.
4131 4129
4132 4130 This command tries to fix the repository status after an
4133 4131 interrupted operation. It should only be necessary when Mercurial
4134 4132 suggests it.
4135 4133
4136 4134 Returns 0 if successful, 1 if nothing to recover or verify fails.
4137 4135 """
4138 4136 if repo.recover():
4139 4137 return hg.verify(repo)
4140 4138 return 1
4141 4139
4142 4140 @command('^remove|rm',
4143 4141 [('A', 'after', None, _('record delete for missing files')),
4144 4142 ('f', 'force', None,
4145 4143 _('forget added files, delete modified files')),
4146 4144 ] + subrepoopts + walkopts,
4147 4145 _('[OPTION]... FILE...'),
4148 4146 inferrepo=True)
4149 4147 def remove(ui, repo, *pats, **opts):
4150 4148 """remove the specified files on the next commit
4151 4149
4152 4150 Schedule the indicated files for removal from the current branch.
4153 4151
4154 4152 This command schedules the files to be removed at the next commit.
4155 4153 To undo a remove before that, see :hg:`revert`. To undo added
4156 4154 files, see :hg:`forget`.
4157 4155
4158 4156 .. container:: verbose
4159 4157
4160 4158 -A/--after can be used to remove only files that have already
4161 4159 been deleted, -f/--force can be used to force deletion, and -Af
4162 4160 can be used to remove files from the next revision without
4163 4161 deleting them from the working directory.
4164 4162
4165 4163 The following table details the behavior of remove for different
4166 4164 file states (columns) and option combinations (rows). The file
4167 4165 states are Added [A], Clean [C], Modified [M] and Missing [!]
4168 4166 (as reported by :hg:`status`). The actions are Warn, Remove
4169 4167 (from branch) and Delete (from disk):
4170 4168
4171 4169 ========= == == == ==
4172 4170 opt/state A C M !
4173 4171 ========= == == == ==
4174 4172 none W RD W R
4175 4173 -f R RD RD R
4176 4174 -A W W W R
4177 4175 -Af R R R R
4178 4176 ========= == == == ==
4179 4177
4180 4178 .. note::
4181 4179
4182 4180 :hg:`remove` never deletes files in Added [A] state from the
4183 4181 working directory, not even if ``--force`` is specified.
4184 4182
4185 4183 Returns 0 on success, 1 if any warnings encountered.
4186 4184 """
4187 4185
4188 4186 after, force = opts.get('after'), opts.get('force')
4189 4187 if not pats and not after:
4190 4188 raise error.Abort(_('no files specified'))
4191 4189
4192 4190 m = scmutil.match(repo[None], pats, opts)
4193 4191 subrepos = opts.get('subrepos')
4194 4192 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4195 4193
4196 4194 @command('rename|move|mv',
4197 4195 [('A', 'after', None, _('record a rename that has already occurred')),
4198 4196 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4199 4197 ] + walkopts + dryrunopts,
4200 4198 _('[OPTION]... SOURCE... DEST'))
4201 4199 def rename(ui, repo, *pats, **opts):
4202 4200 """rename files; equivalent of copy + remove
4203 4201
4204 4202 Mark dest as copies of sources; mark sources for deletion. If dest
4205 4203 is a directory, copies are put in that directory. If dest is a
4206 4204 file, there can only be one source.
4207 4205
4208 4206 By default, this command copies the contents of files as they
4209 4207 exist in the working directory. If invoked with -A/--after, the
4210 4208 operation is recorded, but no copying is performed.
4211 4209
4212 4210 This command takes effect at the next commit. To undo a rename
4213 4211 before that, see :hg:`revert`.
4214 4212
4215 4213 Returns 0 on success, 1 if errors are encountered.
4216 4214 """
4217 4215 with repo.wlock(False):
4218 4216 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4219 4217
4220 4218 @command('resolve',
4221 4219 [('a', 'all', None, _('select all unresolved files')),
4222 4220 ('l', 'list', None, _('list state of files needing merge')),
4223 4221 ('m', 'mark', None, _('mark files as resolved')),
4224 4222 ('u', 'unmark', None, _('mark files as unresolved')),
4225 4223 ('n', 'no-status', None, _('hide status prefix'))]
4226 4224 + mergetoolopts + walkopts + formatteropts,
4227 4225 _('[OPTION]... [FILE]...'),
4228 4226 inferrepo=True)
4229 4227 def resolve(ui, repo, *pats, **opts):
4230 4228 """redo merges or set/view the merge status of files
4231 4229
4232 4230 Merges with unresolved conflicts are often the result of
4233 4231 non-interactive merging using the ``internal:merge`` configuration
4234 4232 setting, or a command-line merge tool like ``diff3``. The resolve
4235 4233 command is used to manage the files involved in a merge, after
4236 4234 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4237 4235 working directory must have two parents). See :hg:`help
4238 4236 merge-tools` for information on configuring merge tools.
4239 4237
4240 4238 The resolve command can be used in the following ways:
4241 4239
4242 4240 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4243 4241 files, discarding any previous merge attempts. Re-merging is not
4244 4242 performed for files already marked as resolved. Use ``--all/-a``
4245 4243 to select all unresolved files. ``--tool`` can be used to specify
4246 4244 the merge tool used for the given files. It overrides the HGMERGE
4247 4245 environment variable and your configuration files. Previous file
4248 4246 contents are saved with a ``.orig`` suffix.
4249 4247
4250 4248 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4251 4249 (e.g. after having manually fixed-up the files). The default is
4252 4250 to mark all unresolved files.
4253 4251
4254 4252 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4255 4253 default is to mark all resolved files.
4256 4254
4257 4255 - :hg:`resolve -l`: list files which had or still have conflicts.
4258 4256 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4259 4257 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4260 4258 the list. See :hg:`help filesets` for details.
4261 4259
4262 4260 .. note::
4263 4261
4264 4262 Mercurial will not let you commit files with unresolved merge
4265 4263 conflicts. You must use :hg:`resolve -m ...` before you can
4266 4264 commit after a conflicting merge.
4267 4265
4268 4266 Returns 0 on success, 1 if any files fail a resolve attempt.
4269 4267 """
4270 4268
4271 4269 flaglist = 'all mark unmark list no_status'.split()
4272 4270 all, mark, unmark, show, nostatus = \
4273 4271 [opts.get(o) for o in flaglist]
4274 4272
4275 4273 if (show and (mark or unmark)) or (mark and unmark):
4276 4274 raise error.Abort(_("too many options specified"))
4277 4275 if pats and all:
4278 4276 raise error.Abort(_("can't specify --all and patterns"))
4279 4277 if not (all or pats or show or mark or unmark):
4280 4278 raise error.Abort(_('no files or directories specified'),
4281 4279 hint=('use --all to re-merge all unresolved files'))
4282 4280
4283 4281 if show:
4284 4282 ui.pager('resolve')
4285 4283 fm = ui.formatter('resolve', opts)
4286 4284 ms = mergemod.mergestate.read(repo)
4287 4285 m = scmutil.match(repo[None], pats, opts)
4288 4286 for f in ms:
4289 4287 if not m(f):
4290 4288 continue
4291 4289 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4292 4290 'd': 'driverresolved'}[ms[f]]
4293 4291 fm.startitem()
4294 4292 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4295 4293 fm.write('path', '%s\n', f, label=l)
4296 4294 fm.end()
4297 4295 return 0
4298 4296
4299 4297 with repo.wlock():
4300 4298 ms = mergemod.mergestate.read(repo)
4301 4299
4302 4300 if not (ms.active() or repo.dirstate.p2() != nullid):
4303 4301 raise error.Abort(
4304 4302 _('resolve command not applicable when not merging'))
4305 4303
4306 4304 wctx = repo[None]
4307 4305
4308 4306 if ms.mergedriver and ms.mdstate() == 'u':
4309 4307 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4310 4308 ms.commit()
4311 4309 # allow mark and unmark to go through
4312 4310 if not mark and not unmark and not proceed:
4313 4311 return 1
4314 4312
4315 4313 m = scmutil.match(wctx, pats, opts)
4316 4314 ret = 0
4317 4315 didwork = False
4318 4316 runconclude = False
4319 4317
4320 4318 tocomplete = []
4321 4319 for f in ms:
4322 4320 if not m(f):
4323 4321 continue
4324 4322
4325 4323 didwork = True
4326 4324
4327 4325 # don't let driver-resolved files be marked, and run the conclude
4328 4326 # step if asked to resolve
4329 4327 if ms[f] == "d":
4330 4328 exact = m.exact(f)
4331 4329 if mark:
4332 4330 if exact:
4333 4331 ui.warn(_('not marking %s as it is driver-resolved\n')
4334 4332 % f)
4335 4333 elif unmark:
4336 4334 if exact:
4337 4335 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4338 4336 % f)
4339 4337 else:
4340 4338 runconclude = True
4341 4339 continue
4342 4340
4343 4341 if mark:
4344 4342 ms.mark(f, "r")
4345 4343 elif unmark:
4346 4344 ms.mark(f, "u")
4347 4345 else:
4348 4346 # backup pre-resolve (merge uses .orig for its own purposes)
4349 4347 a = repo.wjoin(f)
4350 4348 try:
4351 4349 util.copyfile(a, a + ".resolve")
4352 4350 except (IOError, OSError) as inst:
4353 4351 if inst.errno != errno.ENOENT:
4354 4352 raise
4355 4353
4356 4354 try:
4357 4355 # preresolve file
4358 4356 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4359 4357 'resolve')
4360 4358 complete, r = ms.preresolve(f, wctx)
4361 4359 if not complete:
4362 4360 tocomplete.append(f)
4363 4361 elif r:
4364 4362 ret = 1
4365 4363 finally:
4366 4364 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4367 4365 ms.commit()
4368 4366
4369 4367 # replace filemerge's .orig file with our resolve file, but only
4370 4368 # for merges that are complete
4371 4369 if complete:
4372 4370 try:
4373 4371 util.rename(a + ".resolve",
4374 4372 scmutil.origpath(ui, repo, a))
4375 4373 except OSError as inst:
4376 4374 if inst.errno != errno.ENOENT:
4377 4375 raise
4378 4376
4379 4377 for f in tocomplete:
4380 4378 try:
4381 4379 # resolve file
4382 4380 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4383 4381 'resolve')
4384 4382 r = ms.resolve(f, wctx)
4385 4383 if r:
4386 4384 ret = 1
4387 4385 finally:
4388 4386 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4389 4387 ms.commit()
4390 4388
4391 4389 # replace filemerge's .orig file with our resolve file
4392 4390 a = repo.wjoin(f)
4393 4391 try:
4394 4392 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4395 4393 except OSError as inst:
4396 4394 if inst.errno != errno.ENOENT:
4397 4395 raise
4398 4396
4399 4397 ms.commit()
4400 4398 ms.recordactions()
4401 4399
4402 4400 if not didwork and pats:
4403 4401 hint = None
4404 4402 if not any([p for p in pats if p.find(':') >= 0]):
4405 4403 pats = ['path:%s' % p for p in pats]
4406 4404 m = scmutil.match(wctx, pats, opts)
4407 4405 for f in ms:
4408 4406 if not m(f):
4409 4407 continue
4410 4408 flags = ''.join(['-%s ' % o[0] for o in flaglist
4411 4409 if opts.get(o)])
4412 4410 hint = _("(try: hg resolve %s%s)\n") % (
4413 4411 flags,
4414 4412 ' '.join(pats))
4415 4413 break
4416 4414 ui.warn(_("arguments do not match paths that need resolving\n"))
4417 4415 if hint:
4418 4416 ui.warn(hint)
4419 4417 elif ms.mergedriver and ms.mdstate() != 's':
4420 4418 # run conclude step when either a driver-resolved file is requested
4421 4419 # or there are no driver-resolved files
4422 4420 # we can't use 'ret' to determine whether any files are unresolved
4423 4421 # because we might not have tried to resolve some
4424 4422 if ((runconclude or not list(ms.driverresolved()))
4425 4423 and not list(ms.unresolved())):
4426 4424 proceed = mergemod.driverconclude(repo, ms, wctx)
4427 4425 ms.commit()
4428 4426 if not proceed:
4429 4427 return 1
4430 4428
4431 4429 # Nudge users into finishing an unfinished operation
4432 4430 unresolvedf = list(ms.unresolved())
4433 4431 driverresolvedf = list(ms.driverresolved())
4434 4432 if not unresolvedf and not driverresolvedf:
4435 4433 ui.status(_('(no more unresolved files)\n'))
4436 4434 cmdutil.checkafterresolved(repo)
4437 4435 elif not unresolvedf:
4438 4436 ui.status(_('(no more unresolved files -- '
4439 4437 'run "hg resolve --all" to conclude)\n'))
4440 4438
4441 4439 return ret
4442 4440
4443 4441 @command('revert',
4444 4442 [('a', 'all', None, _('revert all changes when no arguments given')),
4445 4443 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4446 4444 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4447 4445 ('C', 'no-backup', None, _('do not save backup copies of files')),
4448 4446 ('i', 'interactive', None,
4449 4447 _('interactively select the changes (EXPERIMENTAL)')),
4450 4448 ] + walkopts + dryrunopts,
4451 4449 _('[OPTION]... [-r REV] [NAME]...'))
4452 4450 def revert(ui, repo, *pats, **opts):
4453 4451 """restore files to their checkout state
4454 4452
4455 4453 .. note::
4456 4454
4457 4455 To check out earlier revisions, you should use :hg:`update REV`.
4458 4456 To cancel an uncommitted merge (and lose your changes),
4459 4457 use :hg:`update --clean .`.
4460 4458
4461 4459 With no revision specified, revert the specified files or directories
4462 4460 to the contents they had in the parent of the working directory.
4463 4461 This restores the contents of files to an unmodified
4464 4462 state and unschedules adds, removes, copies, and renames. If the
4465 4463 working directory has two parents, you must explicitly specify a
4466 4464 revision.
4467 4465
4468 4466 Using the -r/--rev or -d/--date options, revert the given files or
4469 4467 directories to their states as of a specific revision. Because
4470 4468 revert does not change the working directory parents, this will
4471 4469 cause these files to appear modified. This can be helpful to "back
4472 4470 out" some or all of an earlier change. See :hg:`backout` for a
4473 4471 related method.
4474 4472
4475 4473 Modified files are saved with a .orig suffix before reverting.
4476 4474 To disable these backups, use --no-backup. It is possible to store
4477 4475 the backup files in a custom directory relative to the root of the
4478 4476 repository by setting the ``ui.origbackuppath`` configuration
4479 4477 option.
4480 4478
4481 4479 See :hg:`help dates` for a list of formats valid for -d/--date.
4482 4480
4483 4481 See :hg:`help backout` for a way to reverse the effect of an
4484 4482 earlier changeset.
4485 4483
4486 4484 Returns 0 on success.
4487 4485 """
4488 4486
4489 4487 if opts.get("date"):
4490 4488 if opts.get("rev"):
4491 4489 raise error.Abort(_("you can't specify a revision and a date"))
4492 4490 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4493 4491
4494 4492 parent, p2 = repo.dirstate.parents()
4495 4493 if not opts.get('rev') and p2 != nullid:
4496 4494 # revert after merge is a trap for new users (issue2915)
4497 4495 raise error.Abort(_('uncommitted merge with no revision specified'),
4498 4496 hint=_("use 'hg update' or see 'hg help revert'"))
4499 4497
4500 4498 ctx = scmutil.revsingle(repo, opts.get('rev'))
4501 4499
4502 4500 if (not (pats or opts.get('include') or opts.get('exclude') or
4503 4501 opts.get('all') or opts.get('interactive'))):
4504 4502 msg = _("no files or directories specified")
4505 4503 if p2 != nullid:
4506 4504 hint = _("uncommitted merge, use --all to discard all changes,"
4507 4505 " or 'hg update -C .' to abort the merge")
4508 4506 raise error.Abort(msg, hint=hint)
4509 4507 dirty = any(repo.status())
4510 4508 node = ctx.node()
4511 4509 if node != parent:
4512 4510 if dirty:
4513 4511 hint = _("uncommitted changes, use --all to discard all"
4514 4512 " changes, or 'hg update %s' to update") % ctx.rev()
4515 4513 else:
4516 4514 hint = _("use --all to revert all files,"
4517 4515 " or 'hg update %s' to update") % ctx.rev()
4518 4516 elif dirty:
4519 4517 hint = _("uncommitted changes, use --all to discard all changes")
4520 4518 else:
4521 4519 hint = _("use --all to revert all files")
4522 4520 raise error.Abort(msg, hint=hint)
4523 4521
4524 4522 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4525 4523
4526 4524 @command('rollback', dryrunopts +
4527 4525 [('f', 'force', False, _('ignore safety measures'))])
4528 4526 def rollback(ui, repo, **opts):
4529 4527 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4530 4528
4531 4529 Please use :hg:`commit --amend` instead of rollback to correct
4532 4530 mistakes in the last commit.
4533 4531
4534 4532 This command should be used with care. There is only one level of
4535 4533 rollback, and there is no way to undo a rollback. It will also
4536 4534 restore the dirstate at the time of the last transaction, losing
4537 4535 any dirstate changes since that time. This command does not alter
4538 4536 the working directory.
4539 4537
4540 4538 Transactions are used to encapsulate the effects of all commands
4541 4539 that create new changesets or propagate existing changesets into a
4542 4540 repository.
4543 4541
4544 4542 .. container:: verbose
4545 4543
4546 4544 For example, the following commands are transactional, and their
4547 4545 effects can be rolled back:
4548 4546
4549 4547 - commit
4550 4548 - import
4551 4549 - pull
4552 4550 - push (with this repository as the destination)
4553 4551 - unbundle
4554 4552
4555 4553 To avoid permanent data loss, rollback will refuse to rollback a
4556 4554 commit transaction if it isn't checked out. Use --force to
4557 4555 override this protection.
4558 4556
4559 4557 The rollback command can be entirely disabled by setting the
4560 4558 ``ui.rollback`` configuration setting to false. If you're here
4561 4559 because you want to use rollback and it's disabled, you can
4562 4560 re-enable the command by setting ``ui.rollback`` to true.
4563 4561
4564 4562 This command is not intended for use on public repositories. Once
4565 4563 changes are visible for pull by other users, rolling a transaction
4566 4564 back locally is ineffective (someone else may already have pulled
4567 4565 the changes). Furthermore, a race is possible with readers of the
4568 4566 repository; for example an in-progress pull from the repository
4569 4567 may fail if a rollback is performed.
4570 4568
4571 4569 Returns 0 on success, 1 if no rollback data is available.
4572 4570 """
4573 4571 if not ui.configbool('ui', 'rollback', True):
4574 4572 raise error.Abort(_('rollback is disabled because it is unsafe'),
4575 4573 hint=('see `hg help -v rollback` for information'))
4576 4574 return repo.rollback(dryrun=opts.get('dry_run'),
4577 4575 force=opts.get('force'))
4578 4576
4579 4577 @command('root', [])
4580 4578 def root(ui, repo):
4581 4579 """print the root (top) of the current working directory
4582 4580
4583 4581 Print the root directory of the current repository.
4584 4582
4585 4583 Returns 0 on success.
4586 4584 """
4587 4585 ui.write(repo.root + "\n")
4588 4586
4589 4587 @command('^serve',
4590 4588 [('A', 'accesslog', '', _('name of access log file to write to'),
4591 4589 _('FILE')),
4592 4590 ('d', 'daemon', None, _('run server in background')),
4593 4591 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4594 4592 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4595 4593 # use string type, then we can check if something was passed
4596 4594 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4597 4595 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4598 4596 _('ADDR')),
4599 4597 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4600 4598 _('PREFIX')),
4601 4599 ('n', 'name', '',
4602 4600 _('name to show in web pages (default: working directory)'), _('NAME')),
4603 4601 ('', 'web-conf', '',
4604 4602 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4605 4603 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4606 4604 _('FILE')),
4607 4605 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4608 4606 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4609 4607 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4610 4608 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4611 4609 ('', 'style', '', _('template style to use'), _('STYLE')),
4612 4610 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4613 4611 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4614 4612 _('[OPTION]...'),
4615 4613 optionalrepo=True)
4616 4614 def serve(ui, repo, **opts):
4617 4615 """start stand-alone webserver
4618 4616
4619 4617 Start a local HTTP repository browser and pull server. You can use
4620 4618 this for ad-hoc sharing and browsing of repositories. It is
4621 4619 recommended to use a real web server to serve a repository for
4622 4620 longer periods of time.
4623 4621
4624 4622 Please note that the server does not implement access control.
4625 4623 This means that, by default, anybody can read from the server and
4626 4624 nobody can write to it by default. Set the ``web.allow_push``
4627 4625 option to ``*`` to allow everybody to push to the server. You
4628 4626 should use a real web server if you need to authenticate users.
4629 4627
4630 4628 By default, the server logs accesses to stdout and errors to
4631 4629 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4632 4630 files.
4633 4631
4634 4632 To have the server choose a free port number to listen on, specify
4635 4633 a port number of 0; in this case, the server will print the port
4636 4634 number it uses.
4637 4635
4638 4636 Returns 0 on success.
4639 4637 """
4640 4638
4641 4639 if opts["stdio"] and opts["cmdserver"]:
4642 4640 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4643 4641
4644 4642 if opts["stdio"]:
4645 4643 if repo is None:
4646 4644 raise error.RepoError(_("there is no Mercurial repository here"
4647 4645 " (.hg not found)"))
4648 4646 s = sshserver.sshserver(ui, repo)
4649 4647 s.serve_forever()
4650 4648
4651 4649 service = server.createservice(ui, repo, opts)
4652 4650 return server.runservice(opts, initfn=service.init, runfn=service.run)
4653 4651
4654 4652 @command('^status|st',
4655 4653 [('A', 'all', None, _('show status of all files')),
4656 4654 ('m', 'modified', None, _('show only modified files')),
4657 4655 ('a', 'added', None, _('show only added files')),
4658 4656 ('r', 'removed', None, _('show only removed files')),
4659 4657 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4660 4658 ('c', 'clean', None, _('show only files without changes')),
4661 4659 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4662 4660 ('i', 'ignored', None, _('show only ignored files')),
4663 4661 ('n', 'no-status', None, _('hide status prefix')),
4664 4662 ('C', 'copies', None, _('show source of copied files')),
4665 4663 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4666 4664 ('', 'rev', [], _('show difference from revision'), _('REV')),
4667 4665 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4668 4666 ] + walkopts + subrepoopts + formatteropts,
4669 4667 _('[OPTION]... [FILE]...'),
4670 4668 inferrepo=True)
4671 4669 def status(ui, repo, *pats, **opts):
4672 4670 """show changed files in the working directory
4673 4671
4674 4672 Show status of files in the repository. If names are given, only
4675 4673 files that match are shown. Files that are clean or ignored or
4676 4674 the source of a copy/move operation, are not listed unless
4677 4675 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4678 4676 Unless options described with "show only ..." are given, the
4679 4677 options -mardu are used.
4680 4678
4681 4679 Option -q/--quiet hides untracked (unknown and ignored) files
4682 4680 unless explicitly requested with -u/--unknown or -i/--ignored.
4683 4681
4684 4682 .. note::
4685 4683
4686 4684 :hg:`status` may appear to disagree with diff if permissions have
4687 4685 changed or a merge has occurred. The standard diff format does
4688 4686 not report permission changes and diff only reports changes
4689 4687 relative to one merge parent.
4690 4688
4691 4689 If one revision is given, it is used as the base revision.
4692 4690 If two revisions are given, the differences between them are
4693 4691 shown. The --change option can also be used as a shortcut to list
4694 4692 the changed files of a revision from its first parent.
4695 4693
4696 4694 The codes used to show the status of files are::
4697 4695
4698 4696 M = modified
4699 4697 A = added
4700 4698 R = removed
4701 4699 C = clean
4702 4700 ! = missing (deleted by non-hg command, but still tracked)
4703 4701 ? = not tracked
4704 4702 I = ignored
4705 4703 = origin of the previous file (with --copies)
4706 4704
4707 4705 .. container:: verbose
4708 4706
4709 4707 Examples:
4710 4708
4711 4709 - show changes in the working directory relative to a
4712 4710 changeset::
4713 4711
4714 4712 hg status --rev 9353
4715 4713
4716 4714 - show changes in the working directory relative to the
4717 4715 current directory (see :hg:`help patterns` for more information)::
4718 4716
4719 4717 hg status re:
4720 4718
4721 4719 - show all changes including copies in an existing changeset::
4722 4720
4723 4721 hg status --copies --change 9353
4724 4722
4725 4723 - get a NUL separated list of added files, suitable for xargs::
4726 4724
4727 4725 hg status -an0
4728 4726
4729 4727 Returns 0 on success.
4730 4728 """
4731 4729
4732 4730 opts = pycompat.byteskwargs(opts)
4733 4731 revs = opts.get('rev')
4734 4732 change = opts.get('change')
4735 4733
4736 4734 if revs and change:
4737 4735 msg = _('cannot specify --rev and --change at the same time')
4738 4736 raise error.Abort(msg)
4739 4737 elif change:
4740 4738 node2 = scmutil.revsingle(repo, change, None).node()
4741 4739 node1 = repo[node2].p1().node()
4742 4740 else:
4743 4741 node1, node2 = scmutil.revpair(repo, revs)
4744 4742
4745 4743 if pats or ui.configbool('commands', 'status.relative'):
4746 4744 cwd = repo.getcwd()
4747 4745 else:
4748 4746 cwd = ''
4749 4747
4750 4748 if opts.get('print0'):
4751 4749 end = '\0'
4752 4750 else:
4753 4751 end = '\n'
4754 4752 copy = {}
4755 4753 states = 'modified added removed deleted unknown ignored clean'.split()
4756 4754 show = [k for k in states if opts.get(k)]
4757 4755 if opts.get('all'):
4758 4756 show += ui.quiet and (states[:4] + ['clean']) or states
4759 4757 if not show:
4760 4758 if ui.quiet:
4761 4759 show = states[:4]
4762 4760 else:
4763 4761 show = states[:5]
4764 4762
4765 4763 m = scmutil.match(repo[node2], pats, opts)
4766 4764 stat = repo.status(node1, node2, m,
4767 4765 'ignored' in show, 'clean' in show, 'unknown' in show,
4768 4766 opts.get('subrepos'))
4769 4767 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4770 4768
4771 4769 if (opts.get('all') or opts.get('copies')
4772 4770 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4773 4771 copy = copies.pathcopies(repo[node1], repo[node2], m)
4774 4772
4775 4773 ui.pager('status')
4776 4774 fm = ui.formatter('status', opts)
4777 4775 fmt = '%s' + end
4778 4776 showchar = not opts.get('no_status')
4779 4777
4780 4778 for state, char, files in changestates:
4781 4779 if state in show:
4782 4780 label = 'status.' + state
4783 4781 for f in files:
4784 4782 fm.startitem()
4785 4783 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4786 4784 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4787 4785 if f in copy:
4788 4786 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4789 4787 label='status.copied')
4790 4788 fm.end()
4791 4789
4792 4790 @command('^summary|sum',
4793 4791 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4794 4792 def summary(ui, repo, **opts):
4795 4793 """summarize working directory state
4796 4794
4797 4795 This generates a brief summary of the working directory state,
4798 4796 including parents, branch, commit status, phase and available updates.
4799 4797
4800 4798 With the --remote option, this will check the default paths for
4801 4799 incoming and outgoing changes. This can be time-consuming.
4802 4800
4803 4801 Returns 0 on success.
4804 4802 """
4805 4803
4806 4804 ui.pager('summary')
4807 4805 ctx = repo[None]
4808 4806 parents = ctx.parents()
4809 4807 pnode = parents[0].node()
4810 4808 marks = []
4811 4809
4812 4810 ms = None
4813 4811 try:
4814 4812 ms = mergemod.mergestate.read(repo)
4815 4813 except error.UnsupportedMergeRecords as e:
4816 4814 s = ' '.join(e.recordtypes)
4817 4815 ui.warn(
4818 4816 _('warning: merge state has unsupported record types: %s\n') % s)
4819 4817 unresolved = 0
4820 4818 else:
4821 4819 unresolved = [f for f in ms if ms[f] == 'u']
4822 4820
4823 4821 for p in parents:
4824 4822 # label with log.changeset (instead of log.parent) since this
4825 4823 # shows a working directory parent *changeset*:
4826 4824 # i18n: column positioning for "hg summary"
4827 4825 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4828 4826 label=cmdutil._changesetlabels(p))
4829 4827 ui.write(' '.join(p.tags()), label='log.tag')
4830 4828 if p.bookmarks():
4831 4829 marks.extend(p.bookmarks())
4832 4830 if p.rev() == -1:
4833 4831 if not len(repo):
4834 4832 ui.write(_(' (empty repository)'))
4835 4833 else:
4836 4834 ui.write(_(' (no revision checked out)'))
4837 4835 if p.obsolete():
4838 4836 ui.write(_(' (obsolete)'))
4839 4837 if p.troubled():
4840 4838 ui.write(' ('
4841 4839 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4842 4840 for trouble in p.troubles())
4843 4841 + ')')
4844 4842 ui.write('\n')
4845 4843 if p.description():
4846 4844 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4847 4845 label='log.summary')
4848 4846
4849 4847 branch = ctx.branch()
4850 4848 bheads = repo.branchheads(branch)
4851 4849 # i18n: column positioning for "hg summary"
4852 4850 m = _('branch: %s\n') % branch
4853 4851 if branch != 'default':
4854 4852 ui.write(m, label='log.branch')
4855 4853 else:
4856 4854 ui.status(m, label='log.branch')
4857 4855
4858 4856 if marks:
4859 4857 active = repo._activebookmark
4860 4858 # i18n: column positioning for "hg summary"
4861 4859 ui.write(_('bookmarks:'), label='log.bookmark')
4862 4860 if active is not None:
4863 4861 if active in marks:
4864 4862 ui.write(' *' + active, label=activebookmarklabel)
4865 4863 marks.remove(active)
4866 4864 else:
4867 4865 ui.write(' [%s]' % active, label=activebookmarklabel)
4868 4866 for m in marks:
4869 4867 ui.write(' ' + m, label='log.bookmark')
4870 4868 ui.write('\n', label='log.bookmark')
4871 4869
4872 4870 status = repo.status(unknown=True)
4873 4871
4874 4872 c = repo.dirstate.copies()
4875 4873 copied, renamed = [], []
4876 4874 for d, s in c.iteritems():
4877 4875 if s in status.removed:
4878 4876 status.removed.remove(s)
4879 4877 renamed.append(d)
4880 4878 else:
4881 4879 copied.append(d)
4882 4880 if d in status.added:
4883 4881 status.added.remove(d)
4884 4882
4885 4883 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4886 4884
4887 4885 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4888 4886 (ui.label(_('%d added'), 'status.added'), status.added),
4889 4887 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4890 4888 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4891 4889 (ui.label(_('%d copied'), 'status.copied'), copied),
4892 4890 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4893 4891 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4894 4892 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4895 4893 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4896 4894 t = []
4897 4895 for l, s in labels:
4898 4896 if s:
4899 4897 t.append(l % len(s))
4900 4898
4901 4899 t = ', '.join(t)
4902 4900 cleanworkdir = False
4903 4901
4904 4902 if repo.vfs.exists('graftstate'):
4905 4903 t += _(' (graft in progress)')
4906 4904 if repo.vfs.exists('updatestate'):
4907 4905 t += _(' (interrupted update)')
4908 4906 elif len(parents) > 1:
4909 4907 t += _(' (merge)')
4910 4908 elif branch != parents[0].branch():
4911 4909 t += _(' (new branch)')
4912 4910 elif (parents[0].closesbranch() and
4913 4911 pnode in repo.branchheads(branch, closed=True)):
4914 4912 t += _(' (head closed)')
4915 4913 elif not (status.modified or status.added or status.removed or renamed or
4916 4914 copied or subs):
4917 4915 t += _(' (clean)')
4918 4916 cleanworkdir = True
4919 4917 elif pnode not in bheads:
4920 4918 t += _(' (new branch head)')
4921 4919
4922 4920 if parents:
4923 4921 pendingphase = max(p.phase() for p in parents)
4924 4922 else:
4925 4923 pendingphase = phases.public
4926 4924
4927 4925 if pendingphase > phases.newcommitphase(ui):
4928 4926 t += ' (%s)' % phases.phasenames[pendingphase]
4929 4927
4930 4928 if cleanworkdir:
4931 4929 # i18n: column positioning for "hg summary"
4932 4930 ui.status(_('commit: %s\n') % t.strip())
4933 4931 else:
4934 4932 # i18n: column positioning for "hg summary"
4935 4933 ui.write(_('commit: %s\n') % t.strip())
4936 4934
4937 4935 # all ancestors of branch heads - all ancestors of parent = new csets
4938 4936 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4939 4937 bheads))
4940 4938
4941 4939 if new == 0:
4942 4940 # i18n: column positioning for "hg summary"
4943 4941 ui.status(_('update: (current)\n'))
4944 4942 elif pnode not in bheads:
4945 4943 # i18n: column positioning for "hg summary"
4946 4944 ui.write(_('update: %d new changesets (update)\n') % new)
4947 4945 else:
4948 4946 # i18n: column positioning for "hg summary"
4949 4947 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4950 4948 (new, len(bheads)))
4951 4949
4952 4950 t = []
4953 4951 draft = len(repo.revs('draft()'))
4954 4952 if draft:
4955 4953 t.append(_('%d draft') % draft)
4956 4954 secret = len(repo.revs('secret()'))
4957 4955 if secret:
4958 4956 t.append(_('%d secret') % secret)
4959 4957
4960 4958 if draft or secret:
4961 4959 ui.status(_('phases: %s\n') % ', '.join(t))
4962 4960
4963 4961 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4964 4962 for trouble in ("unstable", "divergent", "bumped"):
4965 4963 numtrouble = len(repo.revs(trouble + "()"))
4966 4964 # We write all the possibilities to ease translation
4967 4965 troublemsg = {
4968 4966 "unstable": _("unstable: %d changesets"),
4969 4967 "divergent": _("divergent: %d changesets"),
4970 4968 "bumped": _("bumped: %d changesets"),
4971 4969 }
4972 4970 if numtrouble > 0:
4973 4971 ui.status(troublemsg[trouble] % numtrouble + "\n")
4974 4972
4975 4973 cmdutil.summaryhooks(ui, repo)
4976 4974
4977 4975 if opts.get('remote'):
4978 4976 needsincoming, needsoutgoing = True, True
4979 4977 else:
4980 4978 needsincoming, needsoutgoing = False, False
4981 4979 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4982 4980 if i:
4983 4981 needsincoming = True
4984 4982 if o:
4985 4983 needsoutgoing = True
4986 4984 if not needsincoming and not needsoutgoing:
4987 4985 return
4988 4986
4989 4987 def getincoming():
4990 4988 source, branches = hg.parseurl(ui.expandpath('default'))
4991 4989 sbranch = branches[0]
4992 4990 try:
4993 4991 other = hg.peer(repo, {}, source)
4994 4992 except error.RepoError:
4995 4993 if opts.get('remote'):
4996 4994 raise
4997 4995 return source, sbranch, None, None, None
4998 4996 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4999 4997 if revs:
5000 4998 revs = [other.lookup(rev) for rev in revs]
5001 4999 ui.debug('comparing with %s\n' % util.hidepassword(source))
5002 5000 repo.ui.pushbuffer()
5003 5001 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5004 5002 repo.ui.popbuffer()
5005 5003 return source, sbranch, other, commoninc, commoninc[1]
5006 5004
5007 5005 if needsincoming:
5008 5006 source, sbranch, sother, commoninc, incoming = getincoming()
5009 5007 else:
5010 5008 source = sbranch = sother = commoninc = incoming = None
5011 5009
5012 5010 def getoutgoing():
5013 5011 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5014 5012 dbranch = branches[0]
5015 5013 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5016 5014 if source != dest:
5017 5015 try:
5018 5016 dother = hg.peer(repo, {}, dest)
5019 5017 except error.RepoError:
5020 5018 if opts.get('remote'):
5021 5019 raise
5022 5020 return dest, dbranch, None, None
5023 5021 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5024 5022 elif sother is None:
5025 5023 # there is no explicit destination peer, but source one is invalid
5026 5024 return dest, dbranch, None, None
5027 5025 else:
5028 5026 dother = sother
5029 5027 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5030 5028 common = None
5031 5029 else:
5032 5030 common = commoninc
5033 5031 if revs:
5034 5032 revs = [repo.lookup(rev) for rev in revs]
5035 5033 repo.ui.pushbuffer()
5036 5034 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5037 5035 commoninc=common)
5038 5036 repo.ui.popbuffer()
5039 5037 return dest, dbranch, dother, outgoing
5040 5038
5041 5039 if needsoutgoing:
5042 5040 dest, dbranch, dother, outgoing = getoutgoing()
5043 5041 else:
5044 5042 dest = dbranch = dother = outgoing = None
5045 5043
5046 5044 if opts.get('remote'):
5047 5045 t = []
5048 5046 if incoming:
5049 5047 t.append(_('1 or more incoming'))
5050 5048 o = outgoing.missing
5051 5049 if o:
5052 5050 t.append(_('%d outgoing') % len(o))
5053 5051 other = dother or sother
5054 5052 if 'bookmarks' in other.listkeys('namespaces'):
5055 5053 counts = bookmarks.summary(repo, other)
5056 5054 if counts[0] > 0:
5057 5055 t.append(_('%d incoming bookmarks') % counts[0])
5058 5056 if counts[1] > 0:
5059 5057 t.append(_('%d outgoing bookmarks') % counts[1])
5060 5058
5061 5059 if t:
5062 5060 # i18n: column positioning for "hg summary"
5063 5061 ui.write(_('remote: %s\n') % (', '.join(t)))
5064 5062 else:
5065 5063 # i18n: column positioning for "hg summary"
5066 5064 ui.status(_('remote: (synced)\n'))
5067 5065
5068 5066 cmdutil.summaryremotehooks(ui, repo, opts,
5069 5067 ((source, sbranch, sother, commoninc),
5070 5068 (dest, dbranch, dother, outgoing)))
5071 5069
5072 5070 @command('tag',
5073 5071 [('f', 'force', None, _('force tag')),
5074 5072 ('l', 'local', None, _('make the tag local')),
5075 5073 ('r', 'rev', '', _('revision to tag'), _('REV')),
5076 5074 ('', 'remove', None, _('remove a tag')),
5077 5075 # -l/--local is already there, commitopts cannot be used
5078 5076 ('e', 'edit', None, _('invoke editor on commit messages')),
5079 5077 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5080 5078 ] + commitopts2,
5081 5079 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5082 5080 def tag(ui, repo, name1, *names, **opts):
5083 5081 """add one or more tags for the current or given revision
5084 5082
5085 5083 Name a particular revision using <name>.
5086 5084
5087 5085 Tags are used to name particular revisions of the repository and are
5088 5086 very useful to compare different revisions, to go back to significant
5089 5087 earlier versions or to mark branch points as releases, etc. Changing
5090 5088 an existing tag is normally disallowed; use -f/--force to override.
5091 5089
5092 5090 If no revision is given, the parent of the working directory is
5093 5091 used.
5094 5092
5095 5093 To facilitate version control, distribution, and merging of tags,
5096 5094 they are stored as a file named ".hgtags" which is managed similarly
5097 5095 to other project files and can be hand-edited if necessary. This
5098 5096 also means that tagging creates a new commit. The file
5099 5097 ".hg/localtags" is used for local tags (not shared among
5100 5098 repositories).
5101 5099
5102 5100 Tag commits are usually made at the head of a branch. If the parent
5103 5101 of the working directory is not a branch head, :hg:`tag` aborts; use
5104 5102 -f/--force to force the tag commit to be based on a non-head
5105 5103 changeset.
5106 5104
5107 5105 See :hg:`help dates` for a list of formats valid for -d/--date.
5108 5106
5109 5107 Since tag names have priority over branch names during revision
5110 5108 lookup, using an existing branch name as a tag name is discouraged.
5111 5109
5112 5110 Returns 0 on success.
5113 5111 """
5114 5112 wlock = lock = None
5115 5113 try:
5116 5114 wlock = repo.wlock()
5117 5115 lock = repo.lock()
5118 5116 rev_ = "."
5119 5117 names = [t.strip() for t in (name1,) + names]
5120 5118 if len(names) != len(set(names)):
5121 5119 raise error.Abort(_('tag names must be unique'))
5122 5120 for n in names:
5123 5121 scmutil.checknewlabel(repo, n, 'tag')
5124 5122 if not n:
5125 5123 raise error.Abort(_('tag names cannot consist entirely of '
5126 5124 'whitespace'))
5127 5125 if opts.get('rev') and opts.get('remove'):
5128 5126 raise error.Abort(_("--rev and --remove are incompatible"))
5129 5127 if opts.get('rev'):
5130 5128 rev_ = opts['rev']
5131 5129 message = opts.get('message')
5132 5130 if opts.get('remove'):
5133 5131 if opts.get('local'):
5134 5132 expectedtype = 'local'
5135 5133 else:
5136 5134 expectedtype = 'global'
5137 5135
5138 5136 for n in names:
5139 5137 if not repo.tagtype(n):
5140 5138 raise error.Abort(_("tag '%s' does not exist") % n)
5141 5139 if repo.tagtype(n) != expectedtype:
5142 5140 if expectedtype == 'global':
5143 5141 raise error.Abort(_("tag '%s' is not a global tag") % n)
5144 5142 else:
5145 5143 raise error.Abort(_("tag '%s' is not a local tag") % n)
5146 5144 rev_ = 'null'
5147 5145 if not message:
5148 5146 # we don't translate commit messages
5149 5147 message = 'Removed tag %s' % ', '.join(names)
5150 5148 elif not opts.get('force'):
5151 5149 for n in names:
5152 5150 if n in repo.tags():
5153 5151 raise error.Abort(_("tag '%s' already exists "
5154 5152 "(use -f to force)") % n)
5155 5153 if not opts.get('local'):
5156 5154 p1, p2 = repo.dirstate.parents()
5157 5155 if p2 != nullid:
5158 5156 raise error.Abort(_('uncommitted merge'))
5159 5157 bheads = repo.branchheads()
5160 5158 if not opts.get('force') and bheads and p1 not in bheads:
5161 5159 raise error.Abort(_('working directory is not at a branch head '
5162 5160 '(use -f to force)'))
5163 5161 r = scmutil.revsingle(repo, rev_).node()
5164 5162
5165 5163 if not message:
5166 5164 # we don't translate commit messages
5167 5165 message = ('Added tag %s for changeset %s' %
5168 5166 (', '.join(names), short(r)))
5169 5167
5170 5168 date = opts.get('date')
5171 5169 if date:
5172 5170 date = util.parsedate(date)
5173 5171
5174 5172 if opts.get('remove'):
5175 5173 editform = 'tag.remove'
5176 5174 else:
5177 5175 editform = 'tag.add'
5178 5176 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5179 5177
5180 5178 # don't allow tagging the null rev
5181 5179 if (not opts.get('remove') and
5182 5180 scmutil.revsingle(repo, rev_).rev() == nullrev):
5183 5181 raise error.Abort(_("cannot tag null revision"))
5184 5182
5185 5183 tagsmod.tag(repo, names, r, message, opts.get('local'),
5186 5184 opts.get('user'), date, editor=editor)
5187 5185 finally:
5188 5186 release(lock, wlock)
5189 5187
5190 5188 @command('tags', formatteropts, '')
5191 5189 def tags(ui, repo, **opts):
5192 5190 """list repository tags
5193 5191
5194 5192 This lists both regular and local tags. When the -v/--verbose
5195 5193 switch is used, a third column "local" is printed for local tags.
5196 5194 When the -q/--quiet switch is used, only the tag name is printed.
5197 5195
5198 5196 Returns 0 on success.
5199 5197 """
5200 5198
5201 5199 ui.pager('tags')
5202 5200 fm = ui.formatter('tags', opts)
5203 5201 hexfunc = fm.hexfunc
5204 5202 tagtype = ""
5205 5203
5206 5204 for t, n in reversed(repo.tagslist()):
5207 5205 hn = hexfunc(n)
5208 5206 label = 'tags.normal'
5209 5207 tagtype = ''
5210 5208 if repo.tagtype(t) == 'local':
5211 5209 label = 'tags.local'
5212 5210 tagtype = 'local'
5213 5211
5214 5212 fm.startitem()
5215 5213 fm.write('tag', '%s', t, label=label)
5216 5214 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5217 5215 fm.condwrite(not ui.quiet, 'rev node', fmt,
5218 5216 repo.changelog.rev(n), hn, label=label)
5219 5217 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5220 5218 tagtype, label=label)
5221 5219 fm.plain('\n')
5222 5220 fm.end()
5223 5221
5224 5222 @command('tip',
5225 5223 [('p', 'patch', None, _('show patch')),
5226 5224 ('g', 'git', None, _('use git extended diff format')),
5227 5225 ] + templateopts,
5228 5226 _('[-p] [-g]'))
5229 5227 def tip(ui, repo, **opts):
5230 5228 """show the tip revision (DEPRECATED)
5231 5229
5232 5230 The tip revision (usually just called the tip) is the changeset
5233 5231 most recently added to the repository (and therefore the most
5234 5232 recently changed head).
5235 5233
5236 5234 If you have just made a commit, that commit will be the tip. If
5237 5235 you have just pulled changes from another repository, the tip of
5238 5236 that repository becomes the current tip. The "tip" tag is special
5239 5237 and cannot be renamed or assigned to a different changeset.
5240 5238
5241 5239 This command is deprecated, please use :hg:`heads` instead.
5242 5240
5243 5241 Returns 0 on success.
5244 5242 """
5245 5243 displayer = cmdutil.show_changeset(ui, repo, opts)
5246 5244 displayer.show(repo['tip'])
5247 5245 displayer.close()
5248 5246
5249 5247 @command('unbundle',
5250 5248 [('u', 'update', None,
5251 5249 _('update to new branch head if changesets were unbundled'))],
5252 5250 _('[-u] FILE...'))
5253 5251 def unbundle(ui, repo, fname1, *fnames, **opts):
5254 5252 """apply one or more changegroup files
5255 5253
5256 5254 Apply one or more compressed changegroup files generated by the
5257 5255 bundle command.
5258 5256
5259 5257 Returns 0 on success, 1 if an update has unresolved files.
5260 5258 """
5261 5259 fnames = (fname1,) + fnames
5262 5260
5263 5261 with repo.lock():
5264 5262 for fname in fnames:
5265 5263 f = hg.openpath(ui, fname)
5266 5264 gen = exchange.readbundle(ui, f, fname)
5267 5265 if isinstance(gen, bundle2.unbundle20):
5268 5266 tr = repo.transaction('unbundle')
5269 5267 try:
5270 5268 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5271 5269 url='bundle:' + fname)
5272 5270 tr.close()
5273 5271 except error.BundleUnknownFeatureError as exc:
5274 5272 raise error.Abort(_('%s: unknown bundle feature, %s')
5275 5273 % (fname, exc),
5276 5274 hint=_("see https://mercurial-scm.org/"
5277 5275 "wiki/BundleFeature for more "
5278 5276 "information"))
5279 5277 finally:
5280 5278 if tr:
5281 5279 tr.release()
5282 5280 changes = [r.get('return', 0)
5283 5281 for r in op.records['changegroup']]
5284 5282 modheads = changegroup.combineresults(changes)
5285 5283 elif isinstance(gen, streamclone.streamcloneapplier):
5286 5284 raise error.Abort(
5287 5285 _('packed bundles cannot be applied with '
5288 5286 '"hg unbundle"'),
5289 5287 hint=_('use "hg debugapplystreamclonebundle"'))
5290 5288 else:
5291 5289 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5292 5290
5293 5291 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5294 5292
5295 5293 @command('^update|up|checkout|co',
5296 5294 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5297 5295 ('c', 'check', None, _('require clean working directory')),
5298 5296 ('m', 'merge', None, _('merge uncommitted changes')),
5299 5297 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5300 5298 ('r', 'rev', '', _('revision'), _('REV'))
5301 5299 ] + mergetoolopts,
5302 5300 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5303 5301 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5304 5302 merge=None, tool=None):
5305 5303 """update working directory (or switch revisions)
5306 5304
5307 5305 Update the repository's working directory to the specified
5308 5306 changeset. If no changeset is specified, update to the tip of the
5309 5307 current named branch and move the active bookmark (see :hg:`help
5310 5308 bookmarks`).
5311 5309
5312 5310 Update sets the working directory's parent revision to the specified
5313 5311 changeset (see :hg:`help parents`).
5314 5312
5315 5313 If the changeset is not a descendant or ancestor of the working
5316 5314 directory's parent and there are uncommitted changes, the update is
5317 5315 aborted. With the -c/--check option, the working directory is checked
5318 5316 for uncommitted changes; if none are found, the working directory is
5319 5317 updated to the specified changeset.
5320 5318
5321 5319 .. container:: verbose
5322 5320
5323 5321 The -C/--clean, -c/--check, and -m/--merge options control what
5324 5322 happens if the working directory contains uncommitted changes.
5325 5323 At most of one of them can be specified.
5326 5324
5327 5325 1. If no option is specified, and if
5328 5326 the requested changeset is an ancestor or descendant of
5329 5327 the working directory's parent, the uncommitted changes
5330 5328 are merged into the requested changeset and the merged
5331 5329 result is left uncommitted. If the requested changeset is
5332 5330 not an ancestor or descendant (that is, it is on another
5333 5331 branch), the update is aborted and the uncommitted changes
5334 5332 are preserved.
5335 5333
5336 5334 2. With the -m/--merge option, the update is allowed even if the
5337 5335 requested changeset is not an ancestor or descendant of
5338 5336 the working directory's parent.
5339 5337
5340 5338 3. With the -c/--check option, the update is aborted and the
5341 5339 uncommitted changes are preserved.
5342 5340
5343 5341 4. With the -C/--clean option, uncommitted changes are discarded and
5344 5342 the working directory is updated to the requested changeset.
5345 5343
5346 5344 To cancel an uncommitted merge (and lose your changes), use
5347 5345 :hg:`update --clean .`.
5348 5346
5349 5347 Use null as the changeset to remove the working directory (like
5350 5348 :hg:`clone -U`).
5351 5349
5352 5350 If you want to revert just one file to an older revision, use
5353 5351 :hg:`revert [-r REV] NAME`.
5354 5352
5355 5353 See :hg:`help dates` for a list of formats valid for -d/--date.
5356 5354
5357 5355 Returns 0 on success, 1 if there are unresolved files.
5358 5356 """
5359 5357 if rev and node:
5360 5358 raise error.Abort(_("please specify just one revision"))
5361 5359
5362 5360 if ui.configbool('commands', 'update.requiredest'):
5363 5361 if not node and not rev and not date:
5364 5362 raise error.Abort(_('you must specify a destination'),
5365 5363 hint=_('for example: hg update ".::"'))
5366 5364
5367 5365 if rev is None or rev == '':
5368 5366 rev = node
5369 5367
5370 5368 if date and rev is not None:
5371 5369 raise error.Abort(_("you can't specify a revision and a date"))
5372 5370
5373 5371 if len([x for x in (clean, check, merge) if x]) > 1:
5374 5372 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5375 5373 "or -m/merge"))
5376 5374
5377 5375 updatecheck = None
5378 5376 if check:
5379 5377 updatecheck = 'abort'
5380 5378 elif merge:
5381 5379 updatecheck = 'none'
5382 5380
5383 5381 with repo.wlock():
5384 5382 cmdutil.clearunfinished(repo)
5385 5383
5386 5384 if date:
5387 5385 rev = cmdutil.finddate(ui, repo, date)
5388 5386
5389 5387 # if we defined a bookmark, we have to remember the original name
5390 5388 brev = rev
5391 5389 rev = scmutil.revsingle(repo, rev, rev).rev()
5392 5390
5393 5391 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5394 5392
5395 5393 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5396 5394 updatecheck=updatecheck)
5397 5395
5398 5396 @command('verify', [])
5399 5397 def verify(ui, repo):
5400 5398 """verify the integrity of the repository
5401 5399
5402 5400 Verify the integrity of the current repository.
5403 5401
5404 5402 This will perform an extensive check of the repository's
5405 5403 integrity, validating the hashes and checksums of each entry in
5406 5404 the changelog, manifest, and tracked files, as well as the
5407 5405 integrity of their crosslinks and indices.
5408 5406
5409 5407 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5410 5408 for more information about recovery from corruption of the
5411 5409 repository.
5412 5410
5413 5411 Returns 0 on success, 1 if errors are encountered.
5414 5412 """
5415 5413 return hg.verify(repo)
5416 5414
5417 5415 @command('version', [] + formatteropts, norepo=True)
5418 5416 def version_(ui, **opts):
5419 5417 """output version and copyright information"""
5420 5418 if ui.verbose:
5421 5419 ui.pager('version')
5422 5420 fm = ui.formatter("version", opts)
5423 5421 fm.startitem()
5424 5422 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5425 5423 util.version())
5426 5424 license = _(
5427 5425 "(see https://mercurial-scm.org for more information)\n"
5428 5426 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5429 5427 "This is free software; see the source for copying conditions. "
5430 5428 "There is NO\nwarranty; "
5431 5429 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5432 5430 )
5433 5431 if not ui.quiet:
5434 5432 fm.plain(license)
5435 5433
5436 5434 if ui.verbose:
5437 5435 fm.plain(_("\nEnabled extensions:\n\n"))
5438 5436 # format names and versions into columns
5439 5437 names = []
5440 5438 vers = []
5441 5439 isinternals = []
5442 5440 for name, module in extensions.extensions():
5443 5441 names.append(name)
5444 5442 vers.append(extensions.moduleversion(module) or None)
5445 5443 isinternals.append(extensions.ismoduleinternal(module))
5446 5444 fn = fm.nested("extensions")
5447 5445 if names:
5448 5446 namefmt = " %%-%ds " % max(len(n) for n in names)
5449 5447 places = [_("external"), _("internal")]
5450 5448 for n, v, p in zip(names, vers, isinternals):
5451 5449 fn.startitem()
5452 5450 fn.condwrite(ui.verbose, "name", namefmt, n)
5453 5451 if ui.verbose:
5454 5452 fn.plain("%s " % places[p])
5455 5453 fn.data(bundled=p)
5456 5454 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5457 5455 if ui.verbose:
5458 5456 fn.plain("\n")
5459 5457 fn.end()
5460 5458 fm.end()
5461 5459
5462 5460 def loadcmdtable(ui, name, cmdtable):
5463 5461 """Load command functions from specified cmdtable
5464 5462 """
5465 5463 overrides = [cmd for cmd in cmdtable if cmd in table]
5466 5464 if overrides:
5467 5465 ui.warn(_("extension '%s' overrides commands: %s\n")
5468 5466 % (name, " ".join(overrides)))
5469 5467 table.update(cmdtable)
@@ -1,227 +1,227 b''
1 1
2 2 $ cat << EOF >> $HGRCPATH
3 3 > [format]
4 4 > usegeneraldelta=yes
5 5 > EOF
6 6
7 7 bundle w/o type option
8 8
9 9 $ hg init t1
10 10 $ hg init t2
11 11 $ cd t1
12 12 $ echo blablablablabla > file.txt
13 13 $ hg ci -Ama
14 14 adding file.txt
15 15 $ hg log | grep summary
16 16 summary: a
17 17 $ hg bundle ../b1 ../t2
18 18 searching for changes
19 19 1 changesets found
20 20
21 21 $ cd ../t2
22 22 $ hg pull ../b1
23 23 pulling from ../b1
24 24 requesting all changes
25 25 adding changesets
26 26 adding manifests
27 27 adding file changes
28 28 added 1 changesets with 1 changes to 1 files
29 29 (run 'hg update' to get a working copy)
30 30 $ hg up
31 31 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 32 $ hg log | grep summary
33 33 summary: a
34 34 $ cd ..
35 35
36 36 Unknown compression type is rejected
37 37
38 38 $ hg init t3
39 39 $ cd t3
40 40 $ hg -q pull ../b1
41 41 $ hg bundle -a -t unknown out.hg
42 42 abort: unknown is not a recognized bundle specification
43 (see 'hg help bundle' for supported values for --type)
43 (see 'hg help bundlespec' for supported values for --type)
44 44 [255]
45 45
46 46 $ hg bundle -a -t unknown-v2 out.hg
47 47 abort: unknown compression is not supported
48 (see 'hg help bundle' for supported values for --type)
48 (see 'hg help bundlespec' for supported values for --type)
49 49 [255]
50 50
51 51 $ cd ..
52 52
53 53 test bundle types
54 54
55 55 $ testbundle() {
56 56 > echo % test bundle type $1
57 57 > hg init t$1
58 58 > cd t1
59 59 > hg bundle -t $1 ../b$1 ../t$1
60 60 > f -q -B6 -D ../b$1; echo
61 61 > cd ../t$1
62 62 > hg debugbundle ../b$1
63 63 > hg debugbundle --spec ../b$1
64 64 > echo
65 65 > cd ..
66 66 > }
67 67
68 68 $ for t in "None" "bzip2" "gzip" "none-v2" "v2" "v1" "gzip-v1"; do
69 69 > testbundle $t
70 70 > done
71 71 % test bundle type None
72 72 searching for changes
73 73 1 changesets found
74 74 HG20\x00\x00 (esc)
75 75 Stream params: {}
76 76 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
77 77 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
78 78 none-v2
79 79
80 80 % test bundle type bzip2
81 81 searching for changes
82 82 1 changesets found
83 83 HG20\x00\x00 (esc)
84 84 Stream params: sortdict([('Compression', 'BZ')])
85 85 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
86 86 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
87 87 bzip2-v2
88 88
89 89 % test bundle type gzip
90 90 searching for changes
91 91 1 changesets found
92 92 HG20\x00\x00 (esc)
93 93 Stream params: sortdict([('Compression', 'GZ')])
94 94 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
95 95 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
96 96 gzip-v2
97 97
98 98 % test bundle type none-v2
99 99 searching for changes
100 100 1 changesets found
101 101 HG20\x00\x00 (esc)
102 102 Stream params: {}
103 103 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
104 104 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
105 105 none-v2
106 106
107 107 % test bundle type v2
108 108 searching for changes
109 109 1 changesets found
110 110 HG20\x00\x00 (esc)
111 111 Stream params: sortdict([('Compression', 'BZ')])
112 112 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
113 113 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
114 114 bzip2-v2
115 115
116 116 % test bundle type v1
117 117 searching for changes
118 118 1 changesets found
119 119 HG10BZ
120 120 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
121 121 bzip2-v1
122 122
123 123 % test bundle type gzip-v1
124 124 searching for changes
125 125 1 changesets found
126 126 HG10GZ
127 127 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
128 128 gzip-v1
129 129
130 130
131 131 Compression level can be adjusted for bundle2 bundles
132 132
133 133 $ hg init test-complevel
134 134 $ cd test-complevel
135 135
136 136 $ cat > file0 << EOF
137 137 > this is a file
138 138 > with some text
139 139 > and some more text
140 140 > and other content
141 141 > EOF
142 142 $ cat > file1 << EOF
143 143 > this is another file
144 144 > with some other content
145 145 > and repeated, repeated, repeated, repeated content
146 146 > EOF
147 147 $ hg -q commit -A -m initial
148 148
149 149 $ hg bundle -a -t gzip-v2 gzip-v2.hg
150 150 1 changesets found
151 151 $ f --size gzip-v2.hg
152 152 gzip-v2.hg: size=427
153 153
154 154 $ hg --config experimental.bundlecomplevel=1 bundle -a -t gzip-v2 gzip-v2-level1.hg
155 155 1 changesets found
156 156 $ f --size gzip-v2-level1.hg
157 157 gzip-v2-level1.hg: size=435
158 158
159 159 $ cd ..
160 160
161 161 #if zstd
162 162
163 163 $ for t in "zstd" "zstd-v2"; do
164 164 > testbundle $t
165 165 > done
166 166 % test bundle type zstd
167 167 searching for changes
168 168 1 changesets found
169 169 HG20\x00\x00 (esc)
170 170 Stream params: sortdict([('Compression', 'ZS')])
171 171 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
172 172 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
173 173 zstd-v2
174 174
175 175 % test bundle type zstd-v2
176 176 searching for changes
177 177 1 changesets found
178 178 HG20\x00\x00 (esc)
179 179 Stream params: sortdict([('Compression', 'ZS')])
180 180 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
181 181 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
182 182 zstd-v2
183 183
184 184
185 185 Explicit request for zstd on non-generaldelta repos
186 186
187 187 $ hg --config format.usegeneraldelta=false init nogd
188 188 $ hg -q -R nogd pull t1
189 189 $ hg -R nogd bundle -a -t zstd nogd-zstd
190 190 1 changesets found
191 191
192 192 zstd-v1 always fails
193 193
194 194 $ hg -R tzstd bundle -a -t zstd-v1 zstd-v1
195 195 abort: compression engine zstd is not supported on v1 bundles
196 (see 'hg help bundle' for supported values for --type)
196 (see 'hg help bundlespec' for supported values for --type)
197 197 [255]
198 198
199 199 #else
200 200
201 201 zstd is a valid engine but isn't available
202 202
203 203 $ hg -R t1 bundle -a -t zstd irrelevant.hg
204 204 abort: compression engine zstd could not be loaded
205 205 [255]
206 206
207 207 #endif
208 208
209 209 test garbage file
210 210
211 211 $ echo garbage > bgarbage
212 212 $ hg init tgarbage
213 213 $ cd tgarbage
214 214 $ hg pull ../bgarbage
215 215 pulling from ../bgarbage
216 216 abort: ../bgarbage: not a Mercurial bundle
217 217 [255]
218 218 $ cd ..
219 219
220 220 test invalid bundle type
221 221
222 222 $ cd t1
223 223 $ hg bundle -a -t garbage ../bgarbage
224 224 abort: garbage is not a recognized bundle specification
225 (see 'hg help bundle' for supported values for --type)
225 (see 'hg help bundlespec' for supported values for --type)
226 226 [255]
227 227 $ cd ..
@@ -1,452 +1,452 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo a > a
4 4 $ hg ci -A -d'1 0' -m a
5 5 adding a
6 6
7 7 $ cd ..
8 8
9 9 $ hg init b
10 10 $ cd b
11 11 $ echo b > b
12 12 $ hg ci -A -d'1 0' -m b
13 13 adding b
14 14
15 15 $ cd ..
16 16
17 17 $ hg clone a c
18 18 updating to branch default
19 19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20 $ cd c
21 21 $ cat >> .hg/hgrc <<EOF
22 22 > [paths]
23 23 > relative = ../a
24 24 > EOF
25 25 $ hg pull -f ../b
26 26 pulling from ../b
27 27 searching for changes
28 28 warning: repository is unrelated
29 29 requesting all changes
30 30 adding changesets
31 31 adding manifests
32 32 adding file changes
33 33 added 1 changesets with 1 changes to 1 files (+1 heads)
34 34 (run 'hg heads' to see heads, 'hg merge' to merge)
35 35 $ hg merge
36 36 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 37 (branch merge, don't forget to commit)
38 38
39 39 $ cd ..
40 40
41 41 Testing -R/--repository:
42 42
43 43 $ hg -R a tip
44 44 changeset: 0:8580ff50825a
45 45 tag: tip
46 46 user: test
47 47 date: Thu Jan 01 00:00:01 1970 +0000
48 48 summary: a
49 49
50 50 $ hg --repository b tip
51 51 changeset: 0:b6c483daf290
52 52 tag: tip
53 53 user: test
54 54 date: Thu Jan 01 00:00:01 1970 +0000
55 55 summary: b
56 56
57 57
58 58 -R with a URL:
59 59
60 60 $ hg -R file:a identify
61 61 8580ff50825a tip
62 62 $ hg -R file://localhost/`pwd`/a/ identify
63 63 8580ff50825a tip
64 64
65 65 -R with path aliases:
66 66
67 67 $ cd c
68 68 $ hg -R default identify
69 69 8580ff50825a tip
70 70 $ hg -R relative identify
71 71 8580ff50825a tip
72 72 $ echo '[paths]' >> $HGRCPATH
73 73 $ echo 'relativetohome = a' >> $HGRCPATH
74 74 $ HOME=`pwd`/../ hg -R relativetohome identify
75 75 8580ff50825a tip
76 76 $ cd ..
77 77
78 78 #if no-outer-repo
79 79
80 80 Implicit -R:
81 81
82 82 $ hg ann a/a
83 83 0: a
84 84 $ hg ann a/a a/a
85 85 0: a
86 86 $ hg ann a/a b/b
87 87 abort: no repository found in '$TESTTMP' (.hg not found)!
88 88 [255]
89 89 $ hg -R b ann a/a
90 90 abort: a/a not under root '$TESTTMP/b' (glob)
91 91 (consider using '--cwd b')
92 92 [255]
93 93 $ hg log
94 94 abort: no repository found in '$TESTTMP' (.hg not found)!
95 95 [255]
96 96
97 97 #endif
98 98
99 99 Abbreviation of long option:
100 100
101 101 $ hg --repo c tip
102 102 changeset: 1:b6c483daf290
103 103 tag: tip
104 104 parent: -1:000000000000
105 105 user: test
106 106 date: Thu Jan 01 00:00:01 1970 +0000
107 107 summary: b
108 108
109 109
110 110 earlygetopt with duplicate options (36d23de02da1):
111 111
112 112 $ hg --cwd a --cwd b --cwd c tip
113 113 changeset: 1:b6c483daf290
114 114 tag: tip
115 115 parent: -1:000000000000
116 116 user: test
117 117 date: Thu Jan 01 00:00:01 1970 +0000
118 118 summary: b
119 119
120 120 $ hg --repo c --repository b -R a tip
121 121 changeset: 0:8580ff50825a
122 122 tag: tip
123 123 user: test
124 124 date: Thu Jan 01 00:00:01 1970 +0000
125 125 summary: a
126 126
127 127
128 128 earlygetopt short option without following space:
129 129
130 130 $ hg -q -Rb tip
131 131 0:b6c483daf290
132 132
133 133 earlygetopt with illegal abbreviations:
134 134
135 135 $ hg --confi "foo.bar=baz"
136 136 abort: option --config may not be abbreviated!
137 137 [255]
138 138 $ hg --cw a tip
139 139 abort: option --cwd may not be abbreviated!
140 140 [255]
141 141 $ hg --rep a tip
142 142 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
143 143 [255]
144 144 $ hg --repositor a tip
145 145 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
146 146 [255]
147 147 $ hg -qR a tip
148 148 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
149 149 [255]
150 150 $ hg -qRa tip
151 151 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
152 152 [255]
153 153
154 154 Testing --cwd:
155 155
156 156 $ hg --cwd a parents
157 157 changeset: 0:8580ff50825a
158 158 tag: tip
159 159 user: test
160 160 date: Thu Jan 01 00:00:01 1970 +0000
161 161 summary: a
162 162
163 163
164 164 Testing -y/--noninteractive - just be sure it is parsed:
165 165
166 166 $ hg --cwd a tip -q --noninteractive
167 167 0:8580ff50825a
168 168 $ hg --cwd a tip -q -y
169 169 0:8580ff50825a
170 170
171 171 Testing -q/--quiet:
172 172
173 173 $ hg -R a -q tip
174 174 0:8580ff50825a
175 175 $ hg -R b -q tip
176 176 0:b6c483daf290
177 177 $ hg -R c --quiet parents
178 178 0:8580ff50825a
179 179 1:b6c483daf290
180 180
181 181 Testing -v/--verbose:
182 182
183 183 $ hg --cwd c head -v
184 184 changeset: 1:b6c483daf290
185 185 tag: tip
186 186 parent: -1:000000000000
187 187 user: test
188 188 date: Thu Jan 01 00:00:01 1970 +0000
189 189 files: b
190 190 description:
191 191 b
192 192
193 193
194 194 changeset: 0:8580ff50825a
195 195 user: test
196 196 date: Thu Jan 01 00:00:01 1970 +0000
197 197 files: a
198 198 description:
199 199 a
200 200
201 201
202 202 $ hg --cwd b tip --verbose
203 203 changeset: 0:b6c483daf290
204 204 tag: tip
205 205 user: test
206 206 date: Thu Jan 01 00:00:01 1970 +0000
207 207 files: b
208 208 description:
209 209 b
210 210
211 211
212 212
213 213 Testing --config:
214 214
215 215 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
216 216 quuxfoo
217 217 $ hg --cwd c --config '' tip -q
218 218 abort: malformed --config option: '' (use --config section.name=value)
219 219 [255]
220 220 $ hg --cwd c --config a.b tip -q
221 221 abort: malformed --config option: 'a.b' (use --config section.name=value)
222 222 [255]
223 223 $ hg --cwd c --config a tip -q
224 224 abort: malformed --config option: 'a' (use --config section.name=value)
225 225 [255]
226 226 $ hg --cwd c --config a.= tip -q
227 227 abort: malformed --config option: 'a.=' (use --config section.name=value)
228 228 [255]
229 229 $ hg --cwd c --config .b= tip -q
230 230 abort: malformed --config option: '.b=' (use --config section.name=value)
231 231 [255]
232 232
233 233 Testing --debug:
234 234
235 235 $ hg --cwd c log --debug
236 236 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
237 237 tag: tip
238 238 phase: public
239 239 parent: -1:0000000000000000000000000000000000000000
240 240 parent: -1:0000000000000000000000000000000000000000
241 241 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
242 242 user: test
243 243 date: Thu Jan 01 00:00:01 1970 +0000
244 244 files+: b
245 245 extra: branch=default
246 246 description:
247 247 b
248 248
249 249
250 250 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
251 251 phase: public
252 252 parent: -1:0000000000000000000000000000000000000000
253 253 parent: -1:0000000000000000000000000000000000000000
254 254 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
255 255 user: test
256 256 date: Thu Jan 01 00:00:01 1970 +0000
257 257 files+: a
258 258 extra: branch=default
259 259 description:
260 260 a
261 261
262 262
263 263
264 264 Testing --traceback:
265 265
266 266 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
267 267 Traceback (most recent call last):
268 268
269 269 Testing --time:
270 270
271 271 $ hg --cwd a --time id
272 272 8580ff50825a tip
273 273 time: real * (glob)
274 274
275 275 Testing --version:
276 276
277 277 $ hg --version -q
278 278 Mercurial Distributed SCM * (glob)
279 279
280 280 hide outer repo
281 281 $ hg init
282 282
283 283 Testing -h/--help:
284 284
285 285 $ hg -h
286 286 Mercurial Distributed SCM
287 287
288 288 list of commands:
289 289
290 290 add add the specified files on the next commit
291 291 addremove add all new files, delete all missing files
292 292 annotate show changeset information by line for each file
293 293 archive create an unversioned archive of a repository revision
294 294 backout reverse effect of earlier changeset
295 295 bisect subdivision search of changesets
296 296 bookmarks create a new bookmark or list existing bookmarks
297 297 branch set or show the current branch name
298 298 branches list repository named branches
299 bundle create a changegroup file
299 bundle create a bundle file
300 300 cat output the current or given revision of files
301 301 clone make a copy of an existing repository
302 302 commit commit the specified files or all outstanding changes
303 303 config show combined config settings from all hgrc files
304 304 copy mark files as copied for the next commit
305 305 diff diff repository (or selected files)
306 306 export dump the header and diffs for one or more changesets
307 307 files list tracked files
308 308 forget forget the specified files on the next commit
309 309 graft copy changes from other branches onto the current branch
310 310 grep search revision history for a pattern in specified files
311 311 heads show branch heads
312 312 help show help for a given topic or a help overview
313 313 identify identify the working directory or specified revision
314 314 import import an ordered set of patches
315 315 incoming show new changesets found in source
316 316 init create a new repository in the given directory
317 317 log show revision history of entire repository or files
318 318 manifest output the current or given revision of the project manifest
319 319 merge merge another revision into working directory
320 320 outgoing show changesets not found in the destination
321 321 paths show aliases for remote repositories
322 322 phase set or show the current phase name
323 323 pull pull changes from the specified source
324 324 push push changes to the specified destination
325 325 recover roll back an interrupted transaction
326 326 remove remove the specified files on the next commit
327 327 rename rename files; equivalent of copy + remove
328 328 resolve redo merges or set/view the merge status of files
329 329 revert restore files to their checkout state
330 330 root print the root (top) of the current working directory
331 331 serve start stand-alone webserver
332 332 status show changed files in the working directory
333 333 summary summarize working directory state
334 334 tag add one or more tags for the current or given revision
335 335 tags list repository tags
336 336 unbundle apply one or more changegroup files
337 337 update update working directory (or switch revisions)
338 338 verify verify the integrity of the repository
339 339 version output version and copyright information
340 340
341 341 additional help topics:
342 342
343 343 bundlespec Bundle File Formats
344 344 color Colorizing Outputs
345 345 config Configuration Files
346 346 dates Date Formats
347 347 diffs Diff Formats
348 348 environment Environment Variables
349 349 extensions Using Additional Features
350 350 filesets Specifying File Sets
351 351 glossary Glossary
352 352 hgignore Syntax for Mercurial Ignore Files
353 353 hgweb Configuring hgweb
354 354 internals Technical implementation topics
355 355 merge-tools Merge Tools
356 356 pager Pager Support
357 357 patterns File Name Patterns
358 358 phases Working with Phases
359 359 revisions Specifying Revisions
360 360 scripting Using Mercurial from scripts and automation
361 361 subrepos Subrepositories
362 362 templating Template Usage
363 363 urls URL Paths
364 364
365 365 (use 'hg help -v' to show built-in aliases and global options)
366 366
367 367
368 368
369 369 $ hg --help
370 370 Mercurial Distributed SCM
371 371
372 372 list of commands:
373 373
374 374 add add the specified files on the next commit
375 375 addremove add all new files, delete all missing files
376 376 annotate show changeset information by line for each file
377 377 archive create an unversioned archive of a repository revision
378 378 backout reverse effect of earlier changeset
379 379 bisect subdivision search of changesets
380 380 bookmarks create a new bookmark or list existing bookmarks
381 381 branch set or show the current branch name
382 382 branches list repository named branches
383 bundle create a changegroup file
383 bundle create a bundle file
384 384 cat output the current or given revision of files
385 385 clone make a copy of an existing repository
386 386 commit commit the specified files or all outstanding changes
387 387 config show combined config settings from all hgrc files
388 388 copy mark files as copied for the next commit
389 389 diff diff repository (or selected files)
390 390 export dump the header and diffs for one or more changesets
391 391 files list tracked files
392 392 forget forget the specified files on the next commit
393 393 graft copy changes from other branches onto the current branch
394 394 grep search revision history for a pattern in specified files
395 395 heads show branch heads
396 396 help show help for a given topic or a help overview
397 397 identify identify the working directory or specified revision
398 398 import import an ordered set of patches
399 399 incoming show new changesets found in source
400 400 init create a new repository in the given directory
401 401 log show revision history of entire repository or files
402 402 manifest output the current or given revision of the project manifest
403 403 merge merge another revision into working directory
404 404 outgoing show changesets not found in the destination
405 405 paths show aliases for remote repositories
406 406 phase set or show the current phase name
407 407 pull pull changes from the specified source
408 408 push push changes to the specified destination
409 409 recover roll back an interrupted transaction
410 410 remove remove the specified files on the next commit
411 411 rename rename files; equivalent of copy + remove
412 412 resolve redo merges or set/view the merge status of files
413 413 revert restore files to their checkout state
414 414 root print the root (top) of the current working directory
415 415 serve start stand-alone webserver
416 416 status show changed files in the working directory
417 417 summary summarize working directory state
418 418 tag add one or more tags for the current or given revision
419 419 tags list repository tags
420 420 unbundle apply one or more changegroup files
421 421 update update working directory (or switch revisions)
422 422 verify verify the integrity of the repository
423 423 version output version and copyright information
424 424
425 425 additional help topics:
426 426
427 427 bundlespec Bundle File Formats
428 428 color Colorizing Outputs
429 429 config Configuration Files
430 430 dates Date Formats
431 431 diffs Diff Formats
432 432 environment Environment Variables
433 433 extensions Using Additional Features
434 434 filesets Specifying File Sets
435 435 glossary Glossary
436 436 hgignore Syntax for Mercurial Ignore Files
437 437 hgweb Configuring hgweb
438 438 internals Technical implementation topics
439 439 merge-tools Merge Tools
440 440 pager Pager Support
441 441 patterns File Name Patterns
442 442 phases Working with Phases
443 443 revisions Specifying Revisions
444 444 scripting Using Mercurial from scripts and automation
445 445 subrepos Subrepositories
446 446 templating Template Usage
447 447 urls URL Paths
448 448
449 449 (use 'hg help -v' to show built-in aliases and global options)
450 450
451 451 Not tested: --debugger
452 452
@@ -1,3324 +1,3324 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks create a new bookmark or list existing bookmarks
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 bundle create a changegroup file
61 bundle create a bundle file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 files list tracked files
70 70 forget forget the specified files on the next commit
71 71 graft copy changes from other branches onto the current branch
72 72 grep search revision history for a pattern in specified files
73 73 heads show branch heads
74 74 help show help for a given topic or a help overview
75 75 identify identify the working directory or specified revision
76 76 import import an ordered set of patches
77 77 incoming show new changesets found in source
78 78 init create a new repository in the given directory
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge another revision into working directory
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 bundlespec Bundle File Formats
106 106 color Colorizing Outputs
107 107 config Configuration Files
108 108 dates Date Formats
109 109 diffs Diff Formats
110 110 environment Environment Variables
111 111 extensions Using Additional Features
112 112 filesets Specifying File Sets
113 113 glossary Glossary
114 114 hgignore Syntax for Mercurial Ignore Files
115 115 hgweb Configuring hgweb
116 116 internals Technical implementation topics
117 117 merge-tools Merge Tools
118 118 pager Pager Support
119 119 patterns File Name Patterns
120 120 phases Working with Phases
121 121 revisions Specifying Revisions
122 122 scripting Using Mercurial from scripts and automation
123 123 subrepos Subrepositories
124 124 templating Template Usage
125 125 urls URL Paths
126 126
127 127 (use 'hg help -v' to show built-in aliases and global options)
128 128
129 129 $ hg -q help
130 130 add add the specified files on the next commit
131 131 addremove add all new files, delete all missing files
132 132 annotate show changeset information by line for each file
133 133 archive create an unversioned archive of a repository revision
134 134 backout reverse effect of earlier changeset
135 135 bisect subdivision search of changesets
136 136 bookmarks create a new bookmark or list existing bookmarks
137 137 branch set or show the current branch name
138 138 branches list repository named branches
139 bundle create a changegroup file
139 bundle create a bundle file
140 140 cat output the current or given revision of files
141 141 clone make a copy of an existing repository
142 142 commit commit the specified files or all outstanding changes
143 143 config show combined config settings from all hgrc files
144 144 copy mark files as copied for the next commit
145 145 diff diff repository (or selected files)
146 146 export dump the header and diffs for one or more changesets
147 147 files list tracked files
148 148 forget forget the specified files on the next commit
149 149 graft copy changes from other branches onto the current branch
150 150 grep search revision history for a pattern in specified files
151 151 heads show branch heads
152 152 help show help for a given topic or a help overview
153 153 identify identify the working directory or specified revision
154 154 import import an ordered set of patches
155 155 incoming show new changesets found in source
156 156 init create a new repository in the given directory
157 157 log show revision history of entire repository or files
158 158 manifest output the current or given revision of the project manifest
159 159 merge merge another revision into working directory
160 160 outgoing show changesets not found in the destination
161 161 paths show aliases for remote repositories
162 162 phase set or show the current phase name
163 163 pull pull changes from the specified source
164 164 push push changes to the specified destination
165 165 recover roll back an interrupted transaction
166 166 remove remove the specified files on the next commit
167 167 rename rename files; equivalent of copy + remove
168 168 resolve redo merges or set/view the merge status of files
169 169 revert restore files to their checkout state
170 170 root print the root (top) of the current working directory
171 171 serve start stand-alone webserver
172 172 status show changed files in the working directory
173 173 summary summarize working directory state
174 174 tag add one or more tags for the current or given revision
175 175 tags list repository tags
176 176 unbundle apply one or more changegroup files
177 177 update update working directory (or switch revisions)
178 178 verify verify the integrity of the repository
179 179 version output version and copyright information
180 180
181 181 additional help topics:
182 182
183 183 bundlespec Bundle File Formats
184 184 color Colorizing Outputs
185 185 config Configuration Files
186 186 dates Date Formats
187 187 diffs Diff Formats
188 188 environment Environment Variables
189 189 extensions Using Additional Features
190 190 filesets Specifying File Sets
191 191 glossary Glossary
192 192 hgignore Syntax for Mercurial Ignore Files
193 193 hgweb Configuring hgweb
194 194 internals Technical implementation topics
195 195 merge-tools Merge Tools
196 196 pager Pager Support
197 197 patterns File Name Patterns
198 198 phases Working with Phases
199 199 revisions Specifying Revisions
200 200 scripting Using Mercurial from scripts and automation
201 201 subrepos Subrepositories
202 202 templating Template Usage
203 203 urls URL Paths
204 204
205 205 Test extension help:
206 206 $ hg help extensions --config extensions.rebase= --config extensions.children=
207 207 Using Additional Features
208 208 """""""""""""""""""""""""
209 209
210 210 Mercurial has the ability to add new features through the use of
211 211 extensions. Extensions may add new commands, add options to existing
212 212 commands, change the default behavior of commands, or implement hooks.
213 213
214 214 To enable the "foo" extension, either shipped with Mercurial or in the
215 215 Python search path, create an entry for it in your configuration file,
216 216 like this:
217 217
218 218 [extensions]
219 219 foo =
220 220
221 221 You may also specify the full path to an extension:
222 222
223 223 [extensions]
224 224 myfeature = ~/.hgext/myfeature.py
225 225
226 226 See 'hg help config' for more information on configuration files.
227 227
228 228 Extensions are not loaded by default for a variety of reasons: they can
229 229 increase startup overhead; they may be meant for advanced usage only; they
230 230 may provide potentially dangerous abilities (such as letting you destroy
231 231 or modify history); they might not be ready for prime time; or they may
232 232 alter some usual behaviors of stock Mercurial. It is thus up to the user
233 233 to activate extensions as needed.
234 234
235 235 To explicitly disable an extension enabled in a configuration file of
236 236 broader scope, prepend its path with !:
237 237
238 238 [extensions]
239 239 # disabling extension bar residing in /path/to/extension/bar.py
240 240 bar = !/path/to/extension/bar.py
241 241 # ditto, but no path was supplied for extension baz
242 242 baz = !
243 243
244 244 enabled extensions:
245 245
246 246 children command to display child changesets (DEPRECATED)
247 247 rebase command to move sets of revisions to a different ancestor
248 248
249 249 disabled extensions:
250 250
251 251 acl hooks for controlling repository access
252 252 blackbox log repository events to a blackbox for debugging
253 253 bugzilla hooks for integrating with the Bugzilla bug tracker
254 254 censor erase file content at a given revision
255 255 churn command to display statistics about repository history
256 256 clonebundles advertise pre-generated bundles to seed clones
257 257 convert import revisions from foreign VCS repositories into
258 258 Mercurial
259 259 eol automatically manage newlines in repository files
260 260 extdiff command to allow external programs to compare revisions
261 261 factotum http authentication with factotum
262 262 gpg commands to sign and verify changesets
263 263 hgk browse the repository in a graphical way
264 264 highlight syntax highlighting for hgweb (requires Pygments)
265 265 histedit interactive history editing
266 266 keyword expand keywords in tracked files
267 267 largefiles track large binary files
268 268 mq manage a stack of patches
269 269 notify hooks for sending email push notifications
270 270 patchbomb command to send changesets as (a series of) patch emails
271 271 purge command to delete untracked files from the working
272 272 directory
273 273 relink recreates hardlinks between repository clones
274 274 schemes extend schemes with shortcuts to repository swarms
275 275 share share a common history between several working directories
276 276 shelve save and restore changes to the working directory
277 277 strip strip changesets and their descendants from history
278 278 transplant command to transplant changesets from another branch
279 279 win32mbcs allow the use of MBCS paths with problematic encodings
280 280 zeroconf discover and advertise repositories on the local network
281 281
282 282 Verify that extension keywords appear in help templates
283 283
284 284 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
285 285
286 286 Test short command list with verbose option
287 287
288 288 $ hg -v help shortlist
289 289 Mercurial Distributed SCM
290 290
291 291 basic commands:
292 292
293 293 add add the specified files on the next commit
294 294 annotate, blame
295 295 show changeset information by line for each file
296 296 clone make a copy of an existing repository
297 297 commit, ci commit the specified files or all outstanding changes
298 298 diff diff repository (or selected files)
299 299 export dump the header and diffs for one or more changesets
300 300 forget forget the specified files on the next commit
301 301 init create a new repository in the given directory
302 302 log, history show revision history of entire repository or files
303 303 merge merge another revision into working directory
304 304 pull pull changes from the specified source
305 305 push push changes to the specified destination
306 306 remove, rm remove the specified files on the next commit
307 307 serve start stand-alone webserver
308 308 status, st show changed files in the working directory
309 309 summary, sum summarize working directory state
310 310 update, up, checkout, co
311 311 update working directory (or switch revisions)
312 312
313 313 global options ([+] can be repeated):
314 314
315 315 -R --repository REPO repository root directory or name of overlay bundle
316 316 file
317 317 --cwd DIR change working directory
318 318 -y --noninteractive do not prompt, automatically pick the first choice for
319 319 all prompts
320 320 -q --quiet suppress output
321 321 -v --verbose enable additional output
322 322 --color TYPE when to colorize (boolean, always, auto, never, or
323 323 debug)
324 324 --config CONFIG [+] set/override config option (use 'section.name=value')
325 325 --debug enable debugging output
326 326 --debugger start debugger
327 327 --encoding ENCODE set the charset encoding (default: ascii)
328 328 --encodingmode MODE set the charset encoding mode (default: strict)
329 329 --traceback always print a traceback on exception
330 330 --time time how long the command takes
331 331 --profile print command execution profile
332 332 --version output version information and exit
333 333 -h --help display help and exit
334 334 --hidden consider hidden changesets
335 335 --pager TYPE when to paginate (boolean, always, auto, or never)
336 336 (default: auto)
337 337
338 338 (use 'hg help' for the full list of commands)
339 339
340 340 $ hg add -h
341 341 hg add [OPTION]... [FILE]...
342 342
343 343 add the specified files on the next commit
344 344
345 345 Schedule files to be version controlled and added to the repository.
346 346
347 347 The files will be added to the repository at the next commit. To undo an
348 348 add before that, see 'hg forget'.
349 349
350 350 If no names are given, add all files to the repository (except files
351 351 matching ".hgignore").
352 352
353 353 Returns 0 if all files are successfully added.
354 354
355 355 options ([+] can be repeated):
356 356
357 357 -I --include PATTERN [+] include names matching the given patterns
358 358 -X --exclude PATTERN [+] exclude names matching the given patterns
359 359 -S --subrepos recurse into subrepositories
360 360 -n --dry-run do not perform actions, just print output
361 361
362 362 (some details hidden, use --verbose to show complete help)
363 363
364 364 Verbose help for add
365 365
366 366 $ hg add -hv
367 367 hg add [OPTION]... [FILE]...
368 368
369 369 add the specified files on the next commit
370 370
371 371 Schedule files to be version controlled and added to the repository.
372 372
373 373 The files will be added to the repository at the next commit. To undo an
374 374 add before that, see 'hg forget'.
375 375
376 376 If no names are given, add all files to the repository (except files
377 377 matching ".hgignore").
378 378
379 379 Examples:
380 380
381 381 - New (unknown) files are added automatically by 'hg add':
382 382
383 383 $ ls
384 384 foo.c
385 385 $ hg status
386 386 ? foo.c
387 387 $ hg add
388 388 adding foo.c
389 389 $ hg status
390 390 A foo.c
391 391
392 392 - Specific files to be added can be specified:
393 393
394 394 $ ls
395 395 bar.c foo.c
396 396 $ hg status
397 397 ? bar.c
398 398 ? foo.c
399 399 $ hg add bar.c
400 400 $ hg status
401 401 A bar.c
402 402 ? foo.c
403 403
404 404 Returns 0 if all files are successfully added.
405 405
406 406 options ([+] can be repeated):
407 407
408 408 -I --include PATTERN [+] include names matching the given patterns
409 409 -X --exclude PATTERN [+] exclude names matching the given patterns
410 410 -S --subrepos recurse into subrepositories
411 411 -n --dry-run do not perform actions, just print output
412 412
413 413 global options ([+] can be repeated):
414 414
415 415 -R --repository REPO repository root directory or name of overlay bundle
416 416 file
417 417 --cwd DIR change working directory
418 418 -y --noninteractive do not prompt, automatically pick the first choice for
419 419 all prompts
420 420 -q --quiet suppress output
421 421 -v --verbose enable additional output
422 422 --color TYPE when to colorize (boolean, always, auto, never, or
423 423 debug)
424 424 --config CONFIG [+] set/override config option (use 'section.name=value')
425 425 --debug enable debugging output
426 426 --debugger start debugger
427 427 --encoding ENCODE set the charset encoding (default: ascii)
428 428 --encodingmode MODE set the charset encoding mode (default: strict)
429 429 --traceback always print a traceback on exception
430 430 --time time how long the command takes
431 431 --profile print command execution profile
432 432 --version output version information and exit
433 433 -h --help display help and exit
434 434 --hidden consider hidden changesets
435 435 --pager TYPE when to paginate (boolean, always, auto, or never)
436 436 (default: auto)
437 437
438 438 Test the textwidth config option
439 439
440 440 $ hg root -h --config ui.textwidth=50
441 441 hg root
442 442
443 443 print the root (top) of the current working
444 444 directory
445 445
446 446 Print the root directory of the current
447 447 repository.
448 448
449 449 Returns 0 on success.
450 450
451 451 (some details hidden, use --verbose to show
452 452 complete help)
453 453
454 454 Test help option with version option
455 455
456 456 $ hg add -h --version
457 457 Mercurial Distributed SCM (version *) (glob)
458 458 (see https://mercurial-scm.org for more information)
459 459
460 460 Copyright (C) 2005-* Matt Mackall and others (glob)
461 461 This is free software; see the source for copying conditions. There is NO
462 462 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
463 463
464 464 $ hg add --skjdfks
465 465 hg add: option --skjdfks not recognized
466 466 hg add [OPTION]... [FILE]...
467 467
468 468 add the specified files on the next commit
469 469
470 470 options ([+] can be repeated):
471 471
472 472 -I --include PATTERN [+] include names matching the given patterns
473 473 -X --exclude PATTERN [+] exclude names matching the given patterns
474 474 -S --subrepos recurse into subrepositories
475 475 -n --dry-run do not perform actions, just print output
476 476
477 477 (use 'hg add -h' to show more help)
478 478 [255]
479 479
480 480 Test ambiguous command help
481 481
482 482 $ hg help ad
483 483 list of commands:
484 484
485 485 add add the specified files on the next commit
486 486 addremove add all new files, delete all missing files
487 487
488 488 (use 'hg help -v ad' to show built-in aliases and global options)
489 489
490 490 Test command without options
491 491
492 492 $ hg help verify
493 493 hg verify
494 494
495 495 verify the integrity of the repository
496 496
497 497 Verify the integrity of the current repository.
498 498
499 499 This will perform an extensive check of the repository's integrity,
500 500 validating the hashes and checksums of each entry in the changelog,
501 501 manifest, and tracked files, as well as the integrity of their crosslinks
502 502 and indices.
503 503
504 504 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
505 505 information about recovery from corruption of the repository.
506 506
507 507 Returns 0 on success, 1 if errors are encountered.
508 508
509 509 (some details hidden, use --verbose to show complete help)
510 510
511 511 $ hg help diff
512 512 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
513 513
514 514 diff repository (or selected files)
515 515
516 516 Show differences between revisions for the specified files.
517 517
518 518 Differences between files are shown using the unified diff format.
519 519
520 520 Note:
521 521 'hg diff' may generate unexpected results for merges, as it will
522 522 default to comparing against the working directory's first parent
523 523 changeset if no revisions are specified.
524 524
525 525 When two revision arguments are given, then changes are shown between
526 526 those revisions. If only one revision is specified then that revision is
527 527 compared to the working directory, and, when no revisions are specified,
528 528 the working directory files are compared to its first parent.
529 529
530 530 Alternatively you can specify -c/--change with a revision to see the
531 531 changes in that changeset relative to its first parent.
532 532
533 533 Without the -a/--text option, diff will avoid generating diffs of files it
534 534 detects as binary. With -a, diff will generate a diff anyway, probably
535 535 with undesirable results.
536 536
537 537 Use the -g/--git option to generate diffs in the git extended diff format.
538 538 For more information, read 'hg help diffs'.
539 539
540 540 Returns 0 on success.
541 541
542 542 options ([+] can be repeated):
543 543
544 544 -r --rev REV [+] revision
545 545 -c --change REV change made by revision
546 546 -a --text treat all files as text
547 547 -g --git use git extended diff format
548 548 --nodates omit dates from diff headers
549 549 --noprefix omit a/ and b/ prefixes from filenames
550 550 -p --show-function show which function each change is in
551 551 --reverse produce a diff that undoes the changes
552 552 -w --ignore-all-space ignore white space when comparing lines
553 553 -b --ignore-space-change ignore changes in the amount of white space
554 554 -B --ignore-blank-lines ignore changes whose lines are all blank
555 555 -U --unified NUM number of lines of context to show
556 556 --stat output diffstat-style summary of changes
557 557 --root DIR produce diffs relative to subdirectory
558 558 -I --include PATTERN [+] include names matching the given patterns
559 559 -X --exclude PATTERN [+] exclude names matching the given patterns
560 560 -S --subrepos recurse into subrepositories
561 561
562 562 (some details hidden, use --verbose to show complete help)
563 563
564 564 $ hg help status
565 565 hg status [OPTION]... [FILE]...
566 566
567 567 aliases: st
568 568
569 569 show changed files in the working directory
570 570
571 571 Show status of files in the repository. If names are given, only files
572 572 that match are shown. Files that are clean or ignored or the source of a
573 573 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
574 574 -C/--copies or -A/--all are given. Unless options described with "show
575 575 only ..." are given, the options -mardu are used.
576 576
577 577 Option -q/--quiet hides untracked (unknown and ignored) files unless
578 578 explicitly requested with -u/--unknown or -i/--ignored.
579 579
580 580 Note:
581 581 'hg status' may appear to disagree with diff if permissions have
582 582 changed or a merge has occurred. The standard diff format does not
583 583 report permission changes and diff only reports changes relative to one
584 584 merge parent.
585 585
586 586 If one revision is given, it is used as the base revision. If two
587 587 revisions are given, the differences between them are shown. The --change
588 588 option can also be used as a shortcut to list the changed files of a
589 589 revision from its first parent.
590 590
591 591 The codes used to show the status of files are:
592 592
593 593 M = modified
594 594 A = added
595 595 R = removed
596 596 C = clean
597 597 ! = missing (deleted by non-hg command, but still tracked)
598 598 ? = not tracked
599 599 I = ignored
600 600 = origin of the previous file (with --copies)
601 601
602 602 Returns 0 on success.
603 603
604 604 options ([+] can be repeated):
605 605
606 606 -A --all show status of all files
607 607 -m --modified show only modified files
608 608 -a --added show only added files
609 609 -r --removed show only removed files
610 610 -d --deleted show only deleted (but tracked) files
611 611 -c --clean show only files without changes
612 612 -u --unknown show only unknown (not tracked) files
613 613 -i --ignored show only ignored files
614 614 -n --no-status hide status prefix
615 615 -C --copies show source of copied files
616 616 -0 --print0 end filenames with NUL, for use with xargs
617 617 --rev REV [+] show difference from revision
618 618 --change REV list the changed files of a revision
619 619 -I --include PATTERN [+] include names matching the given patterns
620 620 -X --exclude PATTERN [+] exclude names matching the given patterns
621 621 -S --subrepos recurse into subrepositories
622 622
623 623 (some details hidden, use --verbose to show complete help)
624 624
625 625 $ hg -q help status
626 626 hg status [OPTION]... [FILE]...
627 627
628 628 show changed files in the working directory
629 629
630 630 $ hg help foo
631 631 abort: no such help topic: foo
632 632 (try 'hg help --keyword foo')
633 633 [255]
634 634
635 635 $ hg skjdfks
636 636 hg: unknown command 'skjdfks'
637 637 Mercurial Distributed SCM
638 638
639 639 basic commands:
640 640
641 641 add add the specified files on the next commit
642 642 annotate show changeset information by line for each file
643 643 clone make a copy of an existing repository
644 644 commit commit the specified files or all outstanding changes
645 645 diff diff repository (or selected files)
646 646 export dump the header and diffs for one or more changesets
647 647 forget forget the specified files on the next commit
648 648 init create a new repository in the given directory
649 649 log show revision history of entire repository or files
650 650 merge merge another revision into working directory
651 651 pull pull changes from the specified source
652 652 push push changes to the specified destination
653 653 remove remove the specified files on the next commit
654 654 serve start stand-alone webserver
655 655 status show changed files in the working directory
656 656 summary summarize working directory state
657 657 update update working directory (or switch revisions)
658 658
659 659 (use 'hg help' for the full list of commands or 'hg -v' for details)
660 660 [255]
661 661
662 662
663 663 Make sure that we don't run afoul of the help system thinking that
664 664 this is a section and erroring out weirdly.
665 665
666 666 $ hg .log
667 667 hg: unknown command '.log'
668 668 (did you mean log?)
669 669 [255]
670 670
671 671 $ hg log.
672 672 hg: unknown command 'log.'
673 673 (did you mean log?)
674 674 [255]
675 675 $ hg pu.lh
676 676 hg: unknown command 'pu.lh'
677 677 (did you mean one of pull, push?)
678 678 [255]
679 679
680 680 $ cat > helpext.py <<EOF
681 681 > import os
682 682 > from mercurial import cmdutil, commands
683 683 >
684 684 > cmdtable = {}
685 685 > command = cmdutil.command(cmdtable)
686 686 >
687 687 > @command('nohelp',
688 688 > [('', 'longdesc', 3, 'x'*90),
689 689 > ('n', '', None, 'normal desc'),
690 690 > ('', 'newline', '', 'line1\nline2')],
691 691 > 'hg nohelp',
692 692 > norepo=True)
693 693 > @command('debugoptADV', [('', 'aopt', None, 'option is (ADVANCED)')])
694 694 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
695 695 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
696 696 > def nohelp(ui, *args, **kwargs):
697 697 > pass
698 698 >
699 699 > def uisetup(ui):
700 700 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
701 701 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
702 702 >
703 703 > EOF
704 704 $ echo '[extensions]' >> $HGRCPATH
705 705 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
706 706
707 707 Test for aliases
708 708
709 709 $ hg help hgalias
710 710 hg hgalias [--remote]
711 711
712 712 alias for: hg summary
713 713
714 714 summarize working directory state
715 715
716 716 This generates a brief summary of the working directory state, including
717 717 parents, branch, commit status, phase and available updates.
718 718
719 719 With the --remote option, this will check the default paths for incoming
720 720 and outgoing changes. This can be time-consuming.
721 721
722 722 Returns 0 on success.
723 723
724 724 defined by: helpext
725 725
726 726 options:
727 727
728 728 --remote check for push and pull
729 729
730 730 (some details hidden, use --verbose to show complete help)
731 731
732 732 $ hg help shellalias
733 733 hg shellalias
734 734
735 735 shell alias for:
736 736
737 737 echo hi
738 738
739 739 defined by: helpext
740 740
741 741 (some details hidden, use --verbose to show complete help)
742 742
743 743 Test command with no help text
744 744
745 745 $ hg help nohelp
746 746 hg nohelp
747 747
748 748 (no help text available)
749 749
750 750 options:
751 751
752 752 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
753 753 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
754 754 -n -- normal desc
755 755 --newline VALUE line1 line2
756 756
757 757 (some details hidden, use --verbose to show complete help)
758 758
759 759 $ hg help -k nohelp
760 760 Commands:
761 761
762 762 nohelp hg nohelp
763 763
764 764 Extension Commands:
765 765
766 766 nohelp (no help text available)
767 767
768 768 Test that default list of commands omits extension commands
769 769
770 770 $ hg help
771 771 Mercurial Distributed SCM
772 772
773 773 list of commands:
774 774
775 775 add add the specified files on the next commit
776 776 addremove add all new files, delete all missing files
777 777 annotate show changeset information by line for each file
778 778 archive create an unversioned archive of a repository revision
779 779 backout reverse effect of earlier changeset
780 780 bisect subdivision search of changesets
781 781 bookmarks create a new bookmark or list existing bookmarks
782 782 branch set or show the current branch name
783 783 branches list repository named branches
784 bundle create a changegroup file
784 bundle create a bundle file
785 785 cat output the current or given revision of files
786 786 clone make a copy of an existing repository
787 787 commit commit the specified files or all outstanding changes
788 788 config show combined config settings from all hgrc files
789 789 copy mark files as copied for the next commit
790 790 diff diff repository (or selected files)
791 791 export dump the header and diffs for one or more changesets
792 792 files list tracked files
793 793 forget forget the specified files on the next commit
794 794 graft copy changes from other branches onto the current branch
795 795 grep search revision history for a pattern in specified files
796 796 heads show branch heads
797 797 help show help for a given topic or a help overview
798 798 identify identify the working directory or specified revision
799 799 import import an ordered set of patches
800 800 incoming show new changesets found in source
801 801 init create a new repository in the given directory
802 802 log show revision history of entire repository or files
803 803 manifest output the current or given revision of the project manifest
804 804 merge merge another revision into working directory
805 805 outgoing show changesets not found in the destination
806 806 paths show aliases for remote repositories
807 807 phase set or show the current phase name
808 808 pull pull changes from the specified source
809 809 push push changes to the specified destination
810 810 recover roll back an interrupted transaction
811 811 remove remove the specified files on the next commit
812 812 rename rename files; equivalent of copy + remove
813 813 resolve redo merges or set/view the merge status of files
814 814 revert restore files to their checkout state
815 815 root print the root (top) of the current working directory
816 816 serve start stand-alone webserver
817 817 status show changed files in the working directory
818 818 summary summarize working directory state
819 819 tag add one or more tags for the current or given revision
820 820 tags list repository tags
821 821 unbundle apply one or more changegroup files
822 822 update update working directory (or switch revisions)
823 823 verify verify the integrity of the repository
824 824 version output version and copyright information
825 825
826 826 enabled extensions:
827 827
828 828 helpext (no help text available)
829 829
830 830 additional help topics:
831 831
832 832 bundlespec Bundle File Formats
833 833 color Colorizing Outputs
834 834 config Configuration Files
835 835 dates Date Formats
836 836 diffs Diff Formats
837 837 environment Environment Variables
838 838 extensions Using Additional Features
839 839 filesets Specifying File Sets
840 840 glossary Glossary
841 841 hgignore Syntax for Mercurial Ignore Files
842 842 hgweb Configuring hgweb
843 843 internals Technical implementation topics
844 844 merge-tools Merge Tools
845 845 pager Pager Support
846 846 patterns File Name Patterns
847 847 phases Working with Phases
848 848 revisions Specifying Revisions
849 849 scripting Using Mercurial from scripts and automation
850 850 subrepos Subrepositories
851 851 templating Template Usage
852 852 urls URL Paths
853 853
854 854 (use 'hg help -v' to show built-in aliases and global options)
855 855
856 856
857 857 Test list of internal help commands
858 858
859 859 $ hg help debug
860 860 debug commands (internal and unsupported):
861 861
862 862 debugancestor
863 863 find the ancestor revision of two revisions in a given index
864 864 debugapplystreamclonebundle
865 865 apply a stream clone bundle file
866 866 debugbuilddag
867 867 builds a repo with a given DAG from scratch in the current
868 868 empty repo
869 869 debugbundle lists the contents of a bundle
870 870 debugcheckstate
871 871 validate the correctness of the current dirstate
872 872 debugcolor show available color, effects or style
873 873 debugcommands
874 874 list all available commands and options
875 875 debugcomplete
876 876 returns the completion list associated with the given command
877 877 debugcreatestreamclonebundle
878 878 create a stream clone bundle file
879 879 debugdag format the changelog or an index DAG as a concise textual
880 880 description
881 881 debugdata dump the contents of a data file revision
882 882 debugdate parse and display a date
883 883 debugdeltachain
884 884 dump information about delta chains in a revlog
885 885 debugdirstate
886 886 show the contents of the current dirstate
887 887 debugdiscovery
888 888 runs the changeset discovery protocol in isolation
889 889 debugextensions
890 890 show information about active extensions
891 891 debugfileset parse and apply a fileset specification
892 892 debugfsinfo show information detected about current filesystem
893 893 debuggetbundle
894 894 retrieves a bundle from a repo
895 895 debugignore display the combined ignore pattern and information about
896 896 ignored files
897 897 debugindex dump the contents of an index file
898 898 debugindexdot
899 899 dump an index DAG as a graphviz dot file
900 900 debuginstall test Mercurial installation
901 901 debugknown test whether node ids are known to a repo
902 902 debuglocks show or modify state of locks
903 903 debugmergestate
904 904 print merge state
905 905 debugnamecomplete
906 906 complete "names" - tags, open branch names, bookmark names
907 907 debugobsolete
908 908 create arbitrary obsolete marker
909 909 debugoptADV (no help text available)
910 910 debugoptDEP (no help text available)
911 911 debugoptEXP (no help text available)
912 912 debugpathcomplete
913 913 complete part or all of a tracked path
914 914 debugpushkey access the pushkey key/value protocol
915 915 debugpvec (no help text available)
916 916 debugrebuilddirstate
917 917 rebuild the dirstate as it would look like for the given
918 918 revision
919 919 debugrebuildfncache
920 920 rebuild the fncache file
921 921 debugrename dump rename information
922 922 debugrevlog show data and statistics about a revlog
923 923 debugrevspec parse and apply a revision specification
924 924 debugsetparents
925 925 manually set the parents of the current working directory
926 926 debugsub (no help text available)
927 927 debugsuccessorssets
928 928 show set of successors for revision
929 929 debugtemplate
930 930 parse and apply a template
931 931 debugupgraderepo
932 932 upgrade a repository to use different features
933 933 debugwalk show how files match on given patterns
934 934 debugwireargs
935 935 (no help text available)
936 936
937 937 (use 'hg help -v debug' to show built-in aliases and global options)
938 938
939 939 internals topic renders index of available sub-topics
940 940
941 941 $ hg help internals
942 942 Technical implementation topics
943 943 """""""""""""""""""""""""""""""
944 944
945 945 bundles Bundles
946 946 censor Censor
947 947 changegroups Changegroups
948 948 requirements Repository Requirements
949 949 revlogs Revision Logs
950 950 wireprotocol Wire Protocol
951 951
952 952 sub-topics can be accessed
953 953
954 954 $ hg help internals.changegroups
955 955 Changegroups
956 956 """"""""""""
957 957
958 958 Changegroups are representations of repository revlog data, specifically
959 959 the changelog data, root/flat manifest data, treemanifest data, and
960 960 filelogs.
961 961
962 962 There are 3 versions of changegroups: "1", "2", and "3". From a high-
963 963 level, versions "1" and "2" are almost exactly the same, with the only
964 964 difference being an additional item in the *delta header*. Version "3"
965 965 adds support for revlog flags in the *delta header* and optionally
966 966 exchanging treemanifests (enabled by setting an option on the
967 967 "changegroup" part in the bundle2).
968 968
969 969 Changegroups when not exchanging treemanifests consist of 3 logical
970 970 segments:
971 971
972 972 +---------------------------------+
973 973 | | | |
974 974 | changeset | manifest | filelogs |
975 975 | | | |
976 976 | | | |
977 977 +---------------------------------+
978 978
979 979 When exchanging treemanifests, there are 4 logical segments:
980 980
981 981 +-------------------------------------------------+
982 982 | | | | |
983 983 | changeset | root | treemanifests | filelogs |
984 984 | | manifest | | |
985 985 | | | | |
986 986 +-------------------------------------------------+
987 987
988 988 The principle building block of each segment is a *chunk*. A *chunk* is a
989 989 framed piece of data:
990 990
991 991 +---------------------------------------+
992 992 | | |
993 993 | length | data |
994 994 | (4 bytes) | (<length - 4> bytes) |
995 995 | | |
996 996 +---------------------------------------+
997 997
998 998 All integers are big-endian signed integers. Each chunk starts with a
999 999 32-bit integer indicating the length of the entire chunk (including the
1000 1000 length field itself).
1001 1001
1002 1002 There is a special case chunk that has a value of 0 for the length
1003 1003 ("0x00000000"). We call this an *empty chunk*.
1004 1004
1005 1005 Delta Groups
1006 1006 ============
1007 1007
1008 1008 A *delta group* expresses the content of a revlog as a series of deltas,
1009 1009 or patches against previous revisions.
1010 1010
1011 1011 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1012 1012 to signal the end of the delta group:
1013 1013
1014 1014 +------------------------------------------------------------------------+
1015 1015 | | | | | |
1016 1016 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1017 1017 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1018 1018 | | | | | |
1019 1019 +------------------------------------------------------------------------+
1020 1020
1021 1021 Each *chunk*'s data consists of the following:
1022 1022
1023 1023 +---------------------------------------+
1024 1024 | | |
1025 1025 | delta header | delta data |
1026 1026 | (various by version) | (various) |
1027 1027 | | |
1028 1028 +---------------------------------------+
1029 1029
1030 1030 The *delta data* is a series of *delta*s that describe a diff from an
1031 1031 existing entry (either that the recipient already has, or previously
1032 1032 specified in the bundlei/changegroup).
1033 1033
1034 1034 The *delta header* is different between versions "1", "2", and "3" of the
1035 1035 changegroup format.
1036 1036
1037 1037 Version 1 (headerlen=80):
1038 1038
1039 1039 +------------------------------------------------------+
1040 1040 | | | | |
1041 1041 | node | p1 node | p2 node | link node |
1042 1042 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1043 1043 | | | | |
1044 1044 +------------------------------------------------------+
1045 1045
1046 1046 Version 2 (headerlen=100):
1047 1047
1048 1048 +------------------------------------------------------------------+
1049 1049 | | | | | |
1050 1050 | node | p1 node | p2 node | base node | link node |
1051 1051 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1052 1052 | | | | | |
1053 1053 +------------------------------------------------------------------+
1054 1054
1055 1055 Version 3 (headerlen=102):
1056 1056
1057 1057 +------------------------------------------------------------------------------+
1058 1058 | | | | | | |
1059 1059 | node | p1 node | p2 node | base node | link node | flags |
1060 1060 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1061 1061 | | | | | | |
1062 1062 +------------------------------------------------------------------------------+
1063 1063
1064 1064 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1065 1065 contain a series of *delta*s, densely packed (no separators). These deltas
1066 1066 describe a diff from an existing entry (either that the recipient already
1067 1067 has, or previously specified in the bundle/changegroup). The format is
1068 1068 described more fully in "hg help internals.bdiff", but briefly:
1069 1069
1070 1070 +---------------------------------------------------------------+
1071 1071 | | | | |
1072 1072 | start offset | end offset | new length | content |
1073 1073 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1074 1074 | | | | |
1075 1075 +---------------------------------------------------------------+
1076 1076
1077 1077 Please note that the length field in the delta data does *not* include
1078 1078 itself.
1079 1079
1080 1080 In version 1, the delta is always applied against the previous node from
1081 1081 the changegroup or the first parent if this is the first entry in the
1082 1082 changegroup.
1083 1083
1084 1084 In version 2 and up, the delta base node is encoded in the entry in the
1085 1085 changegroup. This allows the delta to be expressed against any parent,
1086 1086 which can result in smaller deltas and more efficient encoding of data.
1087 1087
1088 1088 Changeset Segment
1089 1089 =================
1090 1090
1091 1091 The *changeset segment* consists of a single *delta group* holding
1092 1092 changelog data. The *empty chunk* at the end of the *delta group* denotes
1093 1093 the boundary to the *manifest segment*.
1094 1094
1095 1095 Manifest Segment
1096 1096 ================
1097 1097
1098 1098 The *manifest segment* consists of a single *delta group* holding manifest
1099 1099 data. If treemanifests are in use, it contains only the manifest for the
1100 1100 root directory of the repository. Otherwise, it contains the entire
1101 1101 manifest data. The *empty chunk* at the end of the *delta group* denotes
1102 1102 the boundary to the next segment (either the *treemanifests segment* or
1103 1103 the *filelogs segment*, depending on version and the request options).
1104 1104
1105 1105 Treemanifests Segment
1106 1106 ---------------------
1107 1107
1108 1108 The *treemanifests segment* only exists in changegroup version "3", and
1109 1109 only if the 'treemanifest' param is part of the bundle2 changegroup part
1110 1110 (it is not possible to use changegroup version 3 outside of bundle2).
1111 1111 Aside from the filenames in the *treemanifests segment* containing a
1112 1112 trailing "/" character, it behaves identically to the *filelogs segment*
1113 1113 (see below). The final sub-segment is followed by an *empty chunk*
1114 1114 (logically, a sub-segment with filename size 0). This denotes the boundary
1115 1115 to the *filelogs segment*.
1116 1116
1117 1117 Filelogs Segment
1118 1118 ================
1119 1119
1120 1120 The *filelogs segment* consists of multiple sub-segments, each
1121 1121 corresponding to an individual file whose data is being described:
1122 1122
1123 1123 +--------------------------------------------------+
1124 1124 | | | | | |
1125 1125 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1126 1126 | | | | | (4 bytes) |
1127 1127 | | | | | |
1128 1128 +--------------------------------------------------+
1129 1129
1130 1130 The final filelog sub-segment is followed by an *empty chunk* (logically,
1131 1131 a sub-segment with filename size 0). This denotes the end of the segment
1132 1132 and of the overall changegroup.
1133 1133
1134 1134 Each filelog sub-segment consists of the following:
1135 1135
1136 1136 +------------------------------------------------------+
1137 1137 | | | |
1138 1138 | filename length | filename | delta group |
1139 1139 | (4 bytes) | (<length - 4> bytes) | (various) |
1140 1140 | | | |
1141 1141 +------------------------------------------------------+
1142 1142
1143 1143 That is, a *chunk* consisting of the filename (not terminated or padded)
1144 1144 followed by N chunks constituting the *delta group* for this file. The
1145 1145 *empty chunk* at the end of each *delta group* denotes the boundary to the
1146 1146 next filelog sub-segment.
1147 1147
1148 1148 Test list of commands with command with no help text
1149 1149
1150 1150 $ hg help helpext
1151 1151 helpext extension - no help text available
1152 1152
1153 1153 list of commands:
1154 1154
1155 1155 nohelp (no help text available)
1156 1156
1157 1157 (use 'hg help -v helpext' to show built-in aliases and global options)
1158 1158
1159 1159
1160 1160 test advanced, deprecated and experimental options are hidden in command help
1161 1161 $ hg help debugoptADV
1162 1162 hg debugoptADV
1163 1163
1164 1164 (no help text available)
1165 1165
1166 1166 options:
1167 1167
1168 1168 (some details hidden, use --verbose to show complete help)
1169 1169 $ hg help debugoptDEP
1170 1170 hg debugoptDEP
1171 1171
1172 1172 (no help text available)
1173 1173
1174 1174 options:
1175 1175
1176 1176 (some details hidden, use --verbose to show complete help)
1177 1177
1178 1178 $ hg help debugoptEXP
1179 1179 hg debugoptEXP
1180 1180
1181 1181 (no help text available)
1182 1182
1183 1183 options:
1184 1184
1185 1185 (some details hidden, use --verbose to show complete help)
1186 1186
1187 1187 test advanced, deprecated and experimental options are shown with -v
1188 1188 $ hg help -v debugoptADV | grep aopt
1189 1189 --aopt option is (ADVANCED)
1190 1190 $ hg help -v debugoptDEP | grep dopt
1191 1191 --dopt option is (DEPRECATED)
1192 1192 $ hg help -v debugoptEXP | grep eopt
1193 1193 --eopt option is (EXPERIMENTAL)
1194 1194
1195 1195 #if gettext
1196 1196 test deprecated option is hidden with translation with untranslated description
1197 1197 (use many globy for not failing on changed transaction)
1198 1198 $ LANGUAGE=sv hg help debugoptDEP
1199 1199 hg debugoptDEP
1200 1200
1201 1201 (*) (glob)
1202 1202
1203 1203 options:
1204 1204
1205 1205 (some details hidden, use --verbose to show complete help)
1206 1206 #endif
1207 1207
1208 1208 Test commands that collide with topics (issue4240)
1209 1209
1210 1210 $ hg config -hq
1211 1211 hg config [-u] [NAME]...
1212 1212
1213 1213 show combined config settings from all hgrc files
1214 1214 $ hg showconfig -hq
1215 1215 hg config [-u] [NAME]...
1216 1216
1217 1217 show combined config settings from all hgrc files
1218 1218
1219 1219 Test a help topic
1220 1220
1221 1221 $ hg help dates
1222 1222 Date Formats
1223 1223 """"""""""""
1224 1224
1225 1225 Some commands allow the user to specify a date, e.g.:
1226 1226
1227 1227 - backout, commit, import, tag: Specify the commit date.
1228 1228 - log, revert, update: Select revision(s) by date.
1229 1229
1230 1230 Many date formats are valid. Here are some examples:
1231 1231
1232 1232 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1233 1233 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1234 1234 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1235 1235 - "Dec 6" (midnight)
1236 1236 - "13:18" (today assumed)
1237 1237 - "3:39" (3:39AM assumed)
1238 1238 - "3:39pm" (15:39)
1239 1239 - "2006-12-06 13:18:29" (ISO 8601 format)
1240 1240 - "2006-12-6 13:18"
1241 1241 - "2006-12-6"
1242 1242 - "12-6"
1243 1243 - "12/6"
1244 1244 - "12/6/6" (Dec 6 2006)
1245 1245 - "today" (midnight)
1246 1246 - "yesterday" (midnight)
1247 1247 - "now" - right now
1248 1248
1249 1249 Lastly, there is Mercurial's internal format:
1250 1250
1251 1251 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1252 1252
1253 1253 This is the internal representation format for dates. The first number is
1254 1254 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1255 1255 is the offset of the local timezone, in seconds west of UTC (negative if
1256 1256 the timezone is east of UTC).
1257 1257
1258 1258 The log command also accepts date ranges:
1259 1259
1260 1260 - "<DATE" - at or before a given date/time
1261 1261 - ">DATE" - on or after a given date/time
1262 1262 - "DATE to DATE" - a date range, inclusive
1263 1263 - "-DAYS" - within a given number of days of today
1264 1264
1265 1265 Test repeated config section name
1266 1266
1267 1267 $ hg help config.host
1268 1268 "http_proxy.host"
1269 1269 Host name and (optional) port of the proxy server, for example
1270 1270 "myproxy:8000".
1271 1271
1272 1272 "smtp.host"
1273 1273 Host name of mail server, e.g. "mail.example.com".
1274 1274
1275 1275 Unrelated trailing paragraphs shouldn't be included
1276 1276
1277 1277 $ hg help config.extramsg | grep '^$'
1278 1278
1279 1279
1280 1280 Test capitalized section name
1281 1281
1282 1282 $ hg help scripting.HGPLAIN > /dev/null
1283 1283
1284 1284 Help subsection:
1285 1285
1286 1286 $ hg help config.charsets |grep "Email example:" > /dev/null
1287 1287 [1]
1288 1288
1289 1289 Show nested definitions
1290 1290 ("profiling.type"[break]"ls"[break]"stat"[break])
1291 1291
1292 1292 $ hg help config.type | egrep '^$'|wc -l
1293 1293 \s*3 (re)
1294 1294
1295 1295 Separate sections from subsections
1296 1296
1297 1297 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1298 1298 "format"
1299 1299 --------
1300 1300
1301 1301 "usegeneraldelta"
1302 1302
1303 1303 "dotencode"
1304 1304
1305 1305 "usefncache"
1306 1306
1307 1307 "usestore"
1308 1308
1309 1309 "profiling"
1310 1310 -----------
1311 1311
1312 1312 "format"
1313 1313
1314 1314 "progress"
1315 1315 ----------
1316 1316
1317 1317 "format"
1318 1318
1319 1319
1320 1320 Last item in help config.*:
1321 1321
1322 1322 $ hg help config.`hg help config|grep '^ "'| \
1323 1323 > tail -1|sed 's![ "]*!!g'`| \
1324 1324 > grep 'hg help -c config' > /dev/null
1325 1325 [1]
1326 1326
1327 1327 note to use help -c for general hg help config:
1328 1328
1329 1329 $ hg help config |grep 'hg help -c config' > /dev/null
1330 1330
1331 1331 Test templating help
1332 1332
1333 1333 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1334 1334 desc String. The text of the changeset description.
1335 1335 diffstat String. Statistics of changes with the following format:
1336 1336 firstline Any text. Returns the first line of text.
1337 1337 nonempty Any text. Returns '(none)' if the string is empty.
1338 1338
1339 1339 Test deprecated items
1340 1340
1341 1341 $ hg help -v templating | grep currentbookmark
1342 1342 currentbookmark
1343 1343 $ hg help templating | (grep currentbookmark || true)
1344 1344
1345 1345 Test help hooks
1346 1346
1347 1347 $ cat > helphook1.py <<EOF
1348 1348 > from mercurial import help
1349 1349 >
1350 1350 > def rewrite(ui, topic, doc):
1351 1351 > return doc + '\nhelphook1\n'
1352 1352 >
1353 1353 > def extsetup(ui):
1354 1354 > help.addtopichook('revisions', rewrite)
1355 1355 > EOF
1356 1356 $ cat > helphook2.py <<EOF
1357 1357 > from mercurial import help
1358 1358 >
1359 1359 > def rewrite(ui, topic, doc):
1360 1360 > return doc + '\nhelphook2\n'
1361 1361 >
1362 1362 > def extsetup(ui):
1363 1363 > help.addtopichook('revisions', rewrite)
1364 1364 > EOF
1365 1365 $ echo '[extensions]' >> $HGRCPATH
1366 1366 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1367 1367 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1368 1368 $ hg help revsets | grep helphook
1369 1369 helphook1
1370 1370 helphook2
1371 1371
1372 1372 help -c should only show debug --debug
1373 1373
1374 1374 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1375 1375 [1]
1376 1376
1377 1377 help -c should only show deprecated for -v
1378 1378
1379 1379 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1380 1380 [1]
1381 1381
1382 1382 Test -s / --system
1383 1383
1384 1384 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1385 1385 > wc -l | sed -e 's/ //g'
1386 1386 0
1387 1387 $ hg help config.files --system unix | grep 'USER' | \
1388 1388 > wc -l | sed -e 's/ //g'
1389 1389 0
1390 1390
1391 1391 Test -e / -c / -k combinations
1392 1392
1393 1393 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1394 1394 Commands:
1395 1395 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1396 1396 Extensions:
1397 1397 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1398 1398 Topics:
1399 1399 Commands:
1400 1400 Extensions:
1401 1401 Extension Commands:
1402 1402 $ hg help -c schemes
1403 1403 abort: no such help topic: schemes
1404 1404 (try 'hg help --keyword schemes')
1405 1405 [255]
1406 1406 $ hg help -e schemes |head -1
1407 1407 schemes extension - extend schemes with shortcuts to repository swarms
1408 1408 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1409 1409 Commands:
1410 1410 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1411 1411 Extensions:
1412 1412 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1413 1413 Extensions:
1414 1414 Commands:
1415 1415 $ hg help -c commit > /dev/null
1416 1416 $ hg help -e -c commit > /dev/null
1417 1417 $ hg help -e commit > /dev/null
1418 1418 abort: no such help topic: commit
1419 1419 (try 'hg help --keyword commit')
1420 1420 [255]
1421 1421
1422 1422 Test keyword search help
1423 1423
1424 1424 $ cat > prefixedname.py <<EOF
1425 1425 > '''matched against word "clone"
1426 1426 > '''
1427 1427 > EOF
1428 1428 $ echo '[extensions]' >> $HGRCPATH
1429 1429 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1430 1430 $ hg help -k clone
1431 1431 Topics:
1432 1432
1433 1433 config Configuration Files
1434 1434 extensions Using Additional Features
1435 1435 glossary Glossary
1436 1436 phases Working with Phases
1437 1437 subrepos Subrepositories
1438 1438 urls URL Paths
1439 1439
1440 1440 Commands:
1441 1441
1442 1442 bookmarks create a new bookmark or list existing bookmarks
1443 1443 clone make a copy of an existing repository
1444 1444 paths show aliases for remote repositories
1445 1445 update update working directory (or switch revisions)
1446 1446
1447 1447 Extensions:
1448 1448
1449 1449 clonebundles advertise pre-generated bundles to seed clones
1450 1450 prefixedname matched against word "clone"
1451 1451 relink recreates hardlinks between repository clones
1452 1452
1453 1453 Extension Commands:
1454 1454
1455 1455 qclone clone main and patch repository at same time
1456 1456
1457 1457 Test unfound topic
1458 1458
1459 1459 $ hg help nonexistingtopicthatwillneverexisteverever
1460 1460 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1461 1461 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1462 1462 [255]
1463 1463
1464 1464 Test unfound keyword
1465 1465
1466 1466 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1467 1467 abort: no matches
1468 1468 (try 'hg help' for a list of topics)
1469 1469 [255]
1470 1470
1471 1471 Test omit indicating for help
1472 1472
1473 1473 $ cat > addverboseitems.py <<EOF
1474 1474 > '''extension to test omit indicating.
1475 1475 >
1476 1476 > This paragraph is never omitted (for extension)
1477 1477 >
1478 1478 > .. container:: verbose
1479 1479 >
1480 1480 > This paragraph is omitted,
1481 1481 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1482 1482 >
1483 1483 > This paragraph is never omitted, too (for extension)
1484 1484 > '''
1485 1485 >
1486 1486 > from mercurial import help, commands
1487 1487 > testtopic = """This paragraph is never omitted (for topic).
1488 1488 >
1489 1489 > .. container:: verbose
1490 1490 >
1491 1491 > This paragraph is omitted,
1492 1492 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1493 1493 >
1494 1494 > This paragraph is never omitted, too (for topic)
1495 1495 > """
1496 1496 > def extsetup(ui):
1497 1497 > help.helptable.append((["topic-containing-verbose"],
1498 1498 > "This is the topic to test omit indicating.",
1499 1499 > lambda ui: testtopic))
1500 1500 > EOF
1501 1501 $ echo '[extensions]' >> $HGRCPATH
1502 1502 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1503 1503 $ hg help addverboseitems
1504 1504 addverboseitems extension - extension to test omit indicating.
1505 1505
1506 1506 This paragraph is never omitted (for extension)
1507 1507
1508 1508 This paragraph is never omitted, too (for extension)
1509 1509
1510 1510 (some details hidden, use --verbose to show complete help)
1511 1511
1512 1512 no commands defined
1513 1513 $ hg help -v addverboseitems
1514 1514 addverboseitems extension - extension to test omit indicating.
1515 1515
1516 1516 This paragraph is never omitted (for extension)
1517 1517
1518 1518 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1519 1519 extension)
1520 1520
1521 1521 This paragraph is never omitted, too (for extension)
1522 1522
1523 1523 no commands defined
1524 1524 $ hg help topic-containing-verbose
1525 1525 This is the topic to test omit indicating.
1526 1526 """"""""""""""""""""""""""""""""""""""""""
1527 1527
1528 1528 This paragraph is never omitted (for topic).
1529 1529
1530 1530 This paragraph is never omitted, too (for topic)
1531 1531
1532 1532 (some details hidden, use --verbose to show complete help)
1533 1533 $ hg help -v topic-containing-verbose
1534 1534 This is the topic to test omit indicating.
1535 1535 """"""""""""""""""""""""""""""""""""""""""
1536 1536
1537 1537 This paragraph is never omitted (for topic).
1538 1538
1539 1539 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1540 1540 topic)
1541 1541
1542 1542 This paragraph is never omitted, too (for topic)
1543 1543
1544 1544 Test section lookup
1545 1545
1546 1546 $ hg help revset.merge
1547 1547 "merge()"
1548 1548 Changeset is a merge changeset.
1549 1549
1550 1550 $ hg help glossary.dag
1551 1551 DAG
1552 1552 The repository of changesets of a distributed version control system
1553 1553 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1554 1554 of nodes and edges, where nodes correspond to changesets and edges
1555 1555 imply a parent -> child relation. This graph can be visualized by
1556 1556 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1557 1557 limited by the requirement for children to have at most two parents.
1558 1558
1559 1559
1560 1560 $ hg help hgrc.paths
1561 1561 "paths"
1562 1562 -------
1563 1563
1564 1564 Assigns symbolic names and behavior to repositories.
1565 1565
1566 1566 Options are symbolic names defining the URL or directory that is the
1567 1567 location of the repository. Example:
1568 1568
1569 1569 [paths]
1570 1570 my_server = https://example.com/my_repo
1571 1571 local_path = /home/me/repo
1572 1572
1573 1573 These symbolic names can be used from the command line. To pull from
1574 1574 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1575 1575 local_path'.
1576 1576
1577 1577 Options containing colons (":") denote sub-options that can influence
1578 1578 behavior for that specific path. Example:
1579 1579
1580 1580 [paths]
1581 1581 my_server = https://example.com/my_path
1582 1582 my_server:pushurl = ssh://example.com/my_path
1583 1583
1584 1584 The following sub-options can be defined:
1585 1585
1586 1586 "pushurl"
1587 1587 The URL to use for push operations. If not defined, the location
1588 1588 defined by the path's main entry is used.
1589 1589
1590 1590 "pushrev"
1591 1591 A revset defining which revisions to push by default.
1592 1592
1593 1593 When 'hg push' is executed without a "-r" argument, the revset defined
1594 1594 by this sub-option is evaluated to determine what to push.
1595 1595
1596 1596 For example, a value of "." will push the working directory's revision
1597 1597 by default.
1598 1598
1599 1599 Revsets specifying bookmarks will not result in the bookmark being
1600 1600 pushed.
1601 1601
1602 1602 The following special named paths exist:
1603 1603
1604 1604 "default"
1605 1605 The URL or directory to use when no source or remote is specified.
1606 1606
1607 1607 'hg clone' will automatically define this path to the location the
1608 1608 repository was cloned from.
1609 1609
1610 1610 "default-push"
1611 1611 (deprecated) The URL or directory for the default 'hg push' location.
1612 1612 "default:pushurl" should be used instead.
1613 1613
1614 1614 $ hg help glossary.mcguffin
1615 1615 abort: help section not found: glossary.mcguffin
1616 1616 [255]
1617 1617
1618 1618 $ hg help glossary.mc.guffin
1619 1619 abort: help section not found: glossary.mc.guffin
1620 1620 [255]
1621 1621
1622 1622 $ hg help template.files
1623 1623 files List of strings. All files modified, added, or removed by
1624 1624 this changeset.
1625 1625 files(pattern)
1626 1626 All files of the current changeset matching the pattern. See
1627 1627 'hg help patterns'.
1628 1628
1629 1629 Test section lookup by translated message
1630 1630
1631 1631 str.lower() instead of encoding.lower(str) on translated message might
1632 1632 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1633 1633 as the second or later byte of multi-byte character.
1634 1634
1635 1635 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1636 1636 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1637 1637 replacement makes message meaningless.
1638 1638
1639 1639 This tests that section lookup by translated string isn't broken by
1640 1640 such str.lower().
1641 1641
1642 1642 $ python <<EOF
1643 1643 > def escape(s):
1644 1644 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1645 1645 > # translation of "record" in ja_JP.cp932
1646 1646 > upper = "\x8bL\x98^"
1647 1647 > # str.lower()-ed section name should be treated as different one
1648 1648 > lower = "\x8bl\x98^"
1649 1649 > with open('ambiguous.py', 'w') as fp:
1650 1650 > fp.write("""# ambiguous section names in ja_JP.cp932
1651 1651 > u'''summary of extension
1652 1652 >
1653 1653 > %s
1654 1654 > ----
1655 1655 >
1656 1656 > Upper name should show only this message
1657 1657 >
1658 1658 > %s
1659 1659 > ----
1660 1660 >
1661 1661 > Lower name should show only this message
1662 1662 >
1663 1663 > subsequent section
1664 1664 > ------------------
1665 1665 >
1666 1666 > This should be hidden at 'hg help ambiguous' with section name.
1667 1667 > '''
1668 1668 > """ % (escape(upper), escape(lower)))
1669 1669 > EOF
1670 1670
1671 1671 $ cat >> $HGRCPATH <<EOF
1672 1672 > [extensions]
1673 1673 > ambiguous = ./ambiguous.py
1674 1674 > EOF
1675 1675
1676 1676 $ python <<EOF | sh
1677 1677 > upper = "\x8bL\x98^"
1678 1678 > print "hg --encoding cp932 help -e ambiguous.%s" % upper
1679 1679 > EOF
1680 1680 \x8bL\x98^ (esc)
1681 1681 ----
1682 1682
1683 1683 Upper name should show only this message
1684 1684
1685 1685
1686 1686 $ python <<EOF | sh
1687 1687 > lower = "\x8bl\x98^"
1688 1688 > print "hg --encoding cp932 help -e ambiguous.%s" % lower
1689 1689 > EOF
1690 1690 \x8bl\x98^ (esc)
1691 1691 ----
1692 1692
1693 1693 Lower name should show only this message
1694 1694
1695 1695
1696 1696 $ cat >> $HGRCPATH <<EOF
1697 1697 > [extensions]
1698 1698 > ambiguous = !
1699 1699 > EOF
1700 1700
1701 1701 Show help content of disabled extensions
1702 1702
1703 1703 $ cat >> $HGRCPATH <<EOF
1704 1704 > [extensions]
1705 1705 > ambiguous = !./ambiguous.py
1706 1706 > EOF
1707 1707 $ hg help -e ambiguous
1708 1708 ambiguous extension - (no help text available)
1709 1709
1710 1710 (use 'hg help extensions' for information on enabling extensions)
1711 1711
1712 1712 Test dynamic list of merge tools only shows up once
1713 1713 $ hg help merge-tools
1714 1714 Merge Tools
1715 1715 """""""""""
1716 1716
1717 1717 To merge files Mercurial uses merge tools.
1718 1718
1719 1719 A merge tool combines two different versions of a file into a merged file.
1720 1720 Merge tools are given the two files and the greatest common ancestor of
1721 1721 the two file versions, so they can determine the changes made on both
1722 1722 branches.
1723 1723
1724 1724 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1725 1725 backout' and in several extensions.
1726 1726
1727 1727 Usually, the merge tool tries to automatically reconcile the files by
1728 1728 combining all non-overlapping changes that occurred separately in the two
1729 1729 different evolutions of the same initial base file. Furthermore, some
1730 1730 interactive merge programs make it easier to manually resolve conflicting
1731 1731 merges, either in a graphical way, or by inserting some conflict markers.
1732 1732 Mercurial does not include any interactive merge programs but relies on
1733 1733 external tools for that.
1734 1734
1735 1735 Available merge tools
1736 1736 =====================
1737 1737
1738 1738 External merge tools and their properties are configured in the merge-
1739 1739 tools configuration section - see hgrc(5) - but they can often just be
1740 1740 named by their executable.
1741 1741
1742 1742 A merge tool is generally usable if its executable can be found on the
1743 1743 system and if it can handle the merge. The executable is found if it is an
1744 1744 absolute or relative executable path or the name of an application in the
1745 1745 executable search path. The tool is assumed to be able to handle the merge
1746 1746 if it can handle symlinks if the file is a symlink, if it can handle
1747 1747 binary files if the file is binary, and if a GUI is available if the tool
1748 1748 requires a GUI.
1749 1749
1750 1750 There are some internal merge tools which can be used. The internal merge
1751 1751 tools are:
1752 1752
1753 1753 ":dump"
1754 1754 Creates three versions of the files to merge, containing the contents of
1755 1755 local, other and base. These files can then be used to perform a merge
1756 1756 manually. If the file to be merged is named "a.txt", these files will
1757 1757 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1758 1758 they will be placed in the same directory as "a.txt".
1759 1759
1760 1760 ":fail"
1761 1761 Rather than attempting to merge files that were modified on both
1762 1762 branches, it marks them as unresolved. The resolve command must be used
1763 1763 to resolve these conflicts.
1764 1764
1765 1765 ":local"
1766 1766 Uses the local 'p1()' version of files as the merged version.
1767 1767
1768 1768 ":merge"
1769 1769 Uses the internal non-interactive simple merge algorithm for merging
1770 1770 files. It will fail if there are any conflicts and leave markers in the
1771 1771 partially merged file. Markers will have two sections, one for each side
1772 1772 of merge.
1773 1773
1774 1774 ":merge-local"
1775 1775 Like :merge, but resolve all conflicts non-interactively in favor of the
1776 1776 local 'p1()' changes.
1777 1777
1778 1778 ":merge-other"
1779 1779 Like :merge, but resolve all conflicts non-interactively in favor of the
1780 1780 other 'p2()' changes.
1781 1781
1782 1782 ":merge3"
1783 1783 Uses the internal non-interactive simple merge algorithm for merging
1784 1784 files. It will fail if there are any conflicts and leave markers in the
1785 1785 partially merged file. Marker will have three sections, one from each
1786 1786 side of the merge and one for the base content.
1787 1787
1788 1788 ":other"
1789 1789 Uses the other 'p2()' version of files as the merged version.
1790 1790
1791 1791 ":prompt"
1792 1792 Asks the user which of the local 'p1()' or the other 'p2()' version to
1793 1793 keep as the merged version.
1794 1794
1795 1795 ":tagmerge"
1796 1796 Uses the internal tag merge algorithm (experimental).
1797 1797
1798 1798 ":union"
1799 1799 Uses the internal non-interactive simple merge algorithm for merging
1800 1800 files. It will use both left and right sides for conflict regions. No
1801 1801 markers are inserted.
1802 1802
1803 1803 Internal tools are always available and do not require a GUI but will by
1804 1804 default not handle symlinks or binary files.
1805 1805
1806 1806 Choosing a merge tool
1807 1807 =====================
1808 1808
1809 1809 Mercurial uses these rules when deciding which merge tool to use:
1810 1810
1811 1811 1. If a tool has been specified with the --tool option to merge or
1812 1812 resolve, it is used. If it is the name of a tool in the merge-tools
1813 1813 configuration, its configuration is used. Otherwise the specified tool
1814 1814 must be executable by the shell.
1815 1815 2. If the "HGMERGE" environment variable is present, its value is used and
1816 1816 must be executable by the shell.
1817 1817 3. If the filename of the file to be merged matches any of the patterns in
1818 1818 the merge-patterns configuration section, the first usable merge tool
1819 1819 corresponding to a matching pattern is used. Here, binary capabilities
1820 1820 of the merge tool are not considered.
1821 1821 4. If ui.merge is set it will be considered next. If the value is not the
1822 1822 name of a configured tool, the specified value is used and must be
1823 1823 executable by the shell. Otherwise the named tool is used if it is
1824 1824 usable.
1825 1825 5. If any usable merge tools are present in the merge-tools configuration
1826 1826 section, the one with the highest priority is used.
1827 1827 6. If a program named "hgmerge" can be found on the system, it is used -
1828 1828 but it will by default not be used for symlinks and binary files.
1829 1829 7. If the file to be merged is not binary and is not a symlink, then
1830 1830 internal ":merge" is used.
1831 1831 8. The merge of the file fails and must be resolved before commit.
1832 1832
1833 1833 Note:
1834 1834 After selecting a merge program, Mercurial will by default attempt to
1835 1835 merge the files using a simple merge algorithm first. Only if it
1836 1836 doesn't succeed because of conflicting changes Mercurial will actually
1837 1837 execute the merge program. Whether to use the simple merge algorithm
1838 1838 first can be controlled by the premerge setting of the merge tool.
1839 1839 Premerge is enabled by default unless the file is binary or a symlink.
1840 1840
1841 1841 See the merge-tools and ui sections of hgrc(5) for details on the
1842 1842 configuration of merge tools.
1843 1843
1844 1844 Compression engines listed in `hg help bundlespec`
1845 1845
1846 1846 $ hg help bundlespec | grep gzip
1847 1847 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
1848 1848 An algorithm that produces smaller bundles than "gzip".
1849 1849 This engine will likely produce smaller bundles than "gzip" but will be
1850 1850 "gzip"
1851 1851 better compression than "gzip". It also frequently yields better
1852 1852
1853 1853 Test usage of section marks in help documents
1854 1854
1855 1855 $ cd "$TESTDIR"/../doc
1856 1856 $ python check-seclevel.py
1857 1857 $ cd $TESTTMP
1858 1858
1859 1859 #if serve
1860 1860
1861 1861 Test the help pages in hgweb.
1862 1862
1863 1863 Dish up an empty repo; serve it cold.
1864 1864
1865 1865 $ hg init "$TESTTMP/test"
1866 1866 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1867 1867 $ cat hg.pid >> $DAEMON_PIDS
1868 1868
1869 1869 $ get-with-headers.py $LOCALIP:$HGPORT "help"
1870 1870 200 Script output follows
1871 1871
1872 1872 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1873 1873 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1874 1874 <head>
1875 1875 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1876 1876 <meta name="robots" content="index, nofollow" />
1877 1877 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1878 1878 <script type="text/javascript" src="/static/mercurial.js"></script>
1879 1879
1880 1880 <title>Help: Index</title>
1881 1881 </head>
1882 1882 <body>
1883 1883
1884 1884 <div class="container">
1885 1885 <div class="menu">
1886 1886 <div class="logo">
1887 1887 <a href="https://mercurial-scm.org/">
1888 1888 <img src="/static/hglogo.png" alt="mercurial" /></a>
1889 1889 </div>
1890 1890 <ul>
1891 1891 <li><a href="/shortlog">log</a></li>
1892 1892 <li><a href="/graph">graph</a></li>
1893 1893 <li><a href="/tags">tags</a></li>
1894 1894 <li><a href="/bookmarks">bookmarks</a></li>
1895 1895 <li><a href="/branches">branches</a></li>
1896 1896 </ul>
1897 1897 <ul>
1898 1898 <li class="active">help</li>
1899 1899 </ul>
1900 1900 </div>
1901 1901
1902 1902 <div class="main">
1903 1903 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1904 1904 <form class="search" action="/log">
1905 1905
1906 1906 <p><input name="rev" id="search1" type="text" size="30" /></p>
1907 1907 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1908 1908 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1909 1909 </form>
1910 1910 <table class="bigtable">
1911 1911 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
1912 1912
1913 1913 <tr><td>
1914 1914 <a href="/help/bundlespec">
1915 1915 bundlespec
1916 1916 </a>
1917 1917 </td><td>
1918 1918 Bundle File Formats
1919 1919 </td></tr>
1920 1920 <tr><td>
1921 1921 <a href="/help/color">
1922 1922 color
1923 1923 </a>
1924 1924 </td><td>
1925 1925 Colorizing Outputs
1926 1926 </td></tr>
1927 1927 <tr><td>
1928 1928 <a href="/help/config">
1929 1929 config
1930 1930 </a>
1931 1931 </td><td>
1932 1932 Configuration Files
1933 1933 </td></tr>
1934 1934 <tr><td>
1935 1935 <a href="/help/dates">
1936 1936 dates
1937 1937 </a>
1938 1938 </td><td>
1939 1939 Date Formats
1940 1940 </td></tr>
1941 1941 <tr><td>
1942 1942 <a href="/help/diffs">
1943 1943 diffs
1944 1944 </a>
1945 1945 </td><td>
1946 1946 Diff Formats
1947 1947 </td></tr>
1948 1948 <tr><td>
1949 1949 <a href="/help/environment">
1950 1950 environment
1951 1951 </a>
1952 1952 </td><td>
1953 1953 Environment Variables
1954 1954 </td></tr>
1955 1955 <tr><td>
1956 1956 <a href="/help/extensions">
1957 1957 extensions
1958 1958 </a>
1959 1959 </td><td>
1960 1960 Using Additional Features
1961 1961 </td></tr>
1962 1962 <tr><td>
1963 1963 <a href="/help/filesets">
1964 1964 filesets
1965 1965 </a>
1966 1966 </td><td>
1967 1967 Specifying File Sets
1968 1968 </td></tr>
1969 1969 <tr><td>
1970 1970 <a href="/help/glossary">
1971 1971 glossary
1972 1972 </a>
1973 1973 </td><td>
1974 1974 Glossary
1975 1975 </td></tr>
1976 1976 <tr><td>
1977 1977 <a href="/help/hgignore">
1978 1978 hgignore
1979 1979 </a>
1980 1980 </td><td>
1981 1981 Syntax for Mercurial Ignore Files
1982 1982 </td></tr>
1983 1983 <tr><td>
1984 1984 <a href="/help/hgweb">
1985 1985 hgweb
1986 1986 </a>
1987 1987 </td><td>
1988 1988 Configuring hgweb
1989 1989 </td></tr>
1990 1990 <tr><td>
1991 1991 <a href="/help/internals">
1992 1992 internals
1993 1993 </a>
1994 1994 </td><td>
1995 1995 Technical implementation topics
1996 1996 </td></tr>
1997 1997 <tr><td>
1998 1998 <a href="/help/merge-tools">
1999 1999 merge-tools
2000 2000 </a>
2001 2001 </td><td>
2002 2002 Merge Tools
2003 2003 </td></tr>
2004 2004 <tr><td>
2005 2005 <a href="/help/pager">
2006 2006 pager
2007 2007 </a>
2008 2008 </td><td>
2009 2009 Pager Support
2010 2010 </td></tr>
2011 2011 <tr><td>
2012 2012 <a href="/help/patterns">
2013 2013 patterns
2014 2014 </a>
2015 2015 </td><td>
2016 2016 File Name Patterns
2017 2017 </td></tr>
2018 2018 <tr><td>
2019 2019 <a href="/help/phases">
2020 2020 phases
2021 2021 </a>
2022 2022 </td><td>
2023 2023 Working with Phases
2024 2024 </td></tr>
2025 2025 <tr><td>
2026 2026 <a href="/help/revisions">
2027 2027 revisions
2028 2028 </a>
2029 2029 </td><td>
2030 2030 Specifying Revisions
2031 2031 </td></tr>
2032 2032 <tr><td>
2033 2033 <a href="/help/scripting">
2034 2034 scripting
2035 2035 </a>
2036 2036 </td><td>
2037 2037 Using Mercurial from scripts and automation
2038 2038 </td></tr>
2039 2039 <tr><td>
2040 2040 <a href="/help/subrepos">
2041 2041 subrepos
2042 2042 </a>
2043 2043 </td><td>
2044 2044 Subrepositories
2045 2045 </td></tr>
2046 2046 <tr><td>
2047 2047 <a href="/help/templating">
2048 2048 templating
2049 2049 </a>
2050 2050 </td><td>
2051 2051 Template Usage
2052 2052 </td></tr>
2053 2053 <tr><td>
2054 2054 <a href="/help/urls">
2055 2055 urls
2056 2056 </a>
2057 2057 </td><td>
2058 2058 URL Paths
2059 2059 </td></tr>
2060 2060 <tr><td>
2061 2061 <a href="/help/topic-containing-verbose">
2062 2062 topic-containing-verbose
2063 2063 </a>
2064 2064 </td><td>
2065 2065 This is the topic to test omit indicating.
2066 2066 </td></tr>
2067 2067
2068 2068
2069 2069 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2070 2070
2071 2071 <tr><td>
2072 2072 <a href="/help/add">
2073 2073 add
2074 2074 </a>
2075 2075 </td><td>
2076 2076 add the specified files on the next commit
2077 2077 </td></tr>
2078 2078 <tr><td>
2079 2079 <a href="/help/annotate">
2080 2080 annotate
2081 2081 </a>
2082 2082 </td><td>
2083 2083 show changeset information by line for each file
2084 2084 </td></tr>
2085 2085 <tr><td>
2086 2086 <a href="/help/clone">
2087 2087 clone
2088 2088 </a>
2089 2089 </td><td>
2090 2090 make a copy of an existing repository
2091 2091 </td></tr>
2092 2092 <tr><td>
2093 2093 <a href="/help/commit">
2094 2094 commit
2095 2095 </a>
2096 2096 </td><td>
2097 2097 commit the specified files or all outstanding changes
2098 2098 </td></tr>
2099 2099 <tr><td>
2100 2100 <a href="/help/diff">
2101 2101 diff
2102 2102 </a>
2103 2103 </td><td>
2104 2104 diff repository (or selected files)
2105 2105 </td></tr>
2106 2106 <tr><td>
2107 2107 <a href="/help/export">
2108 2108 export
2109 2109 </a>
2110 2110 </td><td>
2111 2111 dump the header and diffs for one or more changesets
2112 2112 </td></tr>
2113 2113 <tr><td>
2114 2114 <a href="/help/forget">
2115 2115 forget
2116 2116 </a>
2117 2117 </td><td>
2118 2118 forget the specified files on the next commit
2119 2119 </td></tr>
2120 2120 <tr><td>
2121 2121 <a href="/help/init">
2122 2122 init
2123 2123 </a>
2124 2124 </td><td>
2125 2125 create a new repository in the given directory
2126 2126 </td></tr>
2127 2127 <tr><td>
2128 2128 <a href="/help/log">
2129 2129 log
2130 2130 </a>
2131 2131 </td><td>
2132 2132 show revision history of entire repository or files
2133 2133 </td></tr>
2134 2134 <tr><td>
2135 2135 <a href="/help/merge">
2136 2136 merge
2137 2137 </a>
2138 2138 </td><td>
2139 2139 merge another revision into working directory
2140 2140 </td></tr>
2141 2141 <tr><td>
2142 2142 <a href="/help/pull">
2143 2143 pull
2144 2144 </a>
2145 2145 </td><td>
2146 2146 pull changes from the specified source
2147 2147 </td></tr>
2148 2148 <tr><td>
2149 2149 <a href="/help/push">
2150 2150 push
2151 2151 </a>
2152 2152 </td><td>
2153 2153 push changes to the specified destination
2154 2154 </td></tr>
2155 2155 <tr><td>
2156 2156 <a href="/help/remove">
2157 2157 remove
2158 2158 </a>
2159 2159 </td><td>
2160 2160 remove the specified files on the next commit
2161 2161 </td></tr>
2162 2162 <tr><td>
2163 2163 <a href="/help/serve">
2164 2164 serve
2165 2165 </a>
2166 2166 </td><td>
2167 2167 start stand-alone webserver
2168 2168 </td></tr>
2169 2169 <tr><td>
2170 2170 <a href="/help/status">
2171 2171 status
2172 2172 </a>
2173 2173 </td><td>
2174 2174 show changed files in the working directory
2175 2175 </td></tr>
2176 2176 <tr><td>
2177 2177 <a href="/help/summary">
2178 2178 summary
2179 2179 </a>
2180 2180 </td><td>
2181 2181 summarize working directory state
2182 2182 </td></tr>
2183 2183 <tr><td>
2184 2184 <a href="/help/update">
2185 2185 update
2186 2186 </a>
2187 2187 </td><td>
2188 2188 update working directory (or switch revisions)
2189 2189 </td></tr>
2190 2190
2191 2191
2192 2192
2193 2193 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2194 2194
2195 2195 <tr><td>
2196 2196 <a href="/help/addremove">
2197 2197 addremove
2198 2198 </a>
2199 2199 </td><td>
2200 2200 add all new files, delete all missing files
2201 2201 </td></tr>
2202 2202 <tr><td>
2203 2203 <a href="/help/archive">
2204 2204 archive
2205 2205 </a>
2206 2206 </td><td>
2207 2207 create an unversioned archive of a repository revision
2208 2208 </td></tr>
2209 2209 <tr><td>
2210 2210 <a href="/help/backout">
2211 2211 backout
2212 2212 </a>
2213 2213 </td><td>
2214 2214 reverse effect of earlier changeset
2215 2215 </td></tr>
2216 2216 <tr><td>
2217 2217 <a href="/help/bisect">
2218 2218 bisect
2219 2219 </a>
2220 2220 </td><td>
2221 2221 subdivision search of changesets
2222 2222 </td></tr>
2223 2223 <tr><td>
2224 2224 <a href="/help/bookmarks">
2225 2225 bookmarks
2226 2226 </a>
2227 2227 </td><td>
2228 2228 create a new bookmark or list existing bookmarks
2229 2229 </td></tr>
2230 2230 <tr><td>
2231 2231 <a href="/help/branch">
2232 2232 branch
2233 2233 </a>
2234 2234 </td><td>
2235 2235 set or show the current branch name
2236 2236 </td></tr>
2237 2237 <tr><td>
2238 2238 <a href="/help/branches">
2239 2239 branches
2240 2240 </a>
2241 2241 </td><td>
2242 2242 list repository named branches
2243 2243 </td></tr>
2244 2244 <tr><td>
2245 2245 <a href="/help/bundle">
2246 2246 bundle
2247 2247 </a>
2248 2248 </td><td>
2249 create a changegroup file
2249 create a bundle file
2250 2250 </td></tr>
2251 2251 <tr><td>
2252 2252 <a href="/help/cat">
2253 2253 cat
2254 2254 </a>
2255 2255 </td><td>
2256 2256 output the current or given revision of files
2257 2257 </td></tr>
2258 2258 <tr><td>
2259 2259 <a href="/help/config">
2260 2260 config
2261 2261 </a>
2262 2262 </td><td>
2263 2263 show combined config settings from all hgrc files
2264 2264 </td></tr>
2265 2265 <tr><td>
2266 2266 <a href="/help/copy">
2267 2267 copy
2268 2268 </a>
2269 2269 </td><td>
2270 2270 mark files as copied for the next commit
2271 2271 </td></tr>
2272 2272 <tr><td>
2273 2273 <a href="/help/files">
2274 2274 files
2275 2275 </a>
2276 2276 </td><td>
2277 2277 list tracked files
2278 2278 </td></tr>
2279 2279 <tr><td>
2280 2280 <a href="/help/graft">
2281 2281 graft
2282 2282 </a>
2283 2283 </td><td>
2284 2284 copy changes from other branches onto the current branch
2285 2285 </td></tr>
2286 2286 <tr><td>
2287 2287 <a href="/help/grep">
2288 2288 grep
2289 2289 </a>
2290 2290 </td><td>
2291 2291 search revision history for a pattern in specified files
2292 2292 </td></tr>
2293 2293 <tr><td>
2294 2294 <a href="/help/heads">
2295 2295 heads
2296 2296 </a>
2297 2297 </td><td>
2298 2298 show branch heads
2299 2299 </td></tr>
2300 2300 <tr><td>
2301 2301 <a href="/help/help">
2302 2302 help
2303 2303 </a>
2304 2304 </td><td>
2305 2305 show help for a given topic or a help overview
2306 2306 </td></tr>
2307 2307 <tr><td>
2308 2308 <a href="/help/hgalias">
2309 2309 hgalias
2310 2310 </a>
2311 2311 </td><td>
2312 2312 summarize working directory state
2313 2313 </td></tr>
2314 2314 <tr><td>
2315 2315 <a href="/help/identify">
2316 2316 identify
2317 2317 </a>
2318 2318 </td><td>
2319 2319 identify the working directory or specified revision
2320 2320 </td></tr>
2321 2321 <tr><td>
2322 2322 <a href="/help/import">
2323 2323 import
2324 2324 </a>
2325 2325 </td><td>
2326 2326 import an ordered set of patches
2327 2327 </td></tr>
2328 2328 <tr><td>
2329 2329 <a href="/help/incoming">
2330 2330 incoming
2331 2331 </a>
2332 2332 </td><td>
2333 2333 show new changesets found in source
2334 2334 </td></tr>
2335 2335 <tr><td>
2336 2336 <a href="/help/manifest">
2337 2337 manifest
2338 2338 </a>
2339 2339 </td><td>
2340 2340 output the current or given revision of the project manifest
2341 2341 </td></tr>
2342 2342 <tr><td>
2343 2343 <a href="/help/nohelp">
2344 2344 nohelp
2345 2345 </a>
2346 2346 </td><td>
2347 2347 (no help text available)
2348 2348 </td></tr>
2349 2349 <tr><td>
2350 2350 <a href="/help/outgoing">
2351 2351 outgoing
2352 2352 </a>
2353 2353 </td><td>
2354 2354 show changesets not found in the destination
2355 2355 </td></tr>
2356 2356 <tr><td>
2357 2357 <a href="/help/paths">
2358 2358 paths
2359 2359 </a>
2360 2360 </td><td>
2361 2361 show aliases for remote repositories
2362 2362 </td></tr>
2363 2363 <tr><td>
2364 2364 <a href="/help/phase">
2365 2365 phase
2366 2366 </a>
2367 2367 </td><td>
2368 2368 set or show the current phase name
2369 2369 </td></tr>
2370 2370 <tr><td>
2371 2371 <a href="/help/recover">
2372 2372 recover
2373 2373 </a>
2374 2374 </td><td>
2375 2375 roll back an interrupted transaction
2376 2376 </td></tr>
2377 2377 <tr><td>
2378 2378 <a href="/help/rename">
2379 2379 rename
2380 2380 </a>
2381 2381 </td><td>
2382 2382 rename files; equivalent of copy + remove
2383 2383 </td></tr>
2384 2384 <tr><td>
2385 2385 <a href="/help/resolve">
2386 2386 resolve
2387 2387 </a>
2388 2388 </td><td>
2389 2389 redo merges or set/view the merge status of files
2390 2390 </td></tr>
2391 2391 <tr><td>
2392 2392 <a href="/help/revert">
2393 2393 revert
2394 2394 </a>
2395 2395 </td><td>
2396 2396 restore files to their checkout state
2397 2397 </td></tr>
2398 2398 <tr><td>
2399 2399 <a href="/help/root">
2400 2400 root
2401 2401 </a>
2402 2402 </td><td>
2403 2403 print the root (top) of the current working directory
2404 2404 </td></tr>
2405 2405 <tr><td>
2406 2406 <a href="/help/shellalias">
2407 2407 shellalias
2408 2408 </a>
2409 2409 </td><td>
2410 2410 (no help text available)
2411 2411 </td></tr>
2412 2412 <tr><td>
2413 2413 <a href="/help/tag">
2414 2414 tag
2415 2415 </a>
2416 2416 </td><td>
2417 2417 add one or more tags for the current or given revision
2418 2418 </td></tr>
2419 2419 <tr><td>
2420 2420 <a href="/help/tags">
2421 2421 tags
2422 2422 </a>
2423 2423 </td><td>
2424 2424 list repository tags
2425 2425 </td></tr>
2426 2426 <tr><td>
2427 2427 <a href="/help/unbundle">
2428 2428 unbundle
2429 2429 </a>
2430 2430 </td><td>
2431 2431 apply one or more changegroup files
2432 2432 </td></tr>
2433 2433 <tr><td>
2434 2434 <a href="/help/verify">
2435 2435 verify
2436 2436 </a>
2437 2437 </td><td>
2438 2438 verify the integrity of the repository
2439 2439 </td></tr>
2440 2440 <tr><td>
2441 2441 <a href="/help/version">
2442 2442 version
2443 2443 </a>
2444 2444 </td><td>
2445 2445 output version and copyright information
2446 2446 </td></tr>
2447 2447
2448 2448
2449 2449 </table>
2450 2450 </div>
2451 2451 </div>
2452 2452
2453 2453
2454 2454
2455 2455 </body>
2456 2456 </html>
2457 2457
2458 2458
2459 2459 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2460 2460 200 Script output follows
2461 2461
2462 2462 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2463 2463 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2464 2464 <head>
2465 2465 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2466 2466 <meta name="robots" content="index, nofollow" />
2467 2467 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2468 2468 <script type="text/javascript" src="/static/mercurial.js"></script>
2469 2469
2470 2470 <title>Help: add</title>
2471 2471 </head>
2472 2472 <body>
2473 2473
2474 2474 <div class="container">
2475 2475 <div class="menu">
2476 2476 <div class="logo">
2477 2477 <a href="https://mercurial-scm.org/">
2478 2478 <img src="/static/hglogo.png" alt="mercurial" /></a>
2479 2479 </div>
2480 2480 <ul>
2481 2481 <li><a href="/shortlog">log</a></li>
2482 2482 <li><a href="/graph">graph</a></li>
2483 2483 <li><a href="/tags">tags</a></li>
2484 2484 <li><a href="/bookmarks">bookmarks</a></li>
2485 2485 <li><a href="/branches">branches</a></li>
2486 2486 </ul>
2487 2487 <ul>
2488 2488 <li class="active"><a href="/help">help</a></li>
2489 2489 </ul>
2490 2490 </div>
2491 2491
2492 2492 <div class="main">
2493 2493 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2494 2494 <h3>Help: add</h3>
2495 2495
2496 2496 <form class="search" action="/log">
2497 2497
2498 2498 <p><input name="rev" id="search1" type="text" size="30" /></p>
2499 2499 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2500 2500 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2501 2501 </form>
2502 2502 <div id="doc">
2503 2503 <p>
2504 2504 hg add [OPTION]... [FILE]...
2505 2505 </p>
2506 2506 <p>
2507 2507 add the specified files on the next commit
2508 2508 </p>
2509 2509 <p>
2510 2510 Schedule files to be version controlled and added to the
2511 2511 repository.
2512 2512 </p>
2513 2513 <p>
2514 2514 The files will be added to the repository at the next commit. To
2515 2515 undo an add before that, see 'hg forget'.
2516 2516 </p>
2517 2517 <p>
2518 2518 If no names are given, add all files to the repository (except
2519 2519 files matching &quot;.hgignore&quot;).
2520 2520 </p>
2521 2521 <p>
2522 2522 Examples:
2523 2523 </p>
2524 2524 <ul>
2525 2525 <li> New (unknown) files are added automatically by 'hg add':
2526 2526 <pre>
2527 2527 \$ ls (re)
2528 2528 foo.c
2529 2529 \$ hg status (re)
2530 2530 ? foo.c
2531 2531 \$ hg add (re)
2532 2532 adding foo.c
2533 2533 \$ hg status (re)
2534 2534 A foo.c
2535 2535 </pre>
2536 2536 <li> Specific files to be added can be specified:
2537 2537 <pre>
2538 2538 \$ ls (re)
2539 2539 bar.c foo.c
2540 2540 \$ hg status (re)
2541 2541 ? bar.c
2542 2542 ? foo.c
2543 2543 \$ hg add bar.c (re)
2544 2544 \$ hg status (re)
2545 2545 A bar.c
2546 2546 ? foo.c
2547 2547 </pre>
2548 2548 </ul>
2549 2549 <p>
2550 2550 Returns 0 if all files are successfully added.
2551 2551 </p>
2552 2552 <p>
2553 2553 options ([+] can be repeated):
2554 2554 </p>
2555 2555 <table>
2556 2556 <tr><td>-I</td>
2557 2557 <td>--include PATTERN [+]</td>
2558 2558 <td>include names matching the given patterns</td></tr>
2559 2559 <tr><td>-X</td>
2560 2560 <td>--exclude PATTERN [+]</td>
2561 2561 <td>exclude names matching the given patterns</td></tr>
2562 2562 <tr><td>-S</td>
2563 2563 <td>--subrepos</td>
2564 2564 <td>recurse into subrepositories</td></tr>
2565 2565 <tr><td>-n</td>
2566 2566 <td>--dry-run</td>
2567 2567 <td>do not perform actions, just print output</td></tr>
2568 2568 </table>
2569 2569 <p>
2570 2570 global options ([+] can be repeated):
2571 2571 </p>
2572 2572 <table>
2573 2573 <tr><td>-R</td>
2574 2574 <td>--repository REPO</td>
2575 2575 <td>repository root directory or name of overlay bundle file</td></tr>
2576 2576 <tr><td></td>
2577 2577 <td>--cwd DIR</td>
2578 2578 <td>change working directory</td></tr>
2579 2579 <tr><td>-y</td>
2580 2580 <td>--noninteractive</td>
2581 2581 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2582 2582 <tr><td>-q</td>
2583 2583 <td>--quiet</td>
2584 2584 <td>suppress output</td></tr>
2585 2585 <tr><td>-v</td>
2586 2586 <td>--verbose</td>
2587 2587 <td>enable additional output</td></tr>
2588 2588 <tr><td></td>
2589 2589 <td>--color TYPE</td>
2590 2590 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2591 2591 <tr><td></td>
2592 2592 <td>--config CONFIG [+]</td>
2593 2593 <td>set/override config option (use 'section.name=value')</td></tr>
2594 2594 <tr><td></td>
2595 2595 <td>--debug</td>
2596 2596 <td>enable debugging output</td></tr>
2597 2597 <tr><td></td>
2598 2598 <td>--debugger</td>
2599 2599 <td>start debugger</td></tr>
2600 2600 <tr><td></td>
2601 2601 <td>--encoding ENCODE</td>
2602 2602 <td>set the charset encoding (default: ascii)</td></tr>
2603 2603 <tr><td></td>
2604 2604 <td>--encodingmode MODE</td>
2605 2605 <td>set the charset encoding mode (default: strict)</td></tr>
2606 2606 <tr><td></td>
2607 2607 <td>--traceback</td>
2608 2608 <td>always print a traceback on exception</td></tr>
2609 2609 <tr><td></td>
2610 2610 <td>--time</td>
2611 2611 <td>time how long the command takes</td></tr>
2612 2612 <tr><td></td>
2613 2613 <td>--profile</td>
2614 2614 <td>print command execution profile</td></tr>
2615 2615 <tr><td></td>
2616 2616 <td>--version</td>
2617 2617 <td>output version information and exit</td></tr>
2618 2618 <tr><td>-h</td>
2619 2619 <td>--help</td>
2620 2620 <td>display help and exit</td></tr>
2621 2621 <tr><td></td>
2622 2622 <td>--hidden</td>
2623 2623 <td>consider hidden changesets</td></tr>
2624 2624 <tr><td></td>
2625 2625 <td>--pager TYPE</td>
2626 2626 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2627 2627 </table>
2628 2628
2629 2629 </div>
2630 2630 </div>
2631 2631 </div>
2632 2632
2633 2633
2634 2634
2635 2635 </body>
2636 2636 </html>
2637 2637
2638 2638
2639 2639 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2640 2640 200 Script output follows
2641 2641
2642 2642 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2643 2643 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2644 2644 <head>
2645 2645 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2646 2646 <meta name="robots" content="index, nofollow" />
2647 2647 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2648 2648 <script type="text/javascript" src="/static/mercurial.js"></script>
2649 2649
2650 2650 <title>Help: remove</title>
2651 2651 </head>
2652 2652 <body>
2653 2653
2654 2654 <div class="container">
2655 2655 <div class="menu">
2656 2656 <div class="logo">
2657 2657 <a href="https://mercurial-scm.org/">
2658 2658 <img src="/static/hglogo.png" alt="mercurial" /></a>
2659 2659 </div>
2660 2660 <ul>
2661 2661 <li><a href="/shortlog">log</a></li>
2662 2662 <li><a href="/graph">graph</a></li>
2663 2663 <li><a href="/tags">tags</a></li>
2664 2664 <li><a href="/bookmarks">bookmarks</a></li>
2665 2665 <li><a href="/branches">branches</a></li>
2666 2666 </ul>
2667 2667 <ul>
2668 2668 <li class="active"><a href="/help">help</a></li>
2669 2669 </ul>
2670 2670 </div>
2671 2671
2672 2672 <div class="main">
2673 2673 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2674 2674 <h3>Help: remove</h3>
2675 2675
2676 2676 <form class="search" action="/log">
2677 2677
2678 2678 <p><input name="rev" id="search1" type="text" size="30" /></p>
2679 2679 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2680 2680 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2681 2681 </form>
2682 2682 <div id="doc">
2683 2683 <p>
2684 2684 hg remove [OPTION]... FILE...
2685 2685 </p>
2686 2686 <p>
2687 2687 aliases: rm
2688 2688 </p>
2689 2689 <p>
2690 2690 remove the specified files on the next commit
2691 2691 </p>
2692 2692 <p>
2693 2693 Schedule the indicated files for removal from the current branch.
2694 2694 </p>
2695 2695 <p>
2696 2696 This command schedules the files to be removed at the next commit.
2697 2697 To undo a remove before that, see 'hg revert'. To undo added
2698 2698 files, see 'hg forget'.
2699 2699 </p>
2700 2700 <p>
2701 2701 -A/--after can be used to remove only files that have already
2702 2702 been deleted, -f/--force can be used to force deletion, and -Af
2703 2703 can be used to remove files from the next revision without
2704 2704 deleting them from the working directory.
2705 2705 </p>
2706 2706 <p>
2707 2707 The following table details the behavior of remove for different
2708 2708 file states (columns) and option combinations (rows). The file
2709 2709 states are Added [A], Clean [C], Modified [M] and Missing [!]
2710 2710 (as reported by 'hg status'). The actions are Warn, Remove
2711 2711 (from branch) and Delete (from disk):
2712 2712 </p>
2713 2713 <table>
2714 2714 <tr><td>opt/state</td>
2715 2715 <td>A</td>
2716 2716 <td>C</td>
2717 2717 <td>M</td>
2718 2718 <td>!</td></tr>
2719 2719 <tr><td>none</td>
2720 2720 <td>W</td>
2721 2721 <td>RD</td>
2722 2722 <td>W</td>
2723 2723 <td>R</td></tr>
2724 2724 <tr><td>-f</td>
2725 2725 <td>R</td>
2726 2726 <td>RD</td>
2727 2727 <td>RD</td>
2728 2728 <td>R</td></tr>
2729 2729 <tr><td>-A</td>
2730 2730 <td>W</td>
2731 2731 <td>W</td>
2732 2732 <td>W</td>
2733 2733 <td>R</td></tr>
2734 2734 <tr><td>-Af</td>
2735 2735 <td>R</td>
2736 2736 <td>R</td>
2737 2737 <td>R</td>
2738 2738 <td>R</td></tr>
2739 2739 </table>
2740 2740 <p>
2741 2741 <b>Note:</b>
2742 2742 </p>
2743 2743 <p>
2744 2744 'hg remove' never deletes files in Added [A] state from the
2745 2745 working directory, not even if &quot;--force&quot; is specified.
2746 2746 </p>
2747 2747 <p>
2748 2748 Returns 0 on success, 1 if any warnings encountered.
2749 2749 </p>
2750 2750 <p>
2751 2751 options ([+] can be repeated):
2752 2752 </p>
2753 2753 <table>
2754 2754 <tr><td>-A</td>
2755 2755 <td>--after</td>
2756 2756 <td>record delete for missing files</td></tr>
2757 2757 <tr><td>-f</td>
2758 2758 <td>--force</td>
2759 2759 <td>forget added files, delete modified files</td></tr>
2760 2760 <tr><td>-S</td>
2761 2761 <td>--subrepos</td>
2762 2762 <td>recurse into subrepositories</td></tr>
2763 2763 <tr><td>-I</td>
2764 2764 <td>--include PATTERN [+]</td>
2765 2765 <td>include names matching the given patterns</td></tr>
2766 2766 <tr><td>-X</td>
2767 2767 <td>--exclude PATTERN [+]</td>
2768 2768 <td>exclude names matching the given patterns</td></tr>
2769 2769 </table>
2770 2770 <p>
2771 2771 global options ([+] can be repeated):
2772 2772 </p>
2773 2773 <table>
2774 2774 <tr><td>-R</td>
2775 2775 <td>--repository REPO</td>
2776 2776 <td>repository root directory or name of overlay bundle file</td></tr>
2777 2777 <tr><td></td>
2778 2778 <td>--cwd DIR</td>
2779 2779 <td>change working directory</td></tr>
2780 2780 <tr><td>-y</td>
2781 2781 <td>--noninteractive</td>
2782 2782 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2783 2783 <tr><td>-q</td>
2784 2784 <td>--quiet</td>
2785 2785 <td>suppress output</td></tr>
2786 2786 <tr><td>-v</td>
2787 2787 <td>--verbose</td>
2788 2788 <td>enable additional output</td></tr>
2789 2789 <tr><td></td>
2790 2790 <td>--color TYPE</td>
2791 2791 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2792 2792 <tr><td></td>
2793 2793 <td>--config CONFIG [+]</td>
2794 2794 <td>set/override config option (use 'section.name=value')</td></tr>
2795 2795 <tr><td></td>
2796 2796 <td>--debug</td>
2797 2797 <td>enable debugging output</td></tr>
2798 2798 <tr><td></td>
2799 2799 <td>--debugger</td>
2800 2800 <td>start debugger</td></tr>
2801 2801 <tr><td></td>
2802 2802 <td>--encoding ENCODE</td>
2803 2803 <td>set the charset encoding (default: ascii)</td></tr>
2804 2804 <tr><td></td>
2805 2805 <td>--encodingmode MODE</td>
2806 2806 <td>set the charset encoding mode (default: strict)</td></tr>
2807 2807 <tr><td></td>
2808 2808 <td>--traceback</td>
2809 2809 <td>always print a traceback on exception</td></tr>
2810 2810 <tr><td></td>
2811 2811 <td>--time</td>
2812 2812 <td>time how long the command takes</td></tr>
2813 2813 <tr><td></td>
2814 2814 <td>--profile</td>
2815 2815 <td>print command execution profile</td></tr>
2816 2816 <tr><td></td>
2817 2817 <td>--version</td>
2818 2818 <td>output version information and exit</td></tr>
2819 2819 <tr><td>-h</td>
2820 2820 <td>--help</td>
2821 2821 <td>display help and exit</td></tr>
2822 2822 <tr><td></td>
2823 2823 <td>--hidden</td>
2824 2824 <td>consider hidden changesets</td></tr>
2825 2825 <tr><td></td>
2826 2826 <td>--pager TYPE</td>
2827 2827 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2828 2828 </table>
2829 2829
2830 2830 </div>
2831 2831 </div>
2832 2832 </div>
2833 2833
2834 2834
2835 2835
2836 2836 </body>
2837 2837 </html>
2838 2838
2839 2839
2840 2840 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
2841 2841 200 Script output follows
2842 2842
2843 2843 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2844 2844 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2845 2845 <head>
2846 2846 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2847 2847 <meta name="robots" content="index, nofollow" />
2848 2848 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2849 2849 <script type="text/javascript" src="/static/mercurial.js"></script>
2850 2850
2851 2851 <title>Help: dates</title>
2852 2852 </head>
2853 2853 <body>
2854 2854
2855 2855 <div class="container">
2856 2856 <div class="menu">
2857 2857 <div class="logo">
2858 2858 <a href="https://mercurial-scm.org/">
2859 2859 <img src="/static/hglogo.png" alt="mercurial" /></a>
2860 2860 </div>
2861 2861 <ul>
2862 2862 <li><a href="/shortlog">log</a></li>
2863 2863 <li><a href="/graph">graph</a></li>
2864 2864 <li><a href="/tags">tags</a></li>
2865 2865 <li><a href="/bookmarks">bookmarks</a></li>
2866 2866 <li><a href="/branches">branches</a></li>
2867 2867 </ul>
2868 2868 <ul>
2869 2869 <li class="active"><a href="/help">help</a></li>
2870 2870 </ul>
2871 2871 </div>
2872 2872
2873 2873 <div class="main">
2874 2874 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2875 2875 <h3>Help: dates</h3>
2876 2876
2877 2877 <form class="search" action="/log">
2878 2878
2879 2879 <p><input name="rev" id="search1" type="text" size="30" /></p>
2880 2880 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2881 2881 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2882 2882 </form>
2883 2883 <div id="doc">
2884 2884 <h1>Date Formats</h1>
2885 2885 <p>
2886 2886 Some commands allow the user to specify a date, e.g.:
2887 2887 </p>
2888 2888 <ul>
2889 2889 <li> backout, commit, import, tag: Specify the commit date.
2890 2890 <li> log, revert, update: Select revision(s) by date.
2891 2891 </ul>
2892 2892 <p>
2893 2893 Many date formats are valid. Here are some examples:
2894 2894 </p>
2895 2895 <ul>
2896 2896 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
2897 2897 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
2898 2898 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
2899 2899 <li> &quot;Dec 6&quot; (midnight)
2900 2900 <li> &quot;13:18&quot; (today assumed)
2901 2901 <li> &quot;3:39&quot; (3:39AM assumed)
2902 2902 <li> &quot;3:39pm&quot; (15:39)
2903 2903 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
2904 2904 <li> &quot;2006-12-6 13:18&quot;
2905 2905 <li> &quot;2006-12-6&quot;
2906 2906 <li> &quot;12-6&quot;
2907 2907 <li> &quot;12/6&quot;
2908 2908 <li> &quot;12/6/6&quot; (Dec 6 2006)
2909 2909 <li> &quot;today&quot; (midnight)
2910 2910 <li> &quot;yesterday&quot; (midnight)
2911 2911 <li> &quot;now&quot; - right now
2912 2912 </ul>
2913 2913 <p>
2914 2914 Lastly, there is Mercurial's internal format:
2915 2915 </p>
2916 2916 <ul>
2917 2917 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
2918 2918 </ul>
2919 2919 <p>
2920 2920 This is the internal representation format for dates. The first number
2921 2921 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
2922 2922 second is the offset of the local timezone, in seconds west of UTC
2923 2923 (negative if the timezone is east of UTC).
2924 2924 </p>
2925 2925 <p>
2926 2926 The log command also accepts date ranges:
2927 2927 </p>
2928 2928 <ul>
2929 2929 <li> &quot;&lt;DATE&quot; - at or before a given date/time
2930 2930 <li> &quot;&gt;DATE&quot; - on or after a given date/time
2931 2931 <li> &quot;DATE to DATE&quot; - a date range, inclusive
2932 2932 <li> &quot;-DAYS&quot; - within a given number of days of today
2933 2933 </ul>
2934 2934
2935 2935 </div>
2936 2936 </div>
2937 2937 </div>
2938 2938
2939 2939
2940 2940
2941 2941 </body>
2942 2942 </html>
2943 2943
2944 2944
2945 2945 Sub-topic indexes rendered properly
2946 2946
2947 2947 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
2948 2948 200 Script output follows
2949 2949
2950 2950 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2951 2951 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2952 2952 <head>
2953 2953 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2954 2954 <meta name="robots" content="index, nofollow" />
2955 2955 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2956 2956 <script type="text/javascript" src="/static/mercurial.js"></script>
2957 2957
2958 2958 <title>Help: internals</title>
2959 2959 </head>
2960 2960 <body>
2961 2961
2962 2962 <div class="container">
2963 2963 <div class="menu">
2964 2964 <div class="logo">
2965 2965 <a href="https://mercurial-scm.org/">
2966 2966 <img src="/static/hglogo.png" alt="mercurial" /></a>
2967 2967 </div>
2968 2968 <ul>
2969 2969 <li><a href="/shortlog">log</a></li>
2970 2970 <li><a href="/graph">graph</a></li>
2971 2971 <li><a href="/tags">tags</a></li>
2972 2972 <li><a href="/bookmarks">bookmarks</a></li>
2973 2973 <li><a href="/branches">branches</a></li>
2974 2974 </ul>
2975 2975 <ul>
2976 2976 <li><a href="/help">help</a></li>
2977 2977 </ul>
2978 2978 </div>
2979 2979
2980 2980 <div class="main">
2981 2981 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2982 2982 <form class="search" action="/log">
2983 2983
2984 2984 <p><input name="rev" id="search1" type="text" size="30" /></p>
2985 2985 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2986 2986 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2987 2987 </form>
2988 2988 <table class="bigtable">
2989 2989 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2990 2990
2991 2991 <tr><td>
2992 2992 <a href="/help/internals.bundles">
2993 2993 bundles
2994 2994 </a>
2995 2995 </td><td>
2996 2996 Bundles
2997 2997 </td></tr>
2998 2998 <tr><td>
2999 2999 <a href="/help/internals.censor">
3000 3000 censor
3001 3001 </a>
3002 3002 </td><td>
3003 3003 Censor
3004 3004 </td></tr>
3005 3005 <tr><td>
3006 3006 <a href="/help/internals.changegroups">
3007 3007 changegroups
3008 3008 </a>
3009 3009 </td><td>
3010 3010 Changegroups
3011 3011 </td></tr>
3012 3012 <tr><td>
3013 3013 <a href="/help/internals.requirements">
3014 3014 requirements
3015 3015 </a>
3016 3016 </td><td>
3017 3017 Repository Requirements
3018 3018 </td></tr>
3019 3019 <tr><td>
3020 3020 <a href="/help/internals.revlogs">
3021 3021 revlogs
3022 3022 </a>
3023 3023 </td><td>
3024 3024 Revision Logs
3025 3025 </td></tr>
3026 3026 <tr><td>
3027 3027 <a href="/help/internals.wireprotocol">
3028 3028 wireprotocol
3029 3029 </a>
3030 3030 </td><td>
3031 3031 Wire Protocol
3032 3032 </td></tr>
3033 3033
3034 3034
3035 3035
3036 3036
3037 3037
3038 3038 </table>
3039 3039 </div>
3040 3040 </div>
3041 3041
3042 3042
3043 3043
3044 3044 </body>
3045 3045 </html>
3046 3046
3047 3047
3048 3048 Sub-topic topics rendered properly
3049 3049
3050 3050 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3051 3051 200 Script output follows
3052 3052
3053 3053 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3054 3054 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3055 3055 <head>
3056 3056 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3057 3057 <meta name="robots" content="index, nofollow" />
3058 3058 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3059 3059 <script type="text/javascript" src="/static/mercurial.js"></script>
3060 3060
3061 3061 <title>Help: internals.changegroups</title>
3062 3062 </head>
3063 3063 <body>
3064 3064
3065 3065 <div class="container">
3066 3066 <div class="menu">
3067 3067 <div class="logo">
3068 3068 <a href="https://mercurial-scm.org/">
3069 3069 <img src="/static/hglogo.png" alt="mercurial" /></a>
3070 3070 </div>
3071 3071 <ul>
3072 3072 <li><a href="/shortlog">log</a></li>
3073 3073 <li><a href="/graph">graph</a></li>
3074 3074 <li><a href="/tags">tags</a></li>
3075 3075 <li><a href="/bookmarks">bookmarks</a></li>
3076 3076 <li><a href="/branches">branches</a></li>
3077 3077 </ul>
3078 3078 <ul>
3079 3079 <li class="active"><a href="/help">help</a></li>
3080 3080 </ul>
3081 3081 </div>
3082 3082
3083 3083 <div class="main">
3084 3084 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3085 3085 <h3>Help: internals.changegroups</h3>
3086 3086
3087 3087 <form class="search" action="/log">
3088 3088
3089 3089 <p><input name="rev" id="search1" type="text" size="30" /></p>
3090 3090 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3091 3091 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3092 3092 </form>
3093 3093 <div id="doc">
3094 3094 <h1>Changegroups</h1>
3095 3095 <p>
3096 3096 Changegroups are representations of repository revlog data, specifically
3097 3097 the changelog data, root/flat manifest data, treemanifest data, and
3098 3098 filelogs.
3099 3099 </p>
3100 3100 <p>
3101 3101 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3102 3102 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3103 3103 only difference being an additional item in the *delta header*. Version
3104 3104 &quot;3&quot; adds support for revlog flags in the *delta header* and optionally
3105 3105 exchanging treemanifests (enabled by setting an option on the
3106 3106 &quot;changegroup&quot; part in the bundle2).
3107 3107 </p>
3108 3108 <p>
3109 3109 Changegroups when not exchanging treemanifests consist of 3 logical
3110 3110 segments:
3111 3111 </p>
3112 3112 <pre>
3113 3113 +---------------------------------+
3114 3114 | | | |
3115 3115 | changeset | manifest | filelogs |
3116 3116 | | | |
3117 3117 | | | |
3118 3118 +---------------------------------+
3119 3119 </pre>
3120 3120 <p>
3121 3121 When exchanging treemanifests, there are 4 logical segments:
3122 3122 </p>
3123 3123 <pre>
3124 3124 +-------------------------------------------------+
3125 3125 | | | | |
3126 3126 | changeset | root | treemanifests | filelogs |
3127 3127 | | manifest | | |
3128 3128 | | | | |
3129 3129 +-------------------------------------------------+
3130 3130 </pre>
3131 3131 <p>
3132 3132 The principle building block of each segment is a *chunk*. A *chunk*
3133 3133 is a framed piece of data:
3134 3134 </p>
3135 3135 <pre>
3136 3136 +---------------------------------------+
3137 3137 | | |
3138 3138 | length | data |
3139 3139 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3140 3140 | | |
3141 3141 +---------------------------------------+
3142 3142 </pre>
3143 3143 <p>
3144 3144 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3145 3145 integer indicating the length of the entire chunk (including the length field
3146 3146 itself).
3147 3147 </p>
3148 3148 <p>
3149 3149 There is a special case chunk that has a value of 0 for the length
3150 3150 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3151 3151 </p>
3152 3152 <h2>Delta Groups</h2>
3153 3153 <p>
3154 3154 A *delta group* expresses the content of a revlog as a series of deltas,
3155 3155 or patches against previous revisions.
3156 3156 </p>
3157 3157 <p>
3158 3158 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3159 3159 to signal the end of the delta group:
3160 3160 </p>
3161 3161 <pre>
3162 3162 +------------------------------------------------------------------------+
3163 3163 | | | | | |
3164 3164 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3165 3165 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3166 3166 | | | | | |
3167 3167 +------------------------------------------------------------------------+
3168 3168 </pre>
3169 3169 <p>
3170 3170 Each *chunk*'s data consists of the following:
3171 3171 </p>
3172 3172 <pre>
3173 3173 +---------------------------------------+
3174 3174 | | |
3175 3175 | delta header | delta data |
3176 3176 | (various by version) | (various) |
3177 3177 | | |
3178 3178 +---------------------------------------+
3179 3179 </pre>
3180 3180 <p>
3181 3181 The *delta data* is a series of *delta*s that describe a diff from an existing
3182 3182 entry (either that the recipient already has, or previously specified in the
3183 3183 bundlei/changegroup).
3184 3184 </p>
3185 3185 <p>
3186 3186 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3187 3187 &quot;3&quot; of the changegroup format.
3188 3188 </p>
3189 3189 <p>
3190 3190 Version 1 (headerlen=80):
3191 3191 </p>
3192 3192 <pre>
3193 3193 +------------------------------------------------------+
3194 3194 | | | | |
3195 3195 | node | p1 node | p2 node | link node |
3196 3196 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3197 3197 | | | | |
3198 3198 +------------------------------------------------------+
3199 3199 </pre>
3200 3200 <p>
3201 3201 Version 2 (headerlen=100):
3202 3202 </p>
3203 3203 <pre>
3204 3204 +------------------------------------------------------------------+
3205 3205 | | | | | |
3206 3206 | node | p1 node | p2 node | base node | link node |
3207 3207 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3208 3208 | | | | | |
3209 3209 +------------------------------------------------------------------+
3210 3210 </pre>
3211 3211 <p>
3212 3212 Version 3 (headerlen=102):
3213 3213 </p>
3214 3214 <pre>
3215 3215 +------------------------------------------------------------------------------+
3216 3216 | | | | | | |
3217 3217 | node | p1 node | p2 node | base node | link node | flags |
3218 3218 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3219 3219 | | | | | | |
3220 3220 +------------------------------------------------------------------------------+
3221 3221 </pre>
3222 3222 <p>
3223 3223 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3224 3224 series of *delta*s, densely packed (no separators). These deltas describe a diff
3225 3225 from an existing entry (either that the recipient already has, or previously
3226 3226 specified in the bundle/changegroup). The format is described more fully in
3227 3227 &quot;hg help internals.bdiff&quot;, but briefly:
3228 3228 </p>
3229 3229 <pre>
3230 3230 +---------------------------------------------------------------+
3231 3231 | | | | |
3232 3232 | start offset | end offset | new length | content |
3233 3233 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3234 3234 | | | | |
3235 3235 +---------------------------------------------------------------+
3236 3236 </pre>
3237 3237 <p>
3238 3238 Please note that the length field in the delta data does *not* include itself.
3239 3239 </p>
3240 3240 <p>
3241 3241 In version 1, the delta is always applied against the previous node from
3242 3242 the changegroup or the first parent if this is the first entry in the
3243 3243 changegroup.
3244 3244 </p>
3245 3245 <p>
3246 3246 In version 2 and up, the delta base node is encoded in the entry in the
3247 3247 changegroup. This allows the delta to be expressed against any parent,
3248 3248 which can result in smaller deltas and more efficient encoding of data.
3249 3249 </p>
3250 3250 <h2>Changeset Segment</h2>
3251 3251 <p>
3252 3252 The *changeset segment* consists of a single *delta group* holding
3253 3253 changelog data. The *empty chunk* at the end of the *delta group* denotes
3254 3254 the boundary to the *manifest segment*.
3255 3255 </p>
3256 3256 <h2>Manifest Segment</h2>
3257 3257 <p>
3258 3258 The *manifest segment* consists of a single *delta group* holding manifest
3259 3259 data. If treemanifests are in use, it contains only the manifest for the
3260 3260 root directory of the repository. Otherwise, it contains the entire
3261 3261 manifest data. The *empty chunk* at the end of the *delta group* denotes
3262 3262 the boundary to the next segment (either the *treemanifests segment* or the
3263 3263 *filelogs segment*, depending on version and the request options).
3264 3264 </p>
3265 3265 <h3>Treemanifests Segment</h3>
3266 3266 <p>
3267 3267 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3268 3268 only if the 'treemanifest' param is part of the bundle2 changegroup part
3269 3269 (it is not possible to use changegroup version 3 outside of bundle2).
3270 3270 Aside from the filenames in the *treemanifests segment* containing a
3271 3271 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3272 3272 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3273 3273 a sub-segment with filename size 0). This denotes the boundary to the
3274 3274 *filelogs segment*.
3275 3275 </p>
3276 3276 <h2>Filelogs Segment</h2>
3277 3277 <p>
3278 3278 The *filelogs segment* consists of multiple sub-segments, each
3279 3279 corresponding to an individual file whose data is being described:
3280 3280 </p>
3281 3281 <pre>
3282 3282 +--------------------------------------------------+
3283 3283 | | | | | |
3284 3284 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3285 3285 | | | | | (4 bytes) |
3286 3286 | | | | | |
3287 3287 +--------------------------------------------------+
3288 3288 </pre>
3289 3289 <p>
3290 3290 The final filelog sub-segment is followed by an *empty chunk* (logically,
3291 3291 a sub-segment with filename size 0). This denotes the end of the segment
3292 3292 and of the overall changegroup.
3293 3293 </p>
3294 3294 <p>
3295 3295 Each filelog sub-segment consists of the following:
3296 3296 </p>
3297 3297 <pre>
3298 3298 +------------------------------------------------------+
3299 3299 | | | |
3300 3300 | filename length | filename | delta group |
3301 3301 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3302 3302 | | | |
3303 3303 +------------------------------------------------------+
3304 3304 </pre>
3305 3305 <p>
3306 3306 That is, a *chunk* consisting of the filename (not terminated or padded)
3307 3307 followed by N chunks constituting the *delta group* for this file. The
3308 3308 *empty chunk* at the end of each *delta group* denotes the boundary to the
3309 3309 next filelog sub-segment.
3310 3310 </p>
3311 3311
3312 3312 </div>
3313 3313 </div>
3314 3314 </div>
3315 3315
3316 3316
3317 3317
3318 3318 </body>
3319 3319 </html>
3320 3320
3321 3321
3322 3322 $ killdaemons.py
3323 3323
3324 3324 #endif
@@ -1,1646 +1,1646 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 changeset/ renders the tip changeset
592 592
593 593 $ request json-rev
594 594 200 Script output follows
595 595
596 596 {
597 597 "bookmarks": [],
598 598 "branch": "default",
599 599 "date": [
600 600 0.0,
601 601 0
602 602 ],
603 603 "desc": "merge test-branch into default",
604 604 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
605 605 "parents": [
606 606 "ceed296fe500c3fac9541e31dad860cb49c89e45",
607 607 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
608 608 ],
609 609 "phase": "draft",
610 610 "tags": [
611 611 "tip"
612 612 ],
613 613 "user": "test"
614 614 }
615 615
616 616 changeset/{revision} shows tags
617 617
618 618 $ request json-rev/78896eb0e102
619 619 200 Script output follows
620 620
621 621 {
622 622 "bookmarks": [],
623 623 "branch": "default",
624 624 "date": [
625 625 0.0,
626 626 0
627 627 ],
628 628 "desc": "move foo",
629 629 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
630 630 "parents": [
631 631 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
632 632 ],
633 633 "phase": "public",
634 634 "tags": [
635 635 "tag1"
636 636 ],
637 637 "user": "test"
638 638 }
639 639
640 640 changeset/{revision} shows bookmarks
641 641
642 642 $ request json-rev/8d7c456572ac
643 643 200 Script output follows
644 644
645 645 {
646 646 "bookmarks": [
647 647 "bookmark1"
648 648 ],
649 649 "branch": "default",
650 650 "date": [
651 651 0.0,
652 652 0
653 653 ],
654 654 "desc": "modify da/foo",
655 655 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
656 656 "parents": [
657 657 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
658 658 ],
659 659 "phase": "public",
660 660 "tags": [],
661 661 "user": "test"
662 662 }
663 663
664 664 changeset/{revision} shows branches
665 665
666 666 $ request json-rev/6ab967a8ab34
667 667 200 Script output follows
668 668
669 669 {
670 670 "bookmarks": [],
671 671 "branch": "test-branch",
672 672 "date": [
673 673 0.0,
674 674 0
675 675 ],
676 676 "desc": "create test branch",
677 677 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
678 678 "parents": [
679 679 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
680 680 ],
681 681 "phase": "draft",
682 682 "tags": [],
683 683 "user": "test"
684 684 }
685 685
686 686 manifest/{revision}/{path} shows info about a directory at a revision
687 687
688 688 $ request json-manifest/06e557f3edf6/
689 689 200 Script output follows
690 690
691 691 {
692 692 "abspath": "/",
693 693 "bookmarks": [],
694 694 "directories": [
695 695 {
696 696 "abspath": "/da",
697 697 "basename": "da",
698 698 "emptydirs": ""
699 699 }
700 700 ],
701 701 "files": [
702 702 {
703 703 "abspath": "foo",
704 704 "basename": "foo",
705 705 "date": [
706 706 0.0,
707 707 0
708 708 ],
709 709 "flags": "",
710 710 "size": 4
711 711 }
712 712 ],
713 713 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
714 714 "tags": []
715 715 }
716 716
717 717 tags/ shows tags info
718 718
719 719 $ request json-tags
720 720 200 Script output follows
721 721
722 722 {
723 723 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
724 724 "tags": [
725 725 {
726 726 "date": [
727 727 0.0,
728 728 0
729 729 ],
730 730 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
731 731 "tag": "tag2"
732 732 },
733 733 {
734 734 "date": [
735 735 0.0,
736 736 0
737 737 ],
738 738 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
739 739 "tag": "tag1"
740 740 }
741 741 ]
742 742 }
743 743
744 744 bookmarks/ shows bookmarks info
745 745
746 746 $ request json-bookmarks
747 747 200 Script output follows
748 748
749 749 {
750 750 "bookmarks": [
751 751 {
752 752 "bookmark": "bookmark2",
753 753 "date": [
754 754 0.0,
755 755 0
756 756 ],
757 757 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45"
758 758 },
759 759 {
760 760 "bookmark": "bookmark1",
761 761 "date": [
762 762 0.0,
763 763 0
764 764 ],
765 765 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5"
766 766 }
767 767 ],
768 768 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
769 769 }
770 770
771 771 branches/ shows branches info
772 772
773 773 $ request json-branches
774 774 200 Script output follows
775 775
776 776 {
777 777 "branches": [
778 778 {
779 779 "branch": "default",
780 780 "date": [
781 781 0.0,
782 782 0
783 783 ],
784 784 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
785 785 "status": "open"
786 786 },
787 787 {
788 788 "branch": "test-branch",
789 789 "date": [
790 790 0.0,
791 791 0
792 792 ],
793 793 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
794 794 "status": "inactive"
795 795 }
796 796 ]
797 797 }
798 798
799 799 summary/ shows a summary of repository state
800 800
801 801 $ request json-summary
802 802 200 Script output follows
803 803
804 804 {
805 805 "archives": [
806 806 {
807 807 "extension": ".tar.bz2",
808 808 "node": "tip",
809 809 "type": "bz2",
810 810 "url": "http://*:$HGPORT/archive/tip.tar.bz2" (glob)
811 811 }
812 812 ],
813 813 "bookmarks": [
814 814 {
815 815 "bookmark": "bookmark2",
816 816 "date": [
817 817 0.0,
818 818 0
819 819 ],
820 820 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45"
821 821 },
822 822 {
823 823 "bookmark": "bookmark1",
824 824 "date": [
825 825 0.0,
826 826 0
827 827 ],
828 828 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5"
829 829 }
830 830 ],
831 831 "branches": [
832 832 {
833 833 "branch": "default",
834 834 "date": [
835 835 0.0,
836 836 0
837 837 ],
838 838 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
839 839 "status": "open"
840 840 },
841 841 {
842 842 "branch": "test-branch",
843 843 "date": [
844 844 0.0,
845 845 0
846 846 ],
847 847 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
848 848 "status": "inactive"
849 849 }
850 850 ],
851 851 "labels": [],
852 852 "lastchange": [
853 853 0.0,
854 854 0
855 855 ],
856 856 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
857 857 "shortlog": [
858 858 {
859 859 "bookmarks": [],
860 860 "branch": "default",
861 861 "date": [
862 862 0.0,
863 863 0
864 864 ],
865 865 "desc": "merge test-branch into default",
866 866 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
867 867 "parents": [
868 868 "ceed296fe500c3fac9541e31dad860cb49c89e45",
869 869 "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
870 870 ],
871 871 "phase": "draft",
872 872 "tags": [
873 873 "tip"
874 874 ],
875 875 "user": "test"
876 876 },
877 877 {
878 878 "bookmarks": [],
879 879 "branch": "test-branch",
880 880 "date": [
881 881 0.0,
882 882 0
883 883 ],
884 884 "desc": "another commit in test-branch",
885 885 "node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
886 886 "parents": [
887 887 "6ab967a8ab3489227a83f80e920faa039a71819f"
888 888 ],
889 889 "phase": "draft",
890 890 "tags": [],
891 891 "user": "test"
892 892 },
893 893 {
894 894 "bookmarks": [],
895 895 "branch": "test-branch",
896 896 "date": [
897 897 0.0,
898 898 0
899 899 ],
900 900 "desc": "create test branch",
901 901 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
902 902 "parents": [
903 903 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
904 904 ],
905 905 "phase": "draft",
906 906 "tags": [],
907 907 "user": "test"
908 908 },
909 909 {
910 910 "bookmarks": [
911 911 "bookmark2"
912 912 ],
913 913 "branch": "default",
914 914 "date": [
915 915 0.0,
916 916 0
917 917 ],
918 918 "desc": "create tag2",
919 919 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
920 920 "parents": [
921 921 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
922 922 ],
923 923 "phase": "draft",
924 924 "tags": [],
925 925 "user": "test"
926 926 },
927 927 {
928 928 "bookmarks": [],
929 929 "branch": "default",
930 930 "date": [
931 931 0.0,
932 932 0
933 933 ],
934 934 "desc": "another commit to da/foo",
935 935 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
936 936 "parents": [
937 937 "93a8ce14f89156426b7fa981af8042da53f03aa0"
938 938 ],
939 939 "phase": "draft",
940 940 "tags": [
941 941 "tag2"
942 942 ],
943 943 "user": "test"
944 944 },
945 945 {
946 946 "bookmarks": [],
947 947 "branch": "default",
948 948 "date": [
949 949 0.0,
950 950 0
951 951 ],
952 952 "desc": "create tag",
953 953 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
954 954 "parents": [
955 955 "78896eb0e102174ce9278438a95e12543e4367a7"
956 956 ],
957 957 "phase": "public",
958 958 "tags": [],
959 959 "user": "test"
960 960 },
961 961 {
962 962 "bookmarks": [],
963 963 "branch": "default",
964 964 "date": [
965 965 0.0,
966 966 0
967 967 ],
968 968 "desc": "move foo",
969 969 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
970 970 "parents": [
971 971 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
972 972 ],
973 973 "phase": "public",
974 974 "tags": [
975 975 "tag1"
976 976 ],
977 977 "user": "test"
978 978 },
979 979 {
980 980 "bookmarks": [
981 981 "bookmark1"
982 982 ],
983 983 "branch": "default",
984 984 "date": [
985 985 0.0,
986 986 0
987 987 ],
988 988 "desc": "modify da/foo",
989 989 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
990 990 "parents": [
991 991 "f8bbb9024b10f93cdbb8d940337398291d40dea8"
992 992 ],
993 993 "phase": "public",
994 994 "tags": [],
995 995 "user": "test"
996 996 },
997 997 {
998 998 "bookmarks": [],
999 999 "branch": "default",
1000 1000 "date": [
1001 1001 0.0,
1002 1002 0
1003 1003 ],
1004 1004 "desc": "modify foo",
1005 1005 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1006 1006 "parents": [
1007 1007 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1008 1008 ],
1009 1009 "phase": "public",
1010 1010 "tags": [],
1011 1011 "user": "test"
1012 1012 },
1013 1013 {
1014 1014 "bookmarks": [],
1015 1015 "branch": "default",
1016 1016 "date": [
1017 1017 0.0,
1018 1018 0
1019 1019 ],
1020 1020 "desc": "initial",
1021 1021 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1022 1022 "parents": [],
1023 1023 "phase": "public",
1024 1024 "tags": [],
1025 1025 "user": "test"
1026 1026 }
1027 1027 ],
1028 1028 "tags": [
1029 1029 {
1030 1030 "date": [
1031 1031 0.0,
1032 1032 0
1033 1033 ],
1034 1034 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1035 1035 "tag": "tag2"
1036 1036 },
1037 1037 {
1038 1038 "date": [
1039 1039 0.0,
1040 1040 0
1041 1041 ],
1042 1042 "node": "78896eb0e102174ce9278438a95e12543e4367a7",
1043 1043 "tag": "tag1"
1044 1044 }
1045 1045 ]
1046 1046 }
1047 1047
1048 1048 $ request json-changelog?rev=create
1049 1049 200 Script output follows
1050 1050
1051 1051 {
1052 1052 "entries": [
1053 1053 {
1054 1054 "bookmarks": [],
1055 1055 "branch": "test-branch",
1056 1056 "date": [
1057 1057 0.0,
1058 1058 0
1059 1059 ],
1060 1060 "desc": "create test branch",
1061 1061 "node": "6ab967a8ab3489227a83f80e920faa039a71819f",
1062 1062 "parents": [
1063 1063 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1064 1064 ],
1065 1065 "phase": "draft",
1066 1066 "tags": [],
1067 1067 "user": "test"
1068 1068 },
1069 1069 {
1070 1070 "bookmarks": [
1071 1071 "bookmark2"
1072 1072 ],
1073 1073 "branch": "default",
1074 1074 "date": [
1075 1075 0.0,
1076 1076 0
1077 1077 ],
1078 1078 "desc": "create tag2",
1079 1079 "node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
1080 1080 "parents": [
1081 1081 "f2890a05fea49bfaf9fb27ed5490894eba32da78"
1082 1082 ],
1083 1083 "phase": "draft",
1084 1084 "tags": [],
1085 1085 "user": "test"
1086 1086 },
1087 1087 {
1088 1088 "bookmarks": [],
1089 1089 "branch": "default",
1090 1090 "date": [
1091 1091 0.0,
1092 1092 0
1093 1093 ],
1094 1094 "desc": "create tag",
1095 1095 "node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
1096 1096 "parents": [
1097 1097 "78896eb0e102174ce9278438a95e12543e4367a7"
1098 1098 ],
1099 1099 "phase": "public",
1100 1100 "tags": [],
1101 1101 "user": "test"
1102 1102 }
1103 1103 ],
1104 1104 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
1105 1105 "query": "create"
1106 1106 }
1107 1107
1108 1108 filediff/{revision}/{path} shows changes to a file in a revision
1109 1109
1110 1110 $ request json-diff/f8bbb9024b10/foo
1111 1111 200 Script output follows
1112 1112
1113 1113 {
1114 1114 "author": "test",
1115 1115 "children": [],
1116 1116 "date": [
1117 1117 0.0,
1118 1118 0
1119 1119 ],
1120 1120 "desc": "modify foo",
1121 1121 "diff": [
1122 1122 {
1123 1123 "blockno": 1,
1124 1124 "lines": [
1125 1125 {
1126 1126 "l": "--- a/foo\tThu Jan 01 00:00:00 1970 +0000\n",
1127 1127 "n": 1,
1128 1128 "t": "-"
1129 1129 },
1130 1130 {
1131 1131 "l": "+++ b/foo\tThu Jan 01 00:00:00 1970 +0000\n",
1132 1132 "n": 2,
1133 1133 "t": "+"
1134 1134 },
1135 1135 {
1136 1136 "l": "@@ -1,1 +1,1 @@\n",
1137 1137 "n": 3,
1138 1138 "t": "@"
1139 1139 },
1140 1140 {
1141 1141 "l": "-foo\n",
1142 1142 "n": 4,
1143 1143 "t": "-"
1144 1144 },
1145 1145 {
1146 1146 "l": "+bar\n",
1147 1147 "n": 5,
1148 1148 "t": "+"
1149 1149 }
1150 1150 ]
1151 1151 }
1152 1152 ],
1153 1153 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1154 1154 "parents": [
1155 1155 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1156 1156 ],
1157 1157 "path": "foo"
1158 1158 }
1159 1159
1160 1160 comparison/{revision}/{path} shows information about before and after for a file
1161 1161
1162 1162 $ request json-comparison/f8bbb9024b10/foo
1163 1163 200 Script output follows
1164 1164
1165 1165 {
1166 1166 "author": "test",
1167 1167 "children": [],
1168 1168 "comparison": [
1169 1169 {
1170 1170 "lines": [
1171 1171 {
1172 1172 "ll": "foo",
1173 1173 "ln": 1,
1174 1174 "rl": "bar",
1175 1175 "rn": 1,
1176 1176 "t": "replace"
1177 1177 }
1178 1178 ]
1179 1179 }
1180 1180 ],
1181 1181 "date": [
1182 1182 0.0,
1183 1183 0
1184 1184 ],
1185 1185 "desc": "modify foo",
1186 1186 "leftnode": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1187 1187 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1188 1188 "parents": [
1189 1189 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1190 1190 ],
1191 1191 "path": "foo",
1192 1192 "rightnode": "f8bbb9024b10f93cdbb8d940337398291d40dea8"
1193 1193 }
1194 1194
1195 1195 annotate/{revision}/{path} shows annotations for each line
1196 1196
1197 1197 $ request json-annotate/f8bbb9024b10/foo
1198 1198 200 Script output follows
1199 1199
1200 1200 {
1201 1201 "abspath": "foo",
1202 1202 "annotate": [
1203 1203 {
1204 1204 "abspath": "foo",
1205 1205 "author": "test",
1206 1206 "desc": "modify foo",
1207 1207 "line": "bar\n",
1208 1208 "lineno": 1,
1209 1209 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1210 1210 "revdate": [
1211 1211 0.0,
1212 1212 0
1213 1213 ],
1214 1214 "targetline": 1
1215 1215 }
1216 1216 ],
1217 1217 "author": "test",
1218 1218 "children": [],
1219 1219 "date": [
1220 1220 0.0,
1221 1221 0
1222 1222 ],
1223 1223 "desc": "modify foo",
1224 1224 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1225 1225 "parents": [
1226 1226 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1227 1227 ],
1228 1228 "permissions": ""
1229 1229 }
1230 1230
1231 1231 filelog/{revision}/{path} shows history of a single file
1232 1232
1233 1233 $ request json-filelog/f8bbb9024b10/foo
1234 1234 200 Script output follows
1235 1235
1236 1236 {
1237 1237 "entries": [
1238 1238 {
1239 1239 "bookmarks": [],
1240 1240 "branch": "default",
1241 1241 "date": [
1242 1242 0.0,
1243 1243 0
1244 1244 ],
1245 1245 "desc": "modify foo",
1246 1246 "node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
1247 1247 "parents": [
1248 1248 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1249 1249 ],
1250 1250 "phase": "public",
1251 1251 "tags": [],
1252 1252 "user": "test"
1253 1253 },
1254 1254 {
1255 1255 "bookmarks": [],
1256 1256 "branch": "default",
1257 1257 "date": [
1258 1258 0.0,
1259 1259 0
1260 1260 ],
1261 1261 "desc": "initial",
1262 1262 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1263 1263 "parents": [],
1264 1264 "phase": "public",
1265 1265 "tags": [],
1266 1266 "user": "test"
1267 1267 }
1268 1268 ]
1269 1269 }
1270 1270
1271 1271 $ request json-filelog/cc725e08502a/da/foo
1272 1272 200 Script output follows
1273 1273
1274 1274 {
1275 1275 "entries": [
1276 1276 {
1277 1277 "bookmarks": [],
1278 1278 "branch": "default",
1279 1279 "date": [
1280 1280 0.0,
1281 1281 0
1282 1282 ],
1283 1283 "desc": "another commit to da/foo",
1284 1284 "node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
1285 1285 "parents": [
1286 1286 "8d7c456572acf3557e8ed8a07286b10c408bcec5"
1287 1287 ],
1288 1288 "phase": "draft",
1289 1289 "tags": [
1290 1290 "tag2"
1291 1291 ],
1292 1292 "user": "test"
1293 1293 },
1294 1294 {
1295 1295 "bookmarks": [
1296 1296 "bookmark1"
1297 1297 ],
1298 1298 "branch": "default",
1299 1299 "date": [
1300 1300 0.0,
1301 1301 0
1302 1302 ],
1303 1303 "desc": "modify da/foo",
1304 1304 "node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
1305 1305 "parents": [
1306 1306 "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
1307 1307 ],
1308 1308 "phase": "public",
1309 1309 "tags": [],
1310 1310 "user": "test"
1311 1311 },
1312 1312 {
1313 1313 "bookmarks": [],
1314 1314 "branch": "default",
1315 1315 "date": [
1316 1316 0.0,
1317 1317 0
1318 1318 ],
1319 1319 "desc": "initial",
1320 1320 "node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
1321 1321 "parents": [],
1322 1322 "phase": "public",
1323 1323 "tags": [],
1324 1324 "user": "test"
1325 1325 }
1326 1326 ]
1327 1327 }
1328 1328
1329 1329 (archive/ doesn't use templating, so ignore it)
1330 1330
1331 1331 (static/ doesn't use templating, so ignore it)
1332 1332
1333 1333 graph/ shows information that can be used to render a graph of the DAG
1334 1334
1335 1335 $ request json-graph
1336 1336 200 Script output follows
1337 1337
1338 1338 "not yet implemented"
1339 1339
1340 1340 help/ shows help topics
1341 1341
1342 1342 $ request json-help
1343 1343 200 Script output follows
1344 1344
1345 1345 {
1346 1346 "earlycommands": [
1347 1347 {
1348 1348 "summary": "add the specified files on the next commit",
1349 1349 "topic": "add"
1350 1350 },
1351 1351 {
1352 1352 "summary": "show changeset information by line for each file",
1353 1353 "topic": "annotate"
1354 1354 },
1355 1355 {
1356 1356 "summary": "make a copy of an existing repository",
1357 1357 "topic": "clone"
1358 1358 },
1359 1359 {
1360 1360 "summary": "commit the specified files or all outstanding changes",
1361 1361 "topic": "commit"
1362 1362 },
1363 1363 {
1364 1364 "summary": "diff repository (or selected files)",
1365 1365 "topic": "diff"
1366 1366 },
1367 1367 {
1368 1368 "summary": "dump the header and diffs for one or more changesets",
1369 1369 "topic": "export"
1370 1370 },
1371 1371 {
1372 1372 "summary": "forget the specified files on the next commit",
1373 1373 "topic": "forget"
1374 1374 },
1375 1375 {
1376 1376 "summary": "create a new repository in the given directory",
1377 1377 "topic": "init"
1378 1378 },
1379 1379 {
1380 1380 "summary": "show revision history of entire repository or files",
1381 1381 "topic": "log"
1382 1382 },
1383 1383 {
1384 1384 "summary": "merge another revision into working directory",
1385 1385 "topic": "merge"
1386 1386 },
1387 1387 {
1388 1388 "summary": "pull changes from the specified source",
1389 1389 "topic": "pull"
1390 1390 },
1391 1391 {
1392 1392 "summary": "push changes to the specified destination",
1393 1393 "topic": "push"
1394 1394 },
1395 1395 {
1396 1396 "summary": "remove the specified files on the next commit",
1397 1397 "topic": "remove"
1398 1398 },
1399 1399 {
1400 1400 "summary": "start stand-alone webserver",
1401 1401 "topic": "serve"
1402 1402 },
1403 1403 {
1404 1404 "summary": "show changed files in the working directory",
1405 1405 "topic": "status"
1406 1406 },
1407 1407 {
1408 1408 "summary": "summarize working directory state",
1409 1409 "topic": "summary"
1410 1410 },
1411 1411 {
1412 1412 "summary": "update working directory (or switch revisions)",
1413 1413 "topic": "update"
1414 1414 }
1415 1415 ],
1416 1416 "othercommands": [
1417 1417 {
1418 1418 "summary": "add all new files, delete all missing files",
1419 1419 "topic": "addremove"
1420 1420 },
1421 1421 {
1422 1422 "summary": "create an unversioned archive of a repository revision",
1423 1423 "topic": "archive"
1424 1424 },
1425 1425 {
1426 1426 "summary": "reverse effect of earlier changeset",
1427 1427 "topic": "backout"
1428 1428 },
1429 1429 {
1430 1430 "summary": "subdivision search of changesets",
1431 1431 "topic": "bisect"
1432 1432 },
1433 1433 {
1434 1434 "summary": "create a new bookmark or list existing bookmarks",
1435 1435 "topic": "bookmarks"
1436 1436 },
1437 1437 {
1438 1438 "summary": "set or show the current branch name",
1439 1439 "topic": "branch"
1440 1440 },
1441 1441 {
1442 1442 "summary": "list repository named branches",
1443 1443 "topic": "branches"
1444 1444 },
1445 1445 {
1446 "summary": "create a changegroup file",
1446 "summary": "create a bundle file",
1447 1447 "topic": "bundle"
1448 1448 },
1449 1449 {
1450 1450 "summary": "output the current or given revision of files",
1451 1451 "topic": "cat"
1452 1452 },
1453 1453 {
1454 1454 "summary": "show combined config settings from all hgrc files",
1455 1455 "topic": "config"
1456 1456 },
1457 1457 {
1458 1458 "summary": "mark files as copied for the next commit",
1459 1459 "topic": "copy"
1460 1460 },
1461 1461 {
1462 1462 "summary": "list tracked files",
1463 1463 "topic": "files"
1464 1464 },
1465 1465 {
1466 1466 "summary": "copy changes from other branches onto the current branch",
1467 1467 "topic": "graft"
1468 1468 },
1469 1469 {
1470 1470 "summary": "search revision history for a pattern in specified files",
1471 1471 "topic": "grep"
1472 1472 },
1473 1473 {
1474 1474 "summary": "show branch heads",
1475 1475 "topic": "heads"
1476 1476 },
1477 1477 {
1478 1478 "summary": "show help for a given topic or a help overview",
1479 1479 "topic": "help"
1480 1480 },
1481 1481 {
1482 1482 "summary": "identify the working directory or specified revision",
1483 1483 "topic": "identify"
1484 1484 },
1485 1485 {
1486 1486 "summary": "import an ordered set of patches",
1487 1487 "topic": "import"
1488 1488 },
1489 1489 {
1490 1490 "summary": "show new changesets found in source",
1491 1491 "topic": "incoming"
1492 1492 },
1493 1493 {
1494 1494 "summary": "output the current or given revision of the project manifest",
1495 1495 "topic": "manifest"
1496 1496 },
1497 1497 {
1498 1498 "summary": "show changesets not found in the destination",
1499 1499 "topic": "outgoing"
1500 1500 },
1501 1501 {
1502 1502 "summary": "show aliases for remote repositories",
1503 1503 "topic": "paths"
1504 1504 },
1505 1505 {
1506 1506 "summary": "set or show the current phase name",
1507 1507 "topic": "phase"
1508 1508 },
1509 1509 {
1510 1510 "summary": "roll back an interrupted transaction",
1511 1511 "topic": "recover"
1512 1512 },
1513 1513 {
1514 1514 "summary": "rename files; equivalent of copy + remove",
1515 1515 "topic": "rename"
1516 1516 },
1517 1517 {
1518 1518 "summary": "redo merges or set/view the merge status of files",
1519 1519 "topic": "resolve"
1520 1520 },
1521 1521 {
1522 1522 "summary": "restore files to their checkout state",
1523 1523 "topic": "revert"
1524 1524 },
1525 1525 {
1526 1526 "summary": "print the root (top) of the current working directory",
1527 1527 "topic": "root"
1528 1528 },
1529 1529 {
1530 1530 "summary": "add one or more tags for the current or given revision",
1531 1531 "topic": "tag"
1532 1532 },
1533 1533 {
1534 1534 "summary": "list repository tags",
1535 1535 "topic": "tags"
1536 1536 },
1537 1537 {
1538 1538 "summary": "apply one or more changegroup files",
1539 1539 "topic": "unbundle"
1540 1540 },
1541 1541 {
1542 1542 "summary": "verify the integrity of the repository",
1543 1543 "topic": "verify"
1544 1544 },
1545 1545 {
1546 1546 "summary": "output version and copyright information",
1547 1547 "topic": "version"
1548 1548 }
1549 1549 ],
1550 1550 "topics": [
1551 1551 {
1552 1552 "summary": "Bundle File Formats",
1553 1553 "topic": "bundlespec"
1554 1554 },
1555 1555 {
1556 1556 "summary": "Colorizing Outputs",
1557 1557 "topic": "color"
1558 1558 },
1559 1559 {
1560 1560 "summary": "Configuration Files",
1561 1561 "topic": "config"
1562 1562 },
1563 1563 {
1564 1564 "summary": "Date Formats",
1565 1565 "topic": "dates"
1566 1566 },
1567 1567 {
1568 1568 "summary": "Diff Formats",
1569 1569 "topic": "diffs"
1570 1570 },
1571 1571 {
1572 1572 "summary": "Environment Variables",
1573 1573 "topic": "environment"
1574 1574 },
1575 1575 {
1576 1576 "summary": "Using Additional Features",
1577 1577 "topic": "extensions"
1578 1578 },
1579 1579 {
1580 1580 "summary": "Specifying File Sets",
1581 1581 "topic": "filesets"
1582 1582 },
1583 1583 {
1584 1584 "summary": "Glossary",
1585 1585 "topic": "glossary"
1586 1586 },
1587 1587 {
1588 1588 "summary": "Syntax for Mercurial Ignore Files",
1589 1589 "topic": "hgignore"
1590 1590 },
1591 1591 {
1592 1592 "summary": "Configuring hgweb",
1593 1593 "topic": "hgweb"
1594 1594 },
1595 1595 {
1596 1596 "summary": "Technical implementation topics",
1597 1597 "topic": "internals"
1598 1598 },
1599 1599 {
1600 1600 "summary": "Merge Tools",
1601 1601 "topic": "merge-tools"
1602 1602 },
1603 1603 {
1604 1604 "summary": "Pager Support",
1605 1605 "topic": "pager"
1606 1606 },
1607 1607 {
1608 1608 "summary": "File Name Patterns",
1609 1609 "topic": "patterns"
1610 1610 },
1611 1611 {
1612 1612 "summary": "Working with Phases",
1613 1613 "topic": "phases"
1614 1614 },
1615 1615 {
1616 1616 "summary": "Specifying Revisions",
1617 1617 "topic": "revisions"
1618 1618 },
1619 1619 {
1620 1620 "summary": "Using Mercurial from scripts and automation",
1621 1621 "topic": "scripting"
1622 1622 },
1623 1623 {
1624 1624 "summary": "Subrepositories",
1625 1625 "topic": "subrepos"
1626 1626 },
1627 1627 {
1628 1628 "summary": "Template Usage",
1629 1629 "topic": "templating"
1630 1630 },
1631 1631 {
1632 1632 "summary": "URL Paths",
1633 1633 "topic": "urls"
1634 1634 }
1635 1635 ]
1636 1636 }
1637 1637
1638 1638 help/{topic} shows an individual help topic
1639 1639
1640 1640 $ request json-help/phases
1641 1641 200 Script output follows
1642 1642
1643 1643 {
1644 1644 "rawdoc": "Working with Phases\n*", (glob)
1645 1645 "topic": "phases"
1646 1646 }
General Comments 0
You need to be logged in to leave comments. Login now