##// END OF EJS Templates
remove: fix --force option help description (issue5177)...
liscju -
r28902:eb017d52 default
parent child Browse files
Show More
@@ -1,7244 +1,7244
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import difflib
11 11 import errno
12 12 import operator
13 13 import os
14 14 import random
15 15 import re
16 16 import shlex
17 17 import socket
18 18 import sys
19 19 import tempfile
20 20 import time
21 21
22 22 from .i18n import _
23 23 from .node import (
24 24 bin,
25 25 hex,
26 26 nullhex,
27 27 nullid,
28 28 nullrev,
29 29 short,
30 30 )
31 31 from . import (
32 32 archival,
33 33 bookmarks,
34 34 bundle2,
35 35 changegroup,
36 36 cmdutil,
37 37 commandserver,
38 38 context,
39 39 copies,
40 40 dagparser,
41 41 dagutil,
42 42 destutil,
43 43 discovery,
44 44 encoding,
45 45 error,
46 46 exchange,
47 47 extensions,
48 48 fileset,
49 49 graphmod,
50 50 hbisect,
51 51 help,
52 52 hg,
53 53 hgweb,
54 54 localrepo,
55 55 lock as lockmod,
56 56 merge as mergemod,
57 57 minirst,
58 58 obsolete,
59 59 patch,
60 60 phases,
61 61 pvec,
62 62 repair,
63 63 revlog,
64 64 revset,
65 65 scmutil,
66 66 setdiscovery,
67 67 simplemerge,
68 68 sshserver,
69 69 streamclone,
70 70 templatekw,
71 71 templater,
72 72 treediscovery,
73 73 ui as uimod,
74 74 util,
75 75 )
76 76
77 77 release = lockmod.release
78 78
79 79 table = {}
80 80
81 81 command = cmdutil.command(table)
82 82
83 83 # label constants
84 84 # until 3.5, bookmarks.current was the advertised name, not
85 85 # bookmarks.active, so we must use both to avoid breaking old
86 86 # custom styles
87 87 activebookmarklabel = 'bookmarks.active bookmarks.current'
88 88
89 89 # common command options
90 90
91 91 globalopts = [
92 92 ('R', 'repository', '',
93 93 _('repository root directory or name of overlay bundle file'),
94 94 _('REPO')),
95 95 ('', 'cwd', '',
96 96 _('change working directory'), _('DIR')),
97 97 ('y', 'noninteractive', None,
98 98 _('do not prompt, automatically pick the first choice for all prompts')),
99 99 ('q', 'quiet', None, _('suppress output')),
100 100 ('v', 'verbose', None, _('enable additional output')),
101 101 ('', 'config', [],
102 102 _('set/override config option (use \'section.name=value\')'),
103 103 _('CONFIG')),
104 104 ('', 'debug', None, _('enable debugging output')),
105 105 ('', 'debugger', None, _('start debugger')),
106 106 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
107 107 _('ENCODE')),
108 108 ('', 'encodingmode', encoding.encodingmode,
109 109 _('set the charset encoding mode'), _('MODE')),
110 110 ('', 'traceback', None, _('always print a traceback on exception')),
111 111 ('', 'time', None, _('time how long the command takes')),
112 112 ('', 'profile', None, _('print command execution profile')),
113 113 ('', 'version', None, _('output version information and exit')),
114 114 ('h', 'help', None, _('display help and exit')),
115 115 ('', 'hidden', False, _('consider hidden changesets')),
116 116 ]
117 117
118 118 dryrunopts = [('n', 'dry-run', None,
119 119 _('do not perform actions, just print output'))]
120 120
121 121 remoteopts = [
122 122 ('e', 'ssh', '',
123 123 _('specify ssh command to use'), _('CMD')),
124 124 ('', 'remotecmd', '',
125 125 _('specify hg command to run on the remote side'), _('CMD')),
126 126 ('', 'insecure', None,
127 127 _('do not verify server certificate (ignoring web.cacerts config)')),
128 128 ]
129 129
130 130 walkopts = [
131 131 ('I', 'include', [],
132 132 _('include names matching the given patterns'), _('PATTERN')),
133 133 ('X', 'exclude', [],
134 134 _('exclude names matching the given patterns'), _('PATTERN')),
135 135 ]
136 136
137 137 commitopts = [
138 138 ('m', 'message', '',
139 139 _('use text as commit message'), _('TEXT')),
140 140 ('l', 'logfile', '',
141 141 _('read commit message from file'), _('FILE')),
142 142 ]
143 143
144 144 commitopts2 = [
145 145 ('d', 'date', '',
146 146 _('record the specified date as commit date'), _('DATE')),
147 147 ('u', 'user', '',
148 148 _('record the specified user as committer'), _('USER')),
149 149 ]
150 150
151 151 # hidden for now
152 152 formatteropts = [
153 153 ('T', 'template', '',
154 154 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
155 155 ]
156 156
157 157 templateopts = [
158 158 ('', 'style', '',
159 159 _('display using template map file (DEPRECATED)'), _('STYLE')),
160 160 ('T', 'template', '',
161 161 _('display with template'), _('TEMPLATE')),
162 162 ]
163 163
164 164 logopts = [
165 165 ('p', 'patch', None, _('show patch')),
166 166 ('g', 'git', None, _('use git extended diff format')),
167 167 ('l', 'limit', '',
168 168 _('limit number of changes displayed'), _('NUM')),
169 169 ('M', 'no-merges', None, _('do not show merges')),
170 170 ('', 'stat', None, _('output diffstat-style summary of changes')),
171 171 ('G', 'graph', None, _("show the revision DAG")),
172 172 ] + templateopts
173 173
174 174 diffopts = [
175 175 ('a', 'text', None, _('treat all files as text')),
176 176 ('g', 'git', None, _('use git extended diff format')),
177 177 ('', 'nodates', None, _('omit dates from diff headers'))
178 178 ]
179 179
180 180 diffwsopts = [
181 181 ('w', 'ignore-all-space', None,
182 182 _('ignore white space when comparing lines')),
183 183 ('b', 'ignore-space-change', None,
184 184 _('ignore changes in the amount of white space')),
185 185 ('B', 'ignore-blank-lines', None,
186 186 _('ignore changes whose lines are all blank')),
187 187 ]
188 188
189 189 diffopts2 = [
190 190 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
191 191 ('p', 'show-function', None, _('show which function each change is in')),
192 192 ('', 'reverse', None, _('produce a diff that undoes the changes')),
193 193 ] + diffwsopts + [
194 194 ('U', 'unified', '',
195 195 _('number of lines of context to show'), _('NUM')),
196 196 ('', 'stat', None, _('output diffstat-style summary of changes')),
197 197 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
198 198 ]
199 199
200 200 mergetoolopts = [
201 201 ('t', 'tool', '', _('specify merge tool')),
202 202 ]
203 203
204 204 similarityopts = [
205 205 ('s', 'similarity', '',
206 206 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
207 207 ]
208 208
209 209 subrepoopts = [
210 210 ('S', 'subrepos', None,
211 211 _('recurse into subrepositories'))
212 212 ]
213 213
214 214 debugrevlogopts = [
215 215 ('c', 'changelog', False, _('open changelog')),
216 216 ('m', 'manifest', False, _('open manifest')),
217 217 ('', 'dir', False, _('open directory manifest')),
218 218 ]
219 219
220 220 # Commands start here, listed alphabetically
221 221
222 222 @command('^add',
223 223 walkopts + subrepoopts + dryrunopts,
224 224 _('[OPTION]... [FILE]...'),
225 225 inferrepo=True)
226 226 def add(ui, repo, *pats, **opts):
227 227 """add the specified files on the next commit
228 228
229 229 Schedule files to be version controlled and added to the
230 230 repository.
231 231
232 232 The files will be added to the repository at the next commit. To
233 233 undo an add before that, see :hg:`forget`.
234 234
235 235 If no names are given, add all files to the repository (except
236 236 files matching ``.hgignore``).
237 237
238 238 .. container:: verbose
239 239
240 240 Examples:
241 241
242 242 - New (unknown) files are added
243 243 automatically by :hg:`add`::
244 244
245 245 $ ls
246 246 foo.c
247 247 $ hg status
248 248 ? foo.c
249 249 $ hg add
250 250 adding foo.c
251 251 $ hg status
252 252 A foo.c
253 253
254 254 - Specific files to be added can be specified::
255 255
256 256 $ ls
257 257 bar.c foo.c
258 258 $ hg status
259 259 ? bar.c
260 260 ? foo.c
261 261 $ hg add bar.c
262 262 $ hg status
263 263 A bar.c
264 264 ? foo.c
265 265
266 266 Returns 0 if all files are successfully added.
267 267 """
268 268
269 269 m = scmutil.match(repo[None], pats, opts)
270 270 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
271 271 return rejected and 1 or 0
272 272
273 273 @command('addremove',
274 274 similarityopts + subrepoopts + walkopts + dryrunopts,
275 275 _('[OPTION]... [FILE]...'),
276 276 inferrepo=True)
277 277 def addremove(ui, repo, *pats, **opts):
278 278 """add all new files, delete all missing files
279 279
280 280 Add all new files and remove all missing files from the
281 281 repository.
282 282
283 283 Unless names are given, new files are ignored if they match any of
284 284 the patterns in ``.hgignore``. As with add, these changes take
285 285 effect at the next commit.
286 286
287 287 Use the -s/--similarity option to detect renamed files. This
288 288 option takes a percentage between 0 (disabled) and 100 (files must
289 289 be identical) as its parameter. With a parameter greater than 0,
290 290 this compares every removed file with every added file and records
291 291 those similar enough as renames. Detecting renamed files this way
292 292 can be expensive. After using this option, :hg:`status -C` can be
293 293 used to check which files were identified as moved or renamed. If
294 294 not specified, -s/--similarity defaults to 100 and only renames of
295 295 identical files are detected.
296 296
297 297 .. container:: verbose
298 298
299 299 Examples:
300 300
301 301 - A number of files (bar.c and foo.c) are new,
302 302 while foobar.c has been removed (without using :hg:`remove`)
303 303 from the repository::
304 304
305 305 $ ls
306 306 bar.c foo.c
307 307 $ hg status
308 308 ! foobar.c
309 309 ? bar.c
310 310 ? foo.c
311 311 $ hg addremove
312 312 adding bar.c
313 313 adding foo.c
314 314 removing foobar.c
315 315 $ hg status
316 316 A bar.c
317 317 A foo.c
318 318 R foobar.c
319 319
320 320 - A file foobar.c was moved to foo.c without using :hg:`rename`.
321 321 Afterwards, it was edited slightly::
322 322
323 323 $ ls
324 324 foo.c
325 325 $ hg status
326 326 ! foobar.c
327 327 ? foo.c
328 328 $ hg addremove --similarity 90
329 329 removing foobar.c
330 330 adding foo.c
331 331 recording removal of foobar.c as rename to foo.c (94% similar)
332 332 $ hg status -C
333 333 A foo.c
334 334 foobar.c
335 335 R foobar.c
336 336
337 337 Returns 0 if all files are successfully added.
338 338 """
339 339 try:
340 340 sim = float(opts.get('similarity') or 100)
341 341 except ValueError:
342 342 raise error.Abort(_('similarity must be a number'))
343 343 if sim < 0 or sim > 100:
344 344 raise error.Abort(_('similarity must be between 0 and 100'))
345 345 matcher = scmutil.match(repo[None], pats, opts)
346 346 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
347 347
348 348 @command('^annotate|blame',
349 349 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
350 350 ('', 'follow', None,
351 351 _('follow copies/renames and list the filename (DEPRECATED)')),
352 352 ('', 'no-follow', None, _("don't follow copies and renames")),
353 353 ('a', 'text', None, _('treat all files as text')),
354 354 ('u', 'user', None, _('list the author (long with -v)')),
355 355 ('f', 'file', None, _('list the filename')),
356 356 ('d', 'date', None, _('list the date (short with -q)')),
357 357 ('n', 'number', None, _('list the revision number (default)')),
358 358 ('c', 'changeset', None, _('list the changeset')),
359 359 ('l', 'line-number', None, _('show line number at the first appearance'))
360 360 ] + diffwsopts + walkopts + formatteropts,
361 361 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
362 362 inferrepo=True)
363 363 def annotate(ui, repo, *pats, **opts):
364 364 """show changeset information by line for each file
365 365
366 366 List changes in files, showing the revision id responsible for
367 367 each line.
368 368
369 369 This command is useful for discovering when a change was made and
370 370 by whom.
371 371
372 372 If you include --file, --user, or --date, the revision number is
373 373 suppressed unless you also include --number.
374 374
375 375 Without the -a/--text option, annotate will avoid processing files
376 376 it detects as binary. With -a, annotate will annotate the file
377 377 anyway, although the results will probably be neither useful
378 378 nor desirable.
379 379
380 380 Returns 0 on success.
381 381 """
382 382 if not pats:
383 383 raise error.Abort(_('at least one filename or pattern is required'))
384 384
385 385 if opts.get('follow'):
386 386 # --follow is deprecated and now just an alias for -f/--file
387 387 # to mimic the behavior of Mercurial before version 1.5
388 388 opts['file'] = True
389 389
390 390 ctx = scmutil.revsingle(repo, opts.get('rev'))
391 391
392 392 fm = ui.formatter('annotate', opts)
393 393 if ui.quiet:
394 394 datefunc = util.shortdate
395 395 else:
396 396 datefunc = util.datestr
397 397 if ctx.rev() is None:
398 398 def hexfn(node):
399 399 if node is None:
400 400 return None
401 401 else:
402 402 return fm.hexfunc(node)
403 403 if opts.get('changeset'):
404 404 # omit "+" suffix which is appended to node hex
405 405 def formatrev(rev):
406 406 if rev is None:
407 407 return '%d' % ctx.p1().rev()
408 408 else:
409 409 return '%d' % rev
410 410 else:
411 411 def formatrev(rev):
412 412 if rev is None:
413 413 return '%d+' % ctx.p1().rev()
414 414 else:
415 415 return '%d ' % rev
416 416 def formathex(hex):
417 417 if hex is None:
418 418 return '%s+' % fm.hexfunc(ctx.p1().node())
419 419 else:
420 420 return '%s ' % hex
421 421 else:
422 422 hexfn = fm.hexfunc
423 423 formatrev = formathex = str
424 424
425 425 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
426 426 ('number', ' ', lambda x: x[0].rev(), formatrev),
427 427 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
428 428 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
429 429 ('file', ' ', lambda x: x[0].path(), str),
430 430 ('line_number', ':', lambda x: x[1], str),
431 431 ]
432 432 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
433 433
434 434 if (not opts.get('user') and not opts.get('changeset')
435 435 and not opts.get('date') and not opts.get('file')):
436 436 opts['number'] = True
437 437
438 438 linenumber = opts.get('line_number') is not None
439 439 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
440 440 raise error.Abort(_('at least one of -n/-c is required for -l'))
441 441
442 442 if fm:
443 443 def makefunc(get, fmt):
444 444 return get
445 445 else:
446 446 def makefunc(get, fmt):
447 447 return lambda x: fmt(get(x))
448 448 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
449 449 if opts.get(op)]
450 450 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
451 451 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
452 452 if opts.get(op))
453 453
454 454 def bad(x, y):
455 455 raise error.Abort("%s: %s" % (x, y))
456 456
457 457 m = scmutil.match(ctx, pats, opts, badfn=bad)
458 458
459 459 follow = not opts.get('no_follow')
460 460 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
461 461 whitespace=True)
462 462 for abs in ctx.walk(m):
463 463 fctx = ctx[abs]
464 464 if not opts.get('text') and util.binary(fctx.data()):
465 465 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
466 466 continue
467 467
468 468 lines = fctx.annotate(follow=follow, linenumber=linenumber,
469 469 diffopts=diffopts)
470 470 formats = []
471 471 pieces = []
472 472
473 473 for f, sep in funcmap:
474 474 l = [f(n) for n, dummy in lines]
475 475 if l:
476 476 if fm:
477 477 formats.append(['%s' for x in l])
478 478 else:
479 479 sizes = [encoding.colwidth(x) for x in l]
480 480 ml = max(sizes)
481 481 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
482 482 pieces.append(l)
483 483
484 484 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
485 485 fm.startitem()
486 486 fm.write(fields, "".join(f), *p)
487 487 fm.write('line', ": %s", l[1])
488 488
489 489 if lines and not lines[-1][1].endswith('\n'):
490 490 fm.plain('\n')
491 491
492 492 fm.end()
493 493
494 494 @command('archive',
495 495 [('', 'no-decode', None, _('do not pass files through decoders')),
496 496 ('p', 'prefix', '', _('directory prefix for files in archive'),
497 497 _('PREFIX')),
498 498 ('r', 'rev', '', _('revision to distribute'), _('REV')),
499 499 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
500 500 ] + subrepoopts + walkopts,
501 501 _('[OPTION]... DEST'))
502 502 def archive(ui, repo, dest, **opts):
503 503 '''create an unversioned archive of a repository revision
504 504
505 505 By default, the revision used is the parent of the working
506 506 directory; use -r/--rev to specify a different revision.
507 507
508 508 The archive type is automatically detected based on file
509 509 extension (to override, use -t/--type).
510 510
511 511 .. container:: verbose
512 512
513 513 Examples:
514 514
515 515 - create a zip file containing the 1.0 release::
516 516
517 517 hg archive -r 1.0 project-1.0.zip
518 518
519 519 - create a tarball excluding .hg files::
520 520
521 521 hg archive project.tar.gz -X ".hg*"
522 522
523 523 Valid types are:
524 524
525 525 :``files``: a directory full of files (default)
526 526 :``tar``: tar archive, uncompressed
527 527 :``tbz2``: tar archive, compressed using bzip2
528 528 :``tgz``: tar archive, compressed using gzip
529 529 :``uzip``: zip archive, uncompressed
530 530 :``zip``: zip archive, compressed using deflate
531 531
532 532 The exact name of the destination archive or directory is given
533 533 using a format string; see :hg:`help export` for details.
534 534
535 535 Each member added to an archive file has a directory prefix
536 536 prepended. Use -p/--prefix to specify a format string for the
537 537 prefix. The default is the basename of the archive, with suffixes
538 538 removed.
539 539
540 540 Returns 0 on success.
541 541 '''
542 542
543 543 ctx = scmutil.revsingle(repo, opts.get('rev'))
544 544 if not ctx:
545 545 raise error.Abort(_('no working directory: please specify a revision'))
546 546 node = ctx.node()
547 547 dest = cmdutil.makefilename(repo, dest, node)
548 548 if os.path.realpath(dest) == repo.root:
549 549 raise error.Abort(_('repository root cannot be destination'))
550 550
551 551 kind = opts.get('type') or archival.guesskind(dest) or 'files'
552 552 prefix = opts.get('prefix')
553 553
554 554 if dest == '-':
555 555 if kind == 'files':
556 556 raise error.Abort(_('cannot archive plain files to stdout'))
557 557 dest = cmdutil.makefileobj(repo, dest)
558 558 if not prefix:
559 559 prefix = os.path.basename(repo.root) + '-%h'
560 560
561 561 prefix = cmdutil.makefilename(repo, prefix, node)
562 562 matchfn = scmutil.match(ctx, [], opts)
563 563 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
564 564 matchfn, prefix, subrepos=opts.get('subrepos'))
565 565
566 566 @command('backout',
567 567 [('', 'merge', None, _('merge with old dirstate parent after backout')),
568 568 ('', 'commit', None,
569 569 _('commit if no conflicts were encountered (DEPRECATED)')),
570 570 ('', 'no-commit', None, _('do not commit')),
571 571 ('', 'parent', '',
572 572 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
573 573 ('r', 'rev', '', _('revision to backout'), _('REV')),
574 574 ('e', 'edit', False, _('invoke editor on commit messages')),
575 575 ] + mergetoolopts + walkopts + commitopts + commitopts2,
576 576 _('[OPTION]... [-r] REV'))
577 577 def backout(ui, repo, node=None, rev=None, **opts):
578 578 '''reverse effect of earlier changeset
579 579
580 580 Prepare a new changeset with the effect of REV undone in the
581 581 current working directory. If no conflicts were encountered,
582 582 it will be committed immediately.
583 583
584 584 If REV is the parent of the working directory, then this new changeset
585 585 is committed automatically (unless --no-commit is specified).
586 586
587 587 .. note::
588 588
589 589 :hg:`backout` cannot be used to fix either an unwanted or
590 590 incorrect merge.
591 591
592 592 .. container:: verbose
593 593
594 594 Examples:
595 595
596 596 - Reverse the effect of the parent of the working directory.
597 597 This backout will be committed immediately::
598 598
599 599 hg backout -r .
600 600
601 601 - Reverse the effect of previous bad revision 23::
602 602
603 603 hg backout -r 23
604 604
605 605 - Reverse the effect of previous bad revision 23 and
606 606 leave changes uncommitted::
607 607
608 608 hg backout -r 23 --no-commit
609 609 hg commit -m "Backout revision 23"
610 610
611 611 By default, the pending changeset will have one parent,
612 612 maintaining a linear history. With --merge, the pending
613 613 changeset will instead have two parents: the old parent of the
614 614 working directory and a new child of REV that simply undoes REV.
615 615
616 616 Before version 1.7, the behavior without --merge was equivalent
617 617 to specifying --merge followed by :hg:`update --clean .` to
618 618 cancel the merge and leave the child of REV as a head to be
619 619 merged separately.
620 620
621 621 See :hg:`help dates` for a list of formats valid for -d/--date.
622 622
623 623 See :hg:`help revert` for a way to restore files to the state
624 624 of another revision.
625 625
626 626 Returns 0 on success, 1 if nothing to backout or there are unresolved
627 627 files.
628 628 '''
629 629 wlock = lock = None
630 630 try:
631 631 wlock = repo.wlock()
632 632 lock = repo.lock()
633 633 return _dobackout(ui, repo, node, rev, **opts)
634 634 finally:
635 635 release(lock, wlock)
636 636
637 637 def _dobackout(ui, repo, node=None, rev=None, **opts):
638 638 if opts.get('commit') and opts.get('no_commit'):
639 639 raise error.Abort(_("cannot use --commit with --no-commit"))
640 640 if opts.get('merge') and opts.get('no_commit'):
641 641 raise error.Abort(_("cannot use --merge with --no-commit"))
642 642
643 643 if rev and node:
644 644 raise error.Abort(_("please specify just one revision"))
645 645
646 646 if not rev:
647 647 rev = node
648 648
649 649 if not rev:
650 650 raise error.Abort(_("please specify a revision to backout"))
651 651
652 652 date = opts.get('date')
653 653 if date:
654 654 opts['date'] = util.parsedate(date)
655 655
656 656 cmdutil.checkunfinished(repo)
657 657 cmdutil.bailifchanged(repo)
658 658 node = scmutil.revsingle(repo, rev).node()
659 659
660 660 op1, op2 = repo.dirstate.parents()
661 661 if not repo.changelog.isancestor(node, op1):
662 662 raise error.Abort(_('cannot backout change that is not an ancestor'))
663 663
664 664 p1, p2 = repo.changelog.parents(node)
665 665 if p1 == nullid:
666 666 raise error.Abort(_('cannot backout a change with no parents'))
667 667 if p2 != nullid:
668 668 if not opts.get('parent'):
669 669 raise error.Abort(_('cannot backout a merge changeset'))
670 670 p = repo.lookup(opts['parent'])
671 671 if p not in (p1, p2):
672 672 raise error.Abort(_('%s is not a parent of %s') %
673 673 (short(p), short(node)))
674 674 parent = p
675 675 else:
676 676 if opts.get('parent'):
677 677 raise error.Abort(_('cannot use --parent on non-merge changeset'))
678 678 parent = p1
679 679
680 680 # the backout should appear on the same branch
681 681 branch = repo.dirstate.branch()
682 682 bheads = repo.branchheads(branch)
683 683 rctx = scmutil.revsingle(repo, hex(parent))
684 684 if not opts.get('merge') and op1 != node:
685 685 dsguard = cmdutil.dirstateguard(repo, 'backout')
686 686 try:
687 687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
688 688 'backout')
689 689 stats = mergemod.update(repo, parent, True, True, node, False)
690 690 repo.setparents(op1, op2)
691 691 dsguard.close()
692 692 hg._showstats(repo, stats)
693 693 if stats[3]:
694 694 repo.ui.status(_("use 'hg resolve' to retry unresolved "
695 695 "file merges\n"))
696 696 return 1
697 697 finally:
698 698 ui.setconfig('ui', 'forcemerge', '', '')
699 699 lockmod.release(dsguard)
700 700 else:
701 701 hg.clean(repo, node, show_stats=False)
702 702 repo.dirstate.setbranch(branch)
703 703 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
704 704
705 705 if opts.get('no_commit'):
706 706 msg = _("changeset %s backed out, "
707 707 "don't forget to commit.\n")
708 708 ui.status(msg % short(node))
709 709 return 0
710 710
711 711 def commitfunc(ui, repo, message, match, opts):
712 712 editform = 'backout'
713 713 e = cmdutil.getcommiteditor(editform=editform, **opts)
714 714 if not message:
715 715 # we don't translate commit messages
716 716 message = "Backed out changeset %s" % short(node)
717 717 e = cmdutil.getcommiteditor(edit=True, editform=editform)
718 718 return repo.commit(message, opts.get('user'), opts.get('date'),
719 719 match, editor=e)
720 720 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
721 721 if not newnode:
722 722 ui.status(_("nothing changed\n"))
723 723 return 1
724 724 cmdutil.commitstatus(repo, newnode, branch, bheads)
725 725
726 726 def nice(node):
727 727 return '%d:%s' % (repo.changelog.rev(node), short(node))
728 728 ui.status(_('changeset %s backs out changeset %s\n') %
729 729 (nice(repo.changelog.tip()), nice(node)))
730 730 if opts.get('merge') and op1 != node:
731 731 hg.clean(repo, op1, show_stats=False)
732 732 ui.status(_('merging with changeset %s\n')
733 733 % nice(repo.changelog.tip()))
734 734 try:
735 735 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
736 736 'backout')
737 737 return hg.merge(repo, hex(repo.changelog.tip()))
738 738 finally:
739 739 ui.setconfig('ui', 'forcemerge', '', '')
740 740 return 0
741 741
742 742 @command('bisect',
743 743 [('r', 'reset', False, _('reset bisect state')),
744 744 ('g', 'good', False, _('mark changeset good')),
745 745 ('b', 'bad', False, _('mark changeset bad')),
746 746 ('s', 'skip', False, _('skip testing changeset')),
747 747 ('e', 'extend', False, _('extend the bisect range')),
748 748 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
749 749 ('U', 'noupdate', False, _('do not update to target'))],
750 750 _("[-gbsr] [-U] [-c CMD] [REV]"))
751 751 def bisect(ui, repo, rev=None, extra=None, command=None,
752 752 reset=None, good=None, bad=None, skip=None, extend=None,
753 753 noupdate=None):
754 754 """subdivision search of changesets
755 755
756 756 This command helps to find changesets which introduce problems. To
757 757 use, mark the earliest changeset you know exhibits the problem as
758 758 bad, then mark the latest changeset which is free from the problem
759 759 as good. Bisect will update your working directory to a revision
760 760 for testing (unless the -U/--noupdate option is specified). Once
761 761 you have performed tests, mark the working directory as good or
762 762 bad, and bisect will either update to another candidate changeset
763 763 or announce that it has found the bad revision.
764 764
765 765 As a shortcut, you can also use the revision argument to mark a
766 766 revision as good or bad without checking it out first.
767 767
768 768 If you supply a command, it will be used for automatic bisection.
769 769 The environment variable HG_NODE will contain the ID of the
770 770 changeset being tested. The exit status of the command will be
771 771 used to mark revisions as good or bad: status 0 means good, 125
772 772 means to skip the revision, 127 (command not found) will abort the
773 773 bisection, and any other non-zero exit status means the revision
774 774 is bad.
775 775
776 776 .. container:: verbose
777 777
778 778 Some examples:
779 779
780 780 - start a bisection with known bad revision 34, and good revision 12::
781 781
782 782 hg bisect --bad 34
783 783 hg bisect --good 12
784 784
785 785 - advance the current bisection by marking current revision as good or
786 786 bad::
787 787
788 788 hg bisect --good
789 789 hg bisect --bad
790 790
791 791 - mark the current revision, or a known revision, to be skipped (e.g. if
792 792 that revision is not usable because of another issue)::
793 793
794 794 hg bisect --skip
795 795 hg bisect --skip 23
796 796
797 797 - skip all revisions that do not touch directories ``foo`` or ``bar``::
798 798
799 799 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
800 800
801 801 - forget the current bisection::
802 802
803 803 hg bisect --reset
804 804
805 805 - use 'make && make tests' to automatically find the first broken
806 806 revision::
807 807
808 808 hg bisect --reset
809 809 hg bisect --bad 34
810 810 hg bisect --good 12
811 811 hg bisect --command "make && make tests"
812 812
813 813 - see all changesets whose states are already known in the current
814 814 bisection::
815 815
816 816 hg log -r "bisect(pruned)"
817 817
818 818 - see the changeset currently being bisected (especially useful
819 819 if running with -U/--noupdate)::
820 820
821 821 hg log -r "bisect(current)"
822 822
823 823 - see all changesets that took part in the current bisection::
824 824
825 825 hg log -r "bisect(range)"
826 826
827 827 - you can even get a nice graph::
828 828
829 829 hg log --graph -r "bisect(range)"
830 830
831 831 See :hg:`help revsets` for more about the `bisect()` keyword.
832 832
833 833 Returns 0 on success.
834 834 """
835 835 def extendbisectrange(nodes, good):
836 836 # bisect is incomplete when it ends on a merge node and
837 837 # one of the parent was not checked.
838 838 parents = repo[nodes[0]].parents()
839 839 if len(parents) > 1:
840 840 if good:
841 841 side = state['bad']
842 842 else:
843 843 side = state['good']
844 844 num = len(set(i.node() for i in parents) & set(side))
845 845 if num == 1:
846 846 return parents[0].ancestor(parents[1])
847 847 return None
848 848
849 849 def print_result(nodes, good):
850 850 displayer = cmdutil.show_changeset(ui, repo, {})
851 851 if len(nodes) == 1:
852 852 # narrowed it down to a single revision
853 853 if good:
854 854 ui.write(_("The first good revision is:\n"))
855 855 else:
856 856 ui.write(_("The first bad revision is:\n"))
857 857 displayer.show(repo[nodes[0]])
858 858 extendnode = extendbisectrange(nodes, good)
859 859 if extendnode is not None:
860 860 ui.write(_('Not all ancestors of this changeset have been'
861 861 ' checked.\nUse bisect --extend to continue the '
862 862 'bisection from\nthe common ancestor, %s.\n')
863 863 % extendnode)
864 864 else:
865 865 # multiple possible revisions
866 866 if good:
867 867 ui.write(_("Due to skipped revisions, the first "
868 868 "good revision could be any of:\n"))
869 869 else:
870 870 ui.write(_("Due to skipped revisions, the first "
871 871 "bad revision could be any of:\n"))
872 872 for n in nodes:
873 873 displayer.show(repo[n])
874 874 displayer.close()
875 875
876 876 def check_state(state, interactive=True):
877 877 if not state['good'] or not state['bad']:
878 878 if (good or bad or skip or reset) and interactive:
879 879 return
880 880 if not state['good']:
881 881 raise error.Abort(_('cannot bisect (no known good revisions)'))
882 882 else:
883 883 raise error.Abort(_('cannot bisect (no known bad revisions)'))
884 884 return True
885 885
886 886 # backward compatibility
887 887 if rev in "good bad reset init".split():
888 888 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
889 889 cmd, rev, extra = rev, extra, None
890 890 if cmd == "good":
891 891 good = True
892 892 elif cmd == "bad":
893 893 bad = True
894 894 else:
895 895 reset = True
896 896 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
897 897 raise error.Abort(_('incompatible arguments'))
898 898
899 899 cmdutil.checkunfinished(repo)
900 900
901 901 if reset:
902 902 p = repo.join("bisect.state")
903 903 if os.path.exists(p):
904 904 os.unlink(p)
905 905 return
906 906
907 907 state = hbisect.load_state(repo)
908 908
909 909 if command:
910 910 changesets = 1
911 911 if noupdate:
912 912 try:
913 913 node = state['current'][0]
914 914 except LookupError:
915 915 raise error.Abort(_('current bisect revision is unknown - '
916 916 'start a new bisect to fix'))
917 917 else:
918 918 node, p2 = repo.dirstate.parents()
919 919 if p2 != nullid:
920 920 raise error.Abort(_('current bisect revision is a merge'))
921 921 try:
922 922 while changesets:
923 923 # update state
924 924 state['current'] = [node]
925 925 hbisect.save_state(repo, state)
926 926 status = ui.system(command, environ={'HG_NODE': hex(node)})
927 927 if status == 125:
928 928 transition = "skip"
929 929 elif status == 0:
930 930 transition = "good"
931 931 # status < 0 means process was killed
932 932 elif status == 127:
933 933 raise error.Abort(_("failed to execute %s") % command)
934 934 elif status < 0:
935 935 raise error.Abort(_("%s killed") % command)
936 936 else:
937 937 transition = "bad"
938 938 ctx = scmutil.revsingle(repo, rev, node)
939 939 rev = None # clear for future iterations
940 940 state[transition].append(ctx.node())
941 941 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
942 942 check_state(state, interactive=False)
943 943 # bisect
944 944 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
945 945 # update to next check
946 946 node = nodes[0]
947 947 if not noupdate:
948 948 cmdutil.bailifchanged(repo)
949 949 hg.clean(repo, node, show_stats=False)
950 950 finally:
951 951 state['current'] = [node]
952 952 hbisect.save_state(repo, state)
953 953 print_result(nodes, bgood)
954 954 return
955 955
956 956 # update state
957 957
958 958 if rev:
959 959 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
960 960 else:
961 961 nodes = [repo.lookup('.')]
962 962
963 963 if good or bad or skip:
964 964 if good:
965 965 state['good'] += nodes
966 966 elif bad:
967 967 state['bad'] += nodes
968 968 elif skip:
969 969 state['skip'] += nodes
970 970 hbisect.save_state(repo, state)
971 971
972 972 if not check_state(state):
973 973 return
974 974
975 975 # actually bisect
976 976 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
977 977 if extend:
978 978 if not changesets:
979 979 extendnode = extendbisectrange(nodes, good)
980 980 if extendnode is not None:
981 981 ui.write(_("Extending search to changeset %d:%s\n")
982 982 % (extendnode.rev(), extendnode))
983 983 state['current'] = [extendnode.node()]
984 984 hbisect.save_state(repo, state)
985 985 if noupdate:
986 986 return
987 987 cmdutil.bailifchanged(repo)
988 988 return hg.clean(repo, extendnode.node())
989 989 raise error.Abort(_("nothing to extend"))
990 990
991 991 if changesets == 0:
992 992 print_result(nodes, good)
993 993 else:
994 994 assert len(nodes) == 1 # only a single node can be tested next
995 995 node = nodes[0]
996 996 # compute the approximate number of remaining tests
997 997 tests, size = 0, 2
998 998 while size <= changesets:
999 999 tests, size = tests + 1, size * 2
1000 1000 rev = repo.changelog.rev(node)
1001 1001 ui.write(_("Testing changeset %d:%s "
1002 1002 "(%d changesets remaining, ~%d tests)\n")
1003 1003 % (rev, short(node), changesets, tests))
1004 1004 state['current'] = [node]
1005 1005 hbisect.save_state(repo, state)
1006 1006 if not noupdate:
1007 1007 cmdutil.bailifchanged(repo)
1008 1008 return hg.clean(repo, node)
1009 1009
1010 1010 @command('bookmarks|bookmark',
1011 1011 [('f', 'force', False, _('force')),
1012 1012 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1013 1013 ('d', 'delete', False, _('delete a given bookmark')),
1014 1014 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1015 1015 ('i', 'inactive', False, _('mark a bookmark inactive')),
1016 1016 ] + formatteropts,
1017 1017 _('hg bookmarks [OPTIONS]... [NAME]...'))
1018 1018 def bookmark(ui, repo, *names, **opts):
1019 1019 '''create a new bookmark or list existing bookmarks
1020 1020
1021 1021 Bookmarks are labels on changesets to help track lines of development.
1022 1022 Bookmarks are unversioned and can be moved, renamed and deleted.
1023 1023 Deleting or moving a bookmark has no effect on the associated changesets.
1024 1024
1025 1025 Creating or updating to a bookmark causes it to be marked as 'active'.
1026 1026 The active bookmark is indicated with a '*'.
1027 1027 When a commit is made, the active bookmark will advance to the new commit.
1028 1028 A plain :hg:`update` will also advance an active bookmark, if possible.
1029 1029 Updating away from a bookmark will cause it to be deactivated.
1030 1030
1031 1031 Bookmarks can be pushed and pulled between repositories (see
1032 1032 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1033 1033 diverged, a new 'divergent bookmark' of the form 'name@path' will
1034 1034 be created. Using :hg:`merge` will resolve the divergence.
1035 1035
1036 1036 A bookmark named '@' has the special property that :hg:`clone` will
1037 1037 check it out by default if it exists.
1038 1038
1039 1039 .. container:: verbose
1040 1040
1041 1041 Examples:
1042 1042
1043 1043 - create an active bookmark for a new line of development::
1044 1044
1045 1045 hg book new-feature
1046 1046
1047 1047 - create an inactive bookmark as a place marker::
1048 1048
1049 1049 hg book -i reviewed
1050 1050
1051 1051 - create an inactive bookmark on another changeset::
1052 1052
1053 1053 hg book -r .^ tested
1054 1054
1055 1055 - rename bookmark turkey to dinner::
1056 1056
1057 1057 hg book -m turkey dinner
1058 1058
1059 1059 - move the '@' bookmark from another branch::
1060 1060
1061 1061 hg book -f @
1062 1062 '''
1063 1063 force = opts.get('force')
1064 1064 rev = opts.get('rev')
1065 1065 delete = opts.get('delete')
1066 1066 rename = opts.get('rename')
1067 1067 inactive = opts.get('inactive')
1068 1068
1069 1069 def checkformat(mark):
1070 1070 mark = mark.strip()
1071 1071 if not mark:
1072 1072 raise error.Abort(_("bookmark names cannot consist entirely of "
1073 1073 "whitespace"))
1074 1074 scmutil.checknewlabel(repo, mark, 'bookmark')
1075 1075 return mark
1076 1076
1077 1077 def checkconflict(repo, mark, cur, force=False, target=None):
1078 1078 if mark in marks and not force:
1079 1079 if target:
1080 1080 if marks[mark] == target and target == cur:
1081 1081 # re-activating a bookmark
1082 1082 return
1083 1083 anc = repo.changelog.ancestors([repo[target].rev()])
1084 1084 bmctx = repo[marks[mark]]
1085 1085 divs = [repo[b].node() for b in marks
1086 1086 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1087 1087
1088 1088 # allow resolving a single divergent bookmark even if moving
1089 1089 # the bookmark across branches when a revision is specified
1090 1090 # that contains a divergent bookmark
1091 1091 if bmctx.rev() not in anc and target in divs:
1092 1092 bookmarks.deletedivergent(repo, [target], mark)
1093 1093 return
1094 1094
1095 1095 deletefrom = [b for b in divs
1096 1096 if repo[b].rev() in anc or b == target]
1097 1097 bookmarks.deletedivergent(repo, deletefrom, mark)
1098 1098 if bookmarks.validdest(repo, bmctx, repo[target]):
1099 1099 ui.status(_("moving bookmark '%s' forward from %s\n") %
1100 1100 (mark, short(bmctx.node())))
1101 1101 return
1102 1102 raise error.Abort(_("bookmark '%s' already exists "
1103 1103 "(use -f to force)") % mark)
1104 1104 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1105 1105 and not force):
1106 1106 raise error.Abort(
1107 1107 _("a bookmark cannot have the name of an existing branch"))
1108 1108
1109 1109 if delete and rename:
1110 1110 raise error.Abort(_("--delete and --rename are incompatible"))
1111 1111 if delete and rev:
1112 1112 raise error.Abort(_("--rev is incompatible with --delete"))
1113 1113 if rename and rev:
1114 1114 raise error.Abort(_("--rev is incompatible with --rename"))
1115 1115 if not names and (delete or rev):
1116 1116 raise error.Abort(_("bookmark name required"))
1117 1117
1118 1118 if delete or rename or names or inactive:
1119 1119 wlock = lock = tr = None
1120 1120 try:
1121 1121 wlock = repo.wlock()
1122 1122 lock = repo.lock()
1123 1123 cur = repo.changectx('.').node()
1124 1124 marks = repo._bookmarks
1125 1125 if delete:
1126 1126 tr = repo.transaction('bookmark')
1127 1127 for mark in names:
1128 1128 if mark not in marks:
1129 1129 raise error.Abort(_("bookmark '%s' does not exist") %
1130 1130 mark)
1131 1131 if mark == repo._activebookmark:
1132 1132 bookmarks.deactivate(repo)
1133 1133 del marks[mark]
1134 1134
1135 1135 elif rename:
1136 1136 tr = repo.transaction('bookmark')
1137 1137 if not names:
1138 1138 raise error.Abort(_("new bookmark name required"))
1139 1139 elif len(names) > 1:
1140 1140 raise error.Abort(_("only one new bookmark name allowed"))
1141 1141 mark = checkformat(names[0])
1142 1142 if rename not in marks:
1143 1143 raise error.Abort(_("bookmark '%s' does not exist")
1144 1144 % rename)
1145 1145 checkconflict(repo, mark, cur, force)
1146 1146 marks[mark] = marks[rename]
1147 1147 if repo._activebookmark == rename and not inactive:
1148 1148 bookmarks.activate(repo, mark)
1149 1149 del marks[rename]
1150 1150 elif names:
1151 1151 tr = repo.transaction('bookmark')
1152 1152 newact = None
1153 1153 for mark in names:
1154 1154 mark = checkformat(mark)
1155 1155 if newact is None:
1156 1156 newact = mark
1157 1157 if inactive and mark == repo._activebookmark:
1158 1158 bookmarks.deactivate(repo)
1159 1159 return
1160 1160 tgt = cur
1161 1161 if rev:
1162 1162 tgt = scmutil.revsingle(repo, rev).node()
1163 1163 checkconflict(repo, mark, cur, force, tgt)
1164 1164 marks[mark] = tgt
1165 1165 if not inactive and cur == marks[newact] and not rev:
1166 1166 bookmarks.activate(repo, newact)
1167 1167 elif cur != tgt and newact == repo._activebookmark:
1168 1168 bookmarks.deactivate(repo)
1169 1169 elif inactive:
1170 1170 if len(marks) == 0:
1171 1171 ui.status(_("no bookmarks set\n"))
1172 1172 elif not repo._activebookmark:
1173 1173 ui.status(_("no active bookmark\n"))
1174 1174 else:
1175 1175 bookmarks.deactivate(repo)
1176 1176 if tr is not None:
1177 1177 marks.recordchange(tr)
1178 1178 tr.close()
1179 1179 finally:
1180 1180 lockmod.release(tr, lock, wlock)
1181 1181 else: # show bookmarks
1182 1182 fm = ui.formatter('bookmarks', opts)
1183 1183 hexfn = fm.hexfunc
1184 1184 marks = repo._bookmarks
1185 1185 if len(marks) == 0 and not fm:
1186 1186 ui.status(_("no bookmarks set\n"))
1187 1187 for bmark, n in sorted(marks.iteritems()):
1188 1188 active = repo._activebookmark
1189 1189 if bmark == active:
1190 1190 prefix, label = '*', activebookmarklabel
1191 1191 else:
1192 1192 prefix, label = ' ', ''
1193 1193
1194 1194 fm.startitem()
1195 1195 if not ui.quiet:
1196 1196 fm.plain(' %s ' % prefix, label=label)
1197 1197 fm.write('bookmark', '%s', bmark, label=label)
1198 1198 pad = " " * (25 - encoding.colwidth(bmark))
1199 1199 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1200 1200 repo.changelog.rev(n), hexfn(n), label=label)
1201 1201 fm.data(active=(bmark == active))
1202 1202 fm.plain('\n')
1203 1203 fm.end()
1204 1204
1205 1205 @command('branch',
1206 1206 [('f', 'force', None,
1207 1207 _('set branch name even if it shadows an existing branch')),
1208 1208 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1209 1209 _('[-fC] [NAME]'))
1210 1210 def branch(ui, repo, label=None, **opts):
1211 1211 """set or show the current branch name
1212 1212
1213 1213 .. note::
1214 1214
1215 1215 Branch names are permanent and global. Use :hg:`bookmark` to create a
1216 1216 light-weight bookmark instead. See :hg:`help glossary` for more
1217 1217 information about named branches and bookmarks.
1218 1218
1219 1219 With no argument, show the current branch name. With one argument,
1220 1220 set the working directory branch name (the branch will not exist
1221 1221 in the repository until the next commit). Standard practice
1222 1222 recommends that primary development take place on the 'default'
1223 1223 branch.
1224 1224
1225 1225 Unless -f/--force is specified, branch will not let you set a
1226 1226 branch name that already exists.
1227 1227
1228 1228 Use -C/--clean to reset the working directory branch to that of
1229 1229 the parent of the working directory, negating a previous branch
1230 1230 change.
1231 1231
1232 1232 Use the command :hg:`update` to switch to an existing branch. Use
1233 1233 :hg:`commit --close-branch` to mark this branch head as closed.
1234 1234 When all heads of a branch are closed, the branch will be
1235 1235 considered closed.
1236 1236
1237 1237 Returns 0 on success.
1238 1238 """
1239 1239 if label:
1240 1240 label = label.strip()
1241 1241
1242 1242 if not opts.get('clean') and not label:
1243 1243 ui.write("%s\n" % repo.dirstate.branch())
1244 1244 return
1245 1245
1246 1246 with repo.wlock():
1247 1247 if opts.get('clean'):
1248 1248 label = repo[None].p1().branch()
1249 1249 repo.dirstate.setbranch(label)
1250 1250 ui.status(_('reset working directory to branch %s\n') % label)
1251 1251 elif label:
1252 1252 if not opts.get('force') and label in repo.branchmap():
1253 1253 if label not in [p.branch() for p in repo[None].parents()]:
1254 1254 raise error.Abort(_('a branch of the same name already'
1255 1255 ' exists'),
1256 1256 # i18n: "it" refers to an existing branch
1257 1257 hint=_("use 'hg update' to switch to it"))
1258 1258 scmutil.checknewlabel(repo, label, 'branch')
1259 1259 repo.dirstate.setbranch(label)
1260 1260 ui.status(_('marked working directory as branch %s\n') % label)
1261 1261
1262 1262 # find any open named branches aside from default
1263 1263 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1264 1264 if n != "default" and not c]
1265 1265 if not others:
1266 1266 ui.status(_('(branches are permanent and global, '
1267 1267 'did you want a bookmark?)\n'))
1268 1268
1269 1269 @command('branches',
1270 1270 [('a', 'active', False,
1271 1271 _('show only branches that have unmerged heads (DEPRECATED)')),
1272 1272 ('c', 'closed', False, _('show normal and closed branches')),
1273 1273 ] + formatteropts,
1274 1274 _('[-c]'))
1275 1275 def branches(ui, repo, active=False, closed=False, **opts):
1276 1276 """list repository named branches
1277 1277
1278 1278 List the repository's named branches, indicating which ones are
1279 1279 inactive. If -c/--closed is specified, also list branches which have
1280 1280 been marked closed (see :hg:`commit --close-branch`).
1281 1281
1282 1282 Use the command :hg:`update` to switch to an existing branch.
1283 1283
1284 1284 Returns 0.
1285 1285 """
1286 1286
1287 1287 fm = ui.formatter('branches', opts)
1288 1288 hexfunc = fm.hexfunc
1289 1289
1290 1290 allheads = set(repo.heads())
1291 1291 branches = []
1292 1292 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1293 1293 isactive = not isclosed and bool(set(heads) & allheads)
1294 1294 branches.append((tag, repo[tip], isactive, not isclosed))
1295 1295 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1296 1296 reverse=True)
1297 1297
1298 1298 for tag, ctx, isactive, isopen in branches:
1299 1299 if active and not isactive:
1300 1300 continue
1301 1301 if isactive:
1302 1302 label = 'branches.active'
1303 1303 notice = ''
1304 1304 elif not isopen:
1305 1305 if not closed:
1306 1306 continue
1307 1307 label = 'branches.closed'
1308 1308 notice = _(' (closed)')
1309 1309 else:
1310 1310 label = 'branches.inactive'
1311 1311 notice = _(' (inactive)')
1312 1312 current = (tag == repo.dirstate.branch())
1313 1313 if current:
1314 1314 label = 'branches.current'
1315 1315
1316 1316 fm.startitem()
1317 1317 fm.write('branch', '%s', tag, label=label)
1318 1318 rev = ctx.rev()
1319 1319 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1320 1320 fmt = ' ' * padsize + ' %d:%s'
1321 1321 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1322 1322 label='log.changeset changeset.%s' % ctx.phasestr())
1323 1323 fm.data(active=isactive, closed=not isopen, current=current)
1324 1324 if not ui.quiet:
1325 1325 fm.plain(notice)
1326 1326 fm.plain('\n')
1327 1327 fm.end()
1328 1328
1329 1329 @command('bundle',
1330 1330 [('f', 'force', None, _('run even when the destination is unrelated')),
1331 1331 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1332 1332 _('REV')),
1333 1333 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1334 1334 _('BRANCH')),
1335 1335 ('', 'base', [],
1336 1336 _('a base changeset assumed to be available at the destination'),
1337 1337 _('REV')),
1338 1338 ('a', 'all', None, _('bundle all changesets in the repository')),
1339 1339 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1340 1340 ] + remoteopts,
1341 1341 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1342 1342 def bundle(ui, repo, fname, dest=None, **opts):
1343 1343 """create a changegroup file
1344 1344
1345 1345 Generate a changegroup file collecting changesets to be added
1346 1346 to a repository.
1347 1347
1348 1348 To create a bundle containing all changesets, use -a/--all
1349 1349 (or --base null). Otherwise, hg assumes the destination will have
1350 1350 all the nodes you specify with --base parameters. Otherwise, hg
1351 1351 will assume the repository has all the nodes in destination, or
1352 1352 default-push/default if no destination is specified.
1353 1353
1354 1354 You can change bundle format with the -t/--type option. You can
1355 1355 specify a compression, a bundle version or both using a dash
1356 1356 (comp-version). The available compression methods are: none, bzip2,
1357 1357 and gzip (by default, bundles are compressed using bzip2). The
1358 1358 available formats are: v1, v2 (default to most suitable).
1359 1359
1360 1360 The bundle file can then be transferred using conventional means
1361 1361 and applied to another repository with the unbundle or pull
1362 1362 command. This is useful when direct push and pull are not
1363 1363 available or when exporting an entire repository is undesirable.
1364 1364
1365 1365 Applying bundles preserves all changeset contents including
1366 1366 permissions, copy/rename information, and revision history.
1367 1367
1368 1368 Returns 0 on success, 1 if no changes found.
1369 1369 """
1370 1370 revs = None
1371 1371 if 'rev' in opts:
1372 1372 revstrings = opts['rev']
1373 1373 revs = scmutil.revrange(repo, revstrings)
1374 1374 if revstrings and not revs:
1375 1375 raise error.Abort(_('no commits to bundle'))
1376 1376
1377 1377 bundletype = opts.get('type', 'bzip2').lower()
1378 1378 try:
1379 1379 bcompression, cgversion, params = exchange.parsebundlespec(
1380 1380 repo, bundletype, strict=False)
1381 1381 except error.UnsupportedBundleSpecification as e:
1382 1382 raise error.Abort(str(e),
1383 1383 hint=_('see "hg help bundle" for supported '
1384 1384 'values for --type'))
1385 1385
1386 1386 # Packed bundles are a pseudo bundle format for now.
1387 1387 if cgversion == 's1':
1388 1388 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1389 1389 hint=_('use "hg debugcreatestreamclonebundle"'))
1390 1390
1391 1391 if opts.get('all'):
1392 1392 if dest:
1393 1393 raise error.Abort(_("--all is incompatible with specifying "
1394 1394 "a destination"))
1395 1395 if opts.get('base'):
1396 1396 ui.warn(_("ignoring --base because --all was specified\n"))
1397 1397 base = ['null']
1398 1398 else:
1399 1399 base = scmutil.revrange(repo, opts.get('base'))
1400 1400 # TODO: get desired bundlecaps from command line.
1401 1401 bundlecaps = None
1402 1402 if cgversion not in changegroup.supportedoutgoingversions(repo):
1403 1403 raise error.Abort(_("repository does not support bundle version %s") %
1404 1404 cgversion)
1405 1405
1406 1406 if base:
1407 1407 if dest:
1408 1408 raise error.Abort(_("--base is incompatible with specifying "
1409 1409 "a destination"))
1410 1410 common = [repo.lookup(rev) for rev in base]
1411 1411 heads = revs and map(repo.lookup, revs) or revs
1412 1412 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1413 1413 common=common, bundlecaps=bundlecaps,
1414 1414 version=cgversion)
1415 1415 outgoing = None
1416 1416 else:
1417 1417 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1418 1418 dest, branches = hg.parseurl(dest, opts.get('branch'))
1419 1419 other = hg.peer(repo, opts, dest)
1420 1420 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1421 1421 heads = revs and map(repo.lookup, revs) or revs
1422 1422 outgoing = discovery.findcommonoutgoing(repo, other,
1423 1423 onlyheads=heads,
1424 1424 force=opts.get('force'),
1425 1425 portable=True)
1426 1426 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1427 1427 bundlecaps, version=cgversion)
1428 1428 if not cg:
1429 1429 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1430 1430 return 1
1431 1431
1432 1432 if cgversion == '01': #bundle1
1433 1433 if bcompression is None:
1434 1434 bcompression = 'UN'
1435 1435 bversion = 'HG10' + bcompression
1436 1436 bcompression = None
1437 1437 else:
1438 1438 assert cgversion == '02'
1439 1439 bversion = 'HG20'
1440 1440
1441 1441 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1442 1442
1443 1443 @command('cat',
1444 1444 [('o', 'output', '',
1445 1445 _('print output to file with formatted name'), _('FORMAT')),
1446 1446 ('r', 'rev', '', _('print the given revision'), _('REV')),
1447 1447 ('', 'decode', None, _('apply any matching decode filter')),
1448 1448 ] + walkopts,
1449 1449 _('[OPTION]... FILE...'),
1450 1450 inferrepo=True)
1451 1451 def cat(ui, repo, file1, *pats, **opts):
1452 1452 """output the current or given revision of files
1453 1453
1454 1454 Print the specified files as they were at the given revision. If
1455 1455 no revision is given, the parent of the working directory is used.
1456 1456
1457 1457 Output may be to a file, in which case the name of the file is
1458 1458 given using a format string. The formatting rules as follows:
1459 1459
1460 1460 :``%%``: literal "%" character
1461 1461 :``%s``: basename of file being printed
1462 1462 :``%d``: dirname of file being printed, or '.' if in repository root
1463 1463 :``%p``: root-relative path name of file being printed
1464 1464 :``%H``: changeset hash (40 hexadecimal digits)
1465 1465 :``%R``: changeset revision number
1466 1466 :``%h``: short-form changeset hash (12 hexadecimal digits)
1467 1467 :``%r``: zero-padded changeset revision number
1468 1468 :``%b``: basename of the exporting repository
1469 1469
1470 1470 Returns 0 on success.
1471 1471 """
1472 1472 ctx = scmutil.revsingle(repo, opts.get('rev'))
1473 1473 m = scmutil.match(ctx, (file1,) + pats, opts)
1474 1474
1475 1475 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1476 1476
1477 1477 @command('^clone',
1478 1478 [('U', 'noupdate', None, _('the clone will include an empty working '
1479 1479 'directory (only a repository)')),
1480 1480 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1481 1481 _('REV')),
1482 1482 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1483 1483 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1484 1484 ('', 'pull', None, _('use pull protocol to copy metadata')),
1485 1485 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1486 1486 ] + remoteopts,
1487 1487 _('[OPTION]... SOURCE [DEST]'),
1488 1488 norepo=True)
1489 1489 def clone(ui, source, dest=None, **opts):
1490 1490 """make a copy of an existing repository
1491 1491
1492 1492 Create a copy of an existing repository in a new directory.
1493 1493
1494 1494 If no destination directory name is specified, it defaults to the
1495 1495 basename of the source.
1496 1496
1497 1497 The location of the source is added to the new repository's
1498 1498 ``.hg/hgrc`` file, as the default to be used for future pulls.
1499 1499
1500 1500 Only local paths and ``ssh://`` URLs are supported as
1501 1501 destinations. For ``ssh://`` destinations, no working directory or
1502 1502 ``.hg/hgrc`` will be created on the remote side.
1503 1503
1504 1504 If the source repository has a bookmark called '@' set, that
1505 1505 revision will be checked out in the new repository by default.
1506 1506
1507 1507 To check out a particular version, use -u/--update, or
1508 1508 -U/--noupdate to create a clone with no working directory.
1509 1509
1510 1510 To pull only a subset of changesets, specify one or more revisions
1511 1511 identifiers with -r/--rev or branches with -b/--branch. The
1512 1512 resulting clone will contain only the specified changesets and
1513 1513 their ancestors. These options (or 'clone src#rev dest') imply
1514 1514 --pull, even for local source repositories.
1515 1515
1516 1516 .. note::
1517 1517
1518 1518 Specifying a tag will include the tagged changeset but not the
1519 1519 changeset containing the tag.
1520 1520
1521 1521 .. container:: verbose
1522 1522
1523 1523 For efficiency, hardlinks are used for cloning whenever the
1524 1524 source and destination are on the same filesystem (note this
1525 1525 applies only to the repository data, not to the working
1526 1526 directory). Some filesystems, such as AFS, implement hardlinking
1527 1527 incorrectly, but do not report errors. In these cases, use the
1528 1528 --pull option to avoid hardlinking.
1529 1529
1530 1530 In some cases, you can clone repositories and the working
1531 1531 directory using full hardlinks with ::
1532 1532
1533 1533 $ cp -al REPO REPOCLONE
1534 1534
1535 1535 This is the fastest way to clone, but it is not always safe. The
1536 1536 operation is not atomic (making sure REPO is not modified during
1537 1537 the operation is up to you) and you have to make sure your
1538 1538 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1539 1539 so). Also, this is not compatible with certain extensions that
1540 1540 place their metadata under the .hg directory, such as mq.
1541 1541
1542 1542 Mercurial will update the working directory to the first applicable
1543 1543 revision from this list:
1544 1544
1545 1545 a) null if -U or the source repository has no changesets
1546 1546 b) if -u . and the source repository is local, the first parent of
1547 1547 the source repository's working directory
1548 1548 c) the changeset specified with -u (if a branch name, this means the
1549 1549 latest head of that branch)
1550 1550 d) the changeset specified with -r
1551 1551 e) the tipmost head specified with -b
1552 1552 f) the tipmost head specified with the url#branch source syntax
1553 1553 g) the revision marked with the '@' bookmark, if present
1554 1554 h) the tipmost head of the default branch
1555 1555 i) tip
1556 1556
1557 1557 When cloning from servers that support it, Mercurial may fetch
1558 1558 pre-generated data from a server-advertised URL. When this is done,
1559 1559 hooks operating on incoming changesets and changegroups may fire twice,
1560 1560 once for the bundle fetched from the URL and another for any additional
1561 1561 data not fetched from this URL. In addition, if an error occurs, the
1562 1562 repository may be rolled back to a partial clone. This behavior may
1563 1563 change in future releases. See :hg:`help -e clonebundles` for more.
1564 1564
1565 1565 Examples:
1566 1566
1567 1567 - clone a remote repository to a new directory named hg/::
1568 1568
1569 1569 hg clone http://selenic.com/hg
1570 1570
1571 1571 - create a lightweight local clone::
1572 1572
1573 1573 hg clone project/ project-feature/
1574 1574
1575 1575 - clone from an absolute path on an ssh server (note double-slash)::
1576 1576
1577 1577 hg clone ssh://user@server//home/projects/alpha/
1578 1578
1579 1579 - do a high-speed clone over a LAN while checking out a
1580 1580 specified version::
1581 1581
1582 1582 hg clone --uncompressed http://server/repo -u 1.5
1583 1583
1584 1584 - create a repository without changesets after a particular revision::
1585 1585
1586 1586 hg clone -r 04e544 experimental/ good/
1587 1587
1588 1588 - clone (and track) a particular named branch::
1589 1589
1590 1590 hg clone http://selenic.com/hg#stable
1591 1591
1592 1592 See :hg:`help urls` for details on specifying URLs.
1593 1593
1594 1594 Returns 0 on success.
1595 1595 """
1596 1596 if opts.get('noupdate') and opts.get('updaterev'):
1597 1597 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1598 1598
1599 1599 r = hg.clone(ui, opts, source, dest,
1600 1600 pull=opts.get('pull'),
1601 1601 stream=opts.get('uncompressed'),
1602 1602 rev=opts.get('rev'),
1603 1603 update=opts.get('updaterev') or not opts.get('noupdate'),
1604 1604 branch=opts.get('branch'),
1605 1605 shareopts=opts.get('shareopts'))
1606 1606
1607 1607 return r is None
1608 1608
1609 1609 @command('^commit|ci',
1610 1610 [('A', 'addremove', None,
1611 1611 _('mark new/missing files as added/removed before committing')),
1612 1612 ('', 'close-branch', None,
1613 1613 _('mark a branch head as closed')),
1614 1614 ('', 'amend', None, _('amend the parent of the working directory')),
1615 1615 ('s', 'secret', None, _('use the secret phase for committing')),
1616 1616 ('e', 'edit', None, _('invoke editor on commit messages')),
1617 1617 ('i', 'interactive', None, _('use interactive mode')),
1618 1618 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1619 1619 _('[OPTION]... [FILE]...'),
1620 1620 inferrepo=True)
1621 1621 def commit(ui, repo, *pats, **opts):
1622 1622 """commit the specified files or all outstanding changes
1623 1623
1624 1624 Commit changes to the given files into the repository. Unlike a
1625 1625 centralized SCM, this operation is a local operation. See
1626 1626 :hg:`push` for a way to actively distribute your changes.
1627 1627
1628 1628 If a list of files is omitted, all changes reported by :hg:`status`
1629 1629 will be committed.
1630 1630
1631 1631 If you are committing the result of a merge, do not provide any
1632 1632 filenames or -I/-X filters.
1633 1633
1634 1634 If no commit message is specified, Mercurial starts your
1635 1635 configured editor where you can enter a message. In case your
1636 1636 commit fails, you will find a backup of your message in
1637 1637 ``.hg/last-message.txt``.
1638 1638
1639 1639 The --close-branch flag can be used to mark the current branch
1640 1640 head closed. When all heads of a branch are closed, the branch
1641 1641 will be considered closed and no longer listed.
1642 1642
1643 1643 The --amend flag can be used to amend the parent of the
1644 1644 working directory with a new commit that contains the changes
1645 1645 in the parent in addition to those currently reported by :hg:`status`,
1646 1646 if there are any. The old commit is stored in a backup bundle in
1647 1647 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1648 1648 on how to restore it).
1649 1649
1650 1650 Message, user and date are taken from the amended commit unless
1651 1651 specified. When a message isn't specified on the command line,
1652 1652 the editor will open with the message of the amended commit.
1653 1653
1654 1654 It is not possible to amend public changesets (see :hg:`help phases`)
1655 1655 or changesets that have children.
1656 1656
1657 1657 See :hg:`help dates` for a list of formats valid for -d/--date.
1658 1658
1659 1659 Returns 0 on success, 1 if nothing changed.
1660 1660
1661 1661 .. container:: verbose
1662 1662
1663 1663 Examples:
1664 1664
1665 1665 - commit all files ending in .py::
1666 1666
1667 1667 hg commit --include "set:**.py"
1668 1668
1669 1669 - commit all non-binary files::
1670 1670
1671 1671 hg commit --exclude "set:binary()"
1672 1672
1673 1673 - amend the current commit and set the date to now::
1674 1674
1675 1675 hg commit --amend --date now
1676 1676 """
1677 1677 wlock = lock = None
1678 1678 try:
1679 1679 wlock = repo.wlock()
1680 1680 lock = repo.lock()
1681 1681 return _docommit(ui, repo, *pats, **opts)
1682 1682 finally:
1683 1683 release(lock, wlock)
1684 1684
1685 1685 def _docommit(ui, repo, *pats, **opts):
1686 1686 if opts.get('interactive'):
1687 1687 opts.pop('interactive')
1688 1688 cmdutil.dorecord(ui, repo, commit, None, False,
1689 1689 cmdutil.recordfilter, *pats, **opts)
1690 1690 return
1691 1691
1692 1692 if opts.get('subrepos'):
1693 1693 if opts.get('amend'):
1694 1694 raise error.Abort(_('cannot amend with --subrepos'))
1695 1695 # Let --subrepos on the command line override config setting.
1696 1696 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1697 1697
1698 1698 cmdutil.checkunfinished(repo, commit=True)
1699 1699
1700 1700 branch = repo[None].branch()
1701 1701 bheads = repo.branchheads(branch)
1702 1702
1703 1703 extra = {}
1704 1704 if opts.get('close_branch'):
1705 1705 extra['close'] = 1
1706 1706
1707 1707 if not bheads:
1708 1708 raise error.Abort(_('can only close branch heads'))
1709 1709 elif opts.get('amend'):
1710 1710 if repo[None].parents()[0].p1().branch() != branch and \
1711 1711 repo[None].parents()[0].p2().branch() != branch:
1712 1712 raise error.Abort(_('can only close branch heads'))
1713 1713
1714 1714 if opts.get('amend'):
1715 1715 if ui.configbool('ui', 'commitsubrepos'):
1716 1716 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1717 1717
1718 1718 old = repo['.']
1719 1719 if not old.mutable():
1720 1720 raise error.Abort(_('cannot amend public changesets'))
1721 1721 if len(repo[None].parents()) > 1:
1722 1722 raise error.Abort(_('cannot amend while merging'))
1723 1723 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1724 1724 if not allowunstable and old.children():
1725 1725 raise error.Abort(_('cannot amend changeset with children'))
1726 1726
1727 1727 # Currently histedit gets confused if an amend happens while histedit
1728 1728 # is in progress. Since we have a checkunfinished command, we are
1729 1729 # temporarily honoring it.
1730 1730 #
1731 1731 # Note: eventually this guard will be removed. Please do not expect
1732 1732 # this behavior to remain.
1733 1733 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1734 1734 cmdutil.checkunfinished(repo)
1735 1735
1736 1736 # commitfunc is used only for temporary amend commit by cmdutil.amend
1737 1737 def commitfunc(ui, repo, message, match, opts):
1738 1738 return repo.commit(message,
1739 1739 opts.get('user') or old.user(),
1740 1740 opts.get('date') or old.date(),
1741 1741 match,
1742 1742 extra=extra)
1743 1743
1744 1744 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1745 1745 if node == old.node():
1746 1746 ui.status(_("nothing changed\n"))
1747 1747 return 1
1748 1748 else:
1749 1749 def commitfunc(ui, repo, message, match, opts):
1750 1750 backup = ui.backupconfig('phases', 'new-commit')
1751 1751 baseui = repo.baseui
1752 1752 basebackup = baseui.backupconfig('phases', 'new-commit')
1753 1753 try:
1754 1754 if opts.get('secret'):
1755 1755 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1756 1756 # Propagate to subrepos
1757 1757 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1758 1758
1759 1759 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1760 1760 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1761 1761 return repo.commit(message, opts.get('user'), opts.get('date'),
1762 1762 match,
1763 1763 editor=editor,
1764 1764 extra=extra)
1765 1765 finally:
1766 1766 ui.restoreconfig(backup)
1767 1767 repo.baseui.restoreconfig(basebackup)
1768 1768
1769 1769
1770 1770 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1771 1771
1772 1772 if not node:
1773 1773 stat = cmdutil.postcommitstatus(repo, pats, opts)
1774 1774 if stat[3]:
1775 1775 ui.status(_("nothing changed (%d missing files, see "
1776 1776 "'hg status')\n") % len(stat[3]))
1777 1777 else:
1778 1778 ui.status(_("nothing changed\n"))
1779 1779 return 1
1780 1780
1781 1781 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1782 1782
1783 1783 @command('config|showconfig|debugconfig',
1784 1784 [('u', 'untrusted', None, _('show untrusted configuration options')),
1785 1785 ('e', 'edit', None, _('edit user config')),
1786 1786 ('l', 'local', None, _('edit repository config')),
1787 1787 ('g', 'global', None, _('edit global config'))],
1788 1788 _('[-u] [NAME]...'),
1789 1789 optionalrepo=True)
1790 1790 def config(ui, repo, *values, **opts):
1791 1791 """show combined config settings from all hgrc files
1792 1792
1793 1793 With no arguments, print names and values of all config items.
1794 1794
1795 1795 With one argument of the form section.name, print just the value
1796 1796 of that config item.
1797 1797
1798 1798 With multiple arguments, print names and values of all config
1799 1799 items with matching section names.
1800 1800
1801 1801 With --edit, start an editor on the user-level config file. With
1802 1802 --global, edit the system-wide config file. With --local, edit the
1803 1803 repository-level config file.
1804 1804
1805 1805 With --debug, the source (filename and line number) is printed
1806 1806 for each config item.
1807 1807
1808 1808 See :hg:`help config` for more information about config files.
1809 1809
1810 1810 Returns 0 on success, 1 if NAME does not exist.
1811 1811
1812 1812 """
1813 1813
1814 1814 if opts.get('edit') or opts.get('local') or opts.get('global'):
1815 1815 if opts.get('local') and opts.get('global'):
1816 1816 raise error.Abort(_("can't use --local and --global together"))
1817 1817
1818 1818 if opts.get('local'):
1819 1819 if not repo:
1820 1820 raise error.Abort(_("can't use --local outside a repository"))
1821 1821 paths = [repo.join('hgrc')]
1822 1822 elif opts.get('global'):
1823 1823 paths = scmutil.systemrcpath()
1824 1824 else:
1825 1825 paths = scmutil.userrcpath()
1826 1826
1827 1827 for f in paths:
1828 1828 if os.path.exists(f):
1829 1829 break
1830 1830 else:
1831 1831 if opts.get('global'):
1832 1832 samplehgrc = uimod.samplehgrcs['global']
1833 1833 elif opts.get('local'):
1834 1834 samplehgrc = uimod.samplehgrcs['local']
1835 1835 else:
1836 1836 samplehgrc = uimod.samplehgrcs['user']
1837 1837
1838 1838 f = paths[0]
1839 1839 fp = open(f, "w")
1840 1840 fp.write(samplehgrc)
1841 1841 fp.close()
1842 1842
1843 1843 editor = ui.geteditor()
1844 1844 ui.system("%s \"%s\"" % (editor, f),
1845 1845 onerr=error.Abort, errprefix=_("edit failed"))
1846 1846 return
1847 1847
1848 1848 for f in scmutil.rcpath():
1849 1849 ui.debug('read config from: %s\n' % f)
1850 1850 untrusted = bool(opts.get('untrusted'))
1851 1851 if values:
1852 1852 sections = [v for v in values if '.' not in v]
1853 1853 items = [v for v in values if '.' in v]
1854 1854 if len(items) > 1 or items and sections:
1855 1855 raise error.Abort(_('only one config item permitted'))
1856 1856 matched = False
1857 1857 for section, name, value in ui.walkconfig(untrusted=untrusted):
1858 1858 value = str(value).replace('\n', '\\n')
1859 1859 sectname = section + '.' + name
1860 1860 if values:
1861 1861 for v in values:
1862 1862 if v == section:
1863 1863 ui.debug('%s: ' %
1864 1864 ui.configsource(section, name, untrusted))
1865 1865 ui.write('%s=%s\n' % (sectname, value))
1866 1866 matched = True
1867 1867 elif v == sectname:
1868 1868 ui.debug('%s: ' %
1869 1869 ui.configsource(section, name, untrusted))
1870 1870 ui.write(value, '\n')
1871 1871 matched = True
1872 1872 else:
1873 1873 ui.debug('%s: ' %
1874 1874 ui.configsource(section, name, untrusted))
1875 1875 ui.write('%s=%s\n' % (sectname, value))
1876 1876 matched = True
1877 1877 if matched:
1878 1878 return 0
1879 1879 return 1
1880 1880
1881 1881 @command('copy|cp',
1882 1882 [('A', 'after', None, _('record a copy that has already occurred')),
1883 1883 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1884 1884 ] + walkopts + dryrunopts,
1885 1885 _('[OPTION]... [SOURCE]... DEST'))
1886 1886 def copy(ui, repo, *pats, **opts):
1887 1887 """mark files as copied for the next commit
1888 1888
1889 1889 Mark dest as having copies of source files. If dest is a
1890 1890 directory, copies are put in that directory. If dest is a file,
1891 1891 the source must be a single file.
1892 1892
1893 1893 By default, this command copies the contents of files as they
1894 1894 exist in the working directory. If invoked with -A/--after, the
1895 1895 operation is recorded, but no copying is performed.
1896 1896
1897 1897 This command takes effect with the next commit. To undo a copy
1898 1898 before that, see :hg:`revert`.
1899 1899
1900 1900 Returns 0 on success, 1 if errors are encountered.
1901 1901 """
1902 1902 with repo.wlock(False):
1903 1903 return cmdutil.copy(ui, repo, pats, opts)
1904 1904
1905 1905 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1906 1906 def debugancestor(ui, repo, *args):
1907 1907 """find the ancestor revision of two revisions in a given index"""
1908 1908 if len(args) == 3:
1909 1909 index, rev1, rev2 = args
1910 1910 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1911 1911 lookup = r.lookup
1912 1912 elif len(args) == 2:
1913 1913 if not repo:
1914 1914 raise error.Abort(_("there is no Mercurial repository here "
1915 1915 "(.hg not found)"))
1916 1916 rev1, rev2 = args
1917 1917 r = repo.changelog
1918 1918 lookup = repo.lookup
1919 1919 else:
1920 1920 raise error.Abort(_('either two or three arguments required'))
1921 1921 a = r.ancestor(lookup(rev1), lookup(rev2))
1922 1922 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1923 1923
1924 1924 @command('debugbuilddag',
1925 1925 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1926 1926 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1927 1927 ('n', 'new-file', None, _('add new file at each rev'))],
1928 1928 _('[OPTION]... [TEXT]'))
1929 1929 def debugbuilddag(ui, repo, text=None,
1930 1930 mergeable_file=False,
1931 1931 overwritten_file=False,
1932 1932 new_file=False):
1933 1933 """builds a repo with a given DAG from scratch in the current empty repo
1934 1934
1935 1935 The description of the DAG is read from stdin if not given on the
1936 1936 command line.
1937 1937
1938 1938 Elements:
1939 1939
1940 1940 - "+n" is a linear run of n nodes based on the current default parent
1941 1941 - "." is a single node based on the current default parent
1942 1942 - "$" resets the default parent to null (implied at the start);
1943 1943 otherwise the default parent is always the last node created
1944 1944 - "<p" sets the default parent to the backref p
1945 1945 - "*p" is a fork at parent p, which is a backref
1946 1946 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1947 1947 - "/p2" is a merge of the preceding node and p2
1948 1948 - ":tag" defines a local tag for the preceding node
1949 1949 - "@branch" sets the named branch for subsequent nodes
1950 1950 - "#...\\n" is a comment up to the end of the line
1951 1951
1952 1952 Whitespace between the above elements is ignored.
1953 1953
1954 1954 A backref is either
1955 1955
1956 1956 - a number n, which references the node curr-n, where curr is the current
1957 1957 node, or
1958 1958 - the name of a local tag you placed earlier using ":tag", or
1959 1959 - empty to denote the default parent.
1960 1960
1961 1961 All string valued-elements are either strictly alphanumeric, or must
1962 1962 be enclosed in double quotes ("..."), with "\\" as escape character.
1963 1963 """
1964 1964
1965 1965 if text is None:
1966 1966 ui.status(_("reading DAG from stdin\n"))
1967 1967 text = ui.fin.read()
1968 1968
1969 1969 cl = repo.changelog
1970 1970 if len(cl) > 0:
1971 1971 raise error.Abort(_('repository is not empty'))
1972 1972
1973 1973 # determine number of revs in DAG
1974 1974 total = 0
1975 1975 for type, data in dagparser.parsedag(text):
1976 1976 if type == 'n':
1977 1977 total += 1
1978 1978
1979 1979 if mergeable_file:
1980 1980 linesperrev = 2
1981 1981 # make a file with k lines per rev
1982 1982 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1983 1983 initialmergedlines.append("")
1984 1984
1985 1985 tags = []
1986 1986
1987 1987 lock = tr = None
1988 1988 try:
1989 1989 lock = repo.lock()
1990 1990 tr = repo.transaction("builddag")
1991 1991
1992 1992 at = -1
1993 1993 atbranch = 'default'
1994 1994 nodeids = []
1995 1995 id = 0
1996 1996 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1997 1997 for type, data in dagparser.parsedag(text):
1998 1998 if type == 'n':
1999 1999 ui.note(('node %s\n' % str(data)))
2000 2000 id, ps = data
2001 2001
2002 2002 files = []
2003 2003 fctxs = {}
2004 2004
2005 2005 p2 = None
2006 2006 if mergeable_file:
2007 2007 fn = "mf"
2008 2008 p1 = repo[ps[0]]
2009 2009 if len(ps) > 1:
2010 2010 p2 = repo[ps[1]]
2011 2011 pa = p1.ancestor(p2)
2012 2012 base, local, other = [x[fn].data() for x in (pa, p1,
2013 2013 p2)]
2014 2014 m3 = simplemerge.Merge3Text(base, local, other)
2015 2015 ml = [l.strip() for l in m3.merge_lines()]
2016 2016 ml.append("")
2017 2017 elif at > 0:
2018 2018 ml = p1[fn].data().split("\n")
2019 2019 else:
2020 2020 ml = initialmergedlines
2021 2021 ml[id * linesperrev] += " r%i" % id
2022 2022 mergedtext = "\n".join(ml)
2023 2023 files.append(fn)
2024 2024 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2025 2025
2026 2026 if overwritten_file:
2027 2027 fn = "of"
2028 2028 files.append(fn)
2029 2029 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2030 2030
2031 2031 if new_file:
2032 2032 fn = "nf%i" % id
2033 2033 files.append(fn)
2034 2034 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2035 2035 if len(ps) > 1:
2036 2036 if not p2:
2037 2037 p2 = repo[ps[1]]
2038 2038 for fn in p2:
2039 2039 if fn.startswith("nf"):
2040 2040 files.append(fn)
2041 2041 fctxs[fn] = p2[fn]
2042 2042
2043 2043 def fctxfn(repo, cx, path):
2044 2044 return fctxs.get(path)
2045 2045
2046 2046 if len(ps) == 0 or ps[0] < 0:
2047 2047 pars = [None, None]
2048 2048 elif len(ps) == 1:
2049 2049 pars = [nodeids[ps[0]], None]
2050 2050 else:
2051 2051 pars = [nodeids[p] for p in ps]
2052 2052 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2053 2053 date=(id, 0),
2054 2054 user="debugbuilddag",
2055 2055 extra={'branch': atbranch})
2056 2056 nodeid = repo.commitctx(cx)
2057 2057 nodeids.append(nodeid)
2058 2058 at = id
2059 2059 elif type == 'l':
2060 2060 id, name = data
2061 2061 ui.note(('tag %s\n' % name))
2062 2062 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2063 2063 elif type == 'a':
2064 2064 ui.note(('branch %s\n' % data))
2065 2065 atbranch = data
2066 2066 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2067 2067 tr.close()
2068 2068
2069 2069 if tags:
2070 2070 repo.vfs.write("localtags", "".join(tags))
2071 2071 finally:
2072 2072 ui.progress(_('building'), None)
2073 2073 release(tr, lock)
2074 2074
2075 2075 @command('debugbundle',
2076 2076 [('a', 'all', None, _('show all details')),
2077 2077 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2078 2078 _('FILE'),
2079 2079 norepo=True)
2080 2080 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2081 2081 """lists the contents of a bundle"""
2082 2082 with hg.openpath(ui, bundlepath) as f:
2083 2083 if spec:
2084 2084 spec = exchange.getbundlespec(ui, f)
2085 2085 ui.write('%s\n' % spec)
2086 2086 return
2087 2087
2088 2088 gen = exchange.readbundle(ui, f, bundlepath)
2089 2089 if isinstance(gen, bundle2.unbundle20):
2090 2090 return _debugbundle2(ui, gen, all=all, **opts)
2091 2091 if all:
2092 2092 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2093 2093
2094 2094 def showchunks(named):
2095 2095 ui.write("\n%s\n" % named)
2096 2096 chain = None
2097 2097 while True:
2098 2098 chunkdata = gen.deltachunk(chain)
2099 2099 if not chunkdata:
2100 2100 break
2101 2101 node = chunkdata['node']
2102 2102 p1 = chunkdata['p1']
2103 2103 p2 = chunkdata['p2']
2104 2104 cs = chunkdata['cs']
2105 2105 deltabase = chunkdata['deltabase']
2106 2106 delta = chunkdata['delta']
2107 2107 ui.write("%s %s %s %s %s %s\n" %
2108 2108 (hex(node), hex(p1), hex(p2),
2109 2109 hex(cs), hex(deltabase), len(delta)))
2110 2110 chain = node
2111 2111
2112 2112 chunkdata = gen.changelogheader()
2113 2113 showchunks("changelog")
2114 2114 chunkdata = gen.manifestheader()
2115 2115 showchunks("manifest")
2116 2116 while True:
2117 2117 chunkdata = gen.filelogheader()
2118 2118 if not chunkdata:
2119 2119 break
2120 2120 fname = chunkdata['filename']
2121 2121 showchunks(fname)
2122 2122 else:
2123 2123 if isinstance(gen, bundle2.unbundle20):
2124 2124 raise error.Abort(_('use debugbundle2 for this file'))
2125 2125 chunkdata = gen.changelogheader()
2126 2126 chain = None
2127 2127 while True:
2128 2128 chunkdata = gen.deltachunk(chain)
2129 2129 if not chunkdata:
2130 2130 break
2131 2131 node = chunkdata['node']
2132 2132 ui.write("%s\n" % hex(node))
2133 2133 chain = node
2134 2134
2135 2135 def _debugbundle2(ui, gen, **opts):
2136 2136 """lists the contents of a bundle2"""
2137 2137 if not isinstance(gen, bundle2.unbundle20):
2138 2138 raise error.Abort(_('not a bundle2 file'))
2139 2139 ui.write(('Stream params: %s\n' % repr(gen.params)))
2140 2140 for part in gen.iterparts():
2141 2141 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2142 2142 if part.type == 'changegroup':
2143 2143 version = part.params.get('version', '01')
2144 2144 cg = changegroup.getunbundler(version, part, 'UN')
2145 2145 chunkdata = cg.changelogheader()
2146 2146 chain = None
2147 2147 while True:
2148 2148 chunkdata = cg.deltachunk(chain)
2149 2149 if not chunkdata:
2150 2150 break
2151 2151 node = chunkdata['node']
2152 2152 ui.write(" %s\n" % hex(node))
2153 2153 chain = node
2154 2154
2155 2155 @command('debugcreatestreamclonebundle', [], 'FILE')
2156 2156 def debugcreatestreamclonebundle(ui, repo, fname):
2157 2157 """create a stream clone bundle file
2158 2158
2159 2159 Stream bundles are special bundles that are essentially archives of
2160 2160 revlog files. They are commonly used for cloning very quickly.
2161 2161 """
2162 2162 requirements, gen = streamclone.generatebundlev1(repo)
2163 2163 changegroup.writechunks(ui, gen, fname)
2164 2164
2165 2165 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2166 2166
2167 2167 @command('debugapplystreamclonebundle', [], 'FILE')
2168 2168 def debugapplystreamclonebundle(ui, repo, fname):
2169 2169 """apply a stream clone bundle file"""
2170 2170 f = hg.openpath(ui, fname)
2171 2171 gen = exchange.readbundle(ui, f, fname)
2172 2172 gen.apply(repo)
2173 2173
2174 2174 @command('debugcheckstate', [], '')
2175 2175 def debugcheckstate(ui, repo):
2176 2176 """validate the correctness of the current dirstate"""
2177 2177 parent1, parent2 = repo.dirstate.parents()
2178 2178 m1 = repo[parent1].manifest()
2179 2179 m2 = repo[parent2].manifest()
2180 2180 errors = 0
2181 2181 for f in repo.dirstate:
2182 2182 state = repo.dirstate[f]
2183 2183 if state in "nr" and f not in m1:
2184 2184 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2185 2185 errors += 1
2186 2186 if state in "a" and f in m1:
2187 2187 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2188 2188 errors += 1
2189 2189 if state in "m" and f not in m1 and f not in m2:
2190 2190 ui.warn(_("%s in state %s, but not in either manifest\n") %
2191 2191 (f, state))
2192 2192 errors += 1
2193 2193 for f in m1:
2194 2194 state = repo.dirstate[f]
2195 2195 if state not in "nrm":
2196 2196 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2197 2197 errors += 1
2198 2198 if errors:
2199 2199 error = _(".hg/dirstate inconsistent with current parent's manifest")
2200 2200 raise error.Abort(error)
2201 2201
2202 2202 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2203 2203 def debugcommands(ui, cmd='', *args):
2204 2204 """list all available commands and options"""
2205 2205 for cmd, vals in sorted(table.iteritems()):
2206 2206 cmd = cmd.split('|')[0].strip('^')
2207 2207 opts = ', '.join([i[1] for i in vals[1]])
2208 2208 ui.write('%s: %s\n' % (cmd, opts))
2209 2209
2210 2210 @command('debugcomplete',
2211 2211 [('o', 'options', None, _('show the command options'))],
2212 2212 _('[-o] CMD'),
2213 2213 norepo=True)
2214 2214 def debugcomplete(ui, cmd='', **opts):
2215 2215 """returns the completion list associated with the given command"""
2216 2216
2217 2217 if opts.get('options'):
2218 2218 options = []
2219 2219 otables = [globalopts]
2220 2220 if cmd:
2221 2221 aliases, entry = cmdutil.findcmd(cmd, table, False)
2222 2222 otables.append(entry[1])
2223 2223 for t in otables:
2224 2224 for o in t:
2225 2225 if "(DEPRECATED)" in o[3]:
2226 2226 continue
2227 2227 if o[0]:
2228 2228 options.append('-%s' % o[0])
2229 2229 options.append('--%s' % o[1])
2230 2230 ui.write("%s\n" % "\n".join(options))
2231 2231 return
2232 2232
2233 2233 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2234 2234 if ui.verbose:
2235 2235 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2236 2236 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2237 2237
2238 2238 @command('debugdag',
2239 2239 [('t', 'tags', None, _('use tags as labels')),
2240 2240 ('b', 'branches', None, _('annotate with branch names')),
2241 2241 ('', 'dots', None, _('use dots for runs')),
2242 2242 ('s', 'spaces', None, _('separate elements by spaces'))],
2243 2243 _('[OPTION]... [FILE [REV]...]'),
2244 2244 optionalrepo=True)
2245 2245 def debugdag(ui, repo, file_=None, *revs, **opts):
2246 2246 """format the changelog or an index DAG as a concise textual description
2247 2247
2248 2248 If you pass a revlog index, the revlog's DAG is emitted. If you list
2249 2249 revision numbers, they get labeled in the output as rN.
2250 2250
2251 2251 Otherwise, the changelog DAG of the current repo is emitted.
2252 2252 """
2253 2253 spaces = opts.get('spaces')
2254 2254 dots = opts.get('dots')
2255 2255 if file_:
2256 2256 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2257 2257 revs = set((int(r) for r in revs))
2258 2258 def events():
2259 2259 for r in rlog:
2260 2260 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2261 2261 if p != -1))
2262 2262 if r in revs:
2263 2263 yield 'l', (r, "r%i" % r)
2264 2264 elif repo:
2265 2265 cl = repo.changelog
2266 2266 tags = opts.get('tags')
2267 2267 branches = opts.get('branches')
2268 2268 if tags:
2269 2269 labels = {}
2270 2270 for l, n in repo.tags().items():
2271 2271 labels.setdefault(cl.rev(n), []).append(l)
2272 2272 def events():
2273 2273 b = "default"
2274 2274 for r in cl:
2275 2275 if branches:
2276 2276 newb = cl.read(cl.node(r))[5]['branch']
2277 2277 if newb != b:
2278 2278 yield 'a', newb
2279 2279 b = newb
2280 2280 yield 'n', (r, list(p for p in cl.parentrevs(r)
2281 2281 if p != -1))
2282 2282 if tags:
2283 2283 ls = labels.get(r)
2284 2284 if ls:
2285 2285 for l in ls:
2286 2286 yield 'l', (r, l)
2287 2287 else:
2288 2288 raise error.Abort(_('need repo for changelog dag'))
2289 2289
2290 2290 for line in dagparser.dagtextlines(events(),
2291 2291 addspaces=spaces,
2292 2292 wraplabels=True,
2293 2293 wrapannotations=True,
2294 2294 wrapnonlinear=dots,
2295 2295 usedots=dots,
2296 2296 maxlinewidth=70):
2297 2297 ui.write(line)
2298 2298 ui.write("\n")
2299 2299
2300 2300 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2301 2301 def debugdata(ui, repo, file_, rev=None, **opts):
2302 2302 """dump the contents of a data file revision"""
2303 2303 if opts.get('changelog') or opts.get('manifest'):
2304 2304 file_, rev = None, file_
2305 2305 elif rev is None:
2306 2306 raise error.CommandError('debugdata', _('invalid arguments'))
2307 2307 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2308 2308 try:
2309 2309 ui.write(r.revision(r.lookup(rev)))
2310 2310 except KeyError:
2311 2311 raise error.Abort(_('invalid revision identifier %s') % rev)
2312 2312
2313 2313 @command('debugdate',
2314 2314 [('e', 'extended', None, _('try extended date formats'))],
2315 2315 _('[-e] DATE [RANGE]'),
2316 2316 norepo=True, optionalrepo=True)
2317 2317 def debugdate(ui, date, range=None, **opts):
2318 2318 """parse and display a date"""
2319 2319 if opts["extended"]:
2320 2320 d = util.parsedate(date, util.extendeddateformats)
2321 2321 else:
2322 2322 d = util.parsedate(date)
2323 2323 ui.write(("internal: %s %s\n") % d)
2324 2324 ui.write(("standard: %s\n") % util.datestr(d))
2325 2325 if range:
2326 2326 m = util.matchdate(range)
2327 2327 ui.write(("match: %s\n") % m(d[0]))
2328 2328
2329 2329 @command('debugdiscovery',
2330 2330 [('', 'old', None, _('use old-style discovery')),
2331 2331 ('', 'nonheads', None,
2332 2332 _('use old-style discovery with non-heads included')),
2333 2333 ] + remoteopts,
2334 2334 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2335 2335 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2336 2336 """runs the changeset discovery protocol in isolation"""
2337 2337 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2338 2338 opts.get('branch'))
2339 2339 remote = hg.peer(repo, opts, remoteurl)
2340 2340 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2341 2341
2342 2342 # make sure tests are repeatable
2343 2343 random.seed(12323)
2344 2344
2345 2345 def doit(localheads, remoteheads, remote=remote):
2346 2346 if opts.get('old'):
2347 2347 if localheads:
2348 2348 raise error.Abort('cannot use localheads with old style '
2349 2349 'discovery')
2350 2350 if not util.safehasattr(remote, 'branches'):
2351 2351 # enable in-client legacy support
2352 2352 remote = localrepo.locallegacypeer(remote.local())
2353 2353 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2354 2354 force=True)
2355 2355 common = set(common)
2356 2356 if not opts.get('nonheads'):
2357 2357 ui.write(("unpruned common: %s\n") %
2358 2358 " ".join(sorted(short(n) for n in common)))
2359 2359 dag = dagutil.revlogdag(repo.changelog)
2360 2360 all = dag.ancestorset(dag.internalizeall(common))
2361 2361 common = dag.externalizeall(dag.headsetofconnecteds(all))
2362 2362 else:
2363 2363 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2364 2364 common = set(common)
2365 2365 rheads = set(hds)
2366 2366 lheads = set(repo.heads())
2367 2367 ui.write(("common heads: %s\n") %
2368 2368 " ".join(sorted(short(n) for n in common)))
2369 2369 if lheads <= common:
2370 2370 ui.write(("local is subset\n"))
2371 2371 elif rheads <= common:
2372 2372 ui.write(("remote is subset\n"))
2373 2373
2374 2374 serverlogs = opts.get('serverlog')
2375 2375 if serverlogs:
2376 2376 for filename in serverlogs:
2377 2377 with open(filename, 'r') as logfile:
2378 2378 line = logfile.readline()
2379 2379 while line:
2380 2380 parts = line.strip().split(';')
2381 2381 op = parts[1]
2382 2382 if op == 'cg':
2383 2383 pass
2384 2384 elif op == 'cgss':
2385 2385 doit(parts[2].split(' '), parts[3].split(' '))
2386 2386 elif op == 'unb':
2387 2387 doit(parts[3].split(' '), parts[2].split(' '))
2388 2388 line = logfile.readline()
2389 2389 else:
2390 2390 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2391 2391 opts.get('remote_head'))
2392 2392 localrevs = opts.get('local_head')
2393 2393 doit(localrevs, remoterevs)
2394 2394
2395 2395 @command('debugextensions', formatteropts, [], norepo=True)
2396 2396 def debugextensions(ui, **opts):
2397 2397 '''show information about active extensions'''
2398 2398 exts = extensions.extensions(ui)
2399 2399 fm = ui.formatter('debugextensions', opts)
2400 2400 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2401 2401 extsource = extmod.__file__
2402 2402 exttestedwith = getattr(extmod, 'testedwith', None)
2403 2403 if exttestedwith is not None:
2404 2404 exttestedwith = exttestedwith.split()
2405 2405 extbuglink = getattr(extmod, 'buglink', None)
2406 2406
2407 2407 fm.startitem()
2408 2408
2409 2409 if ui.quiet or ui.verbose:
2410 2410 fm.write('name', '%s\n', extname)
2411 2411 else:
2412 2412 fm.write('name', '%s', extname)
2413 2413 if not exttestedwith:
2414 2414 fm.plain(_(' (untested!)\n'))
2415 2415 else:
2416 2416 if exttestedwith == ['internal'] or \
2417 2417 util.version() in exttestedwith:
2418 2418 fm.plain('\n')
2419 2419 else:
2420 2420 lasttestedversion = exttestedwith[-1]
2421 2421 fm.plain(' (%s!)\n' % lasttestedversion)
2422 2422
2423 2423 fm.condwrite(ui.verbose and extsource, 'source',
2424 2424 _(' location: %s\n'), extsource or "")
2425 2425
2426 2426 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2427 2427 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2428 2428
2429 2429 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2430 2430 _(' bug reporting: %s\n'), extbuglink or "")
2431 2431
2432 2432 fm.end()
2433 2433
2434 2434 @command('debugfileset',
2435 2435 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2436 2436 _('[-r REV] FILESPEC'))
2437 2437 def debugfileset(ui, repo, expr, **opts):
2438 2438 '''parse and apply a fileset specification'''
2439 2439 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2440 2440 if ui.verbose:
2441 2441 tree = fileset.parse(expr)
2442 2442 ui.note(fileset.prettyformat(tree), "\n")
2443 2443
2444 2444 for f in ctx.getfileset(expr):
2445 2445 ui.write("%s\n" % f)
2446 2446
2447 2447 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2448 2448 def debugfsinfo(ui, path="."):
2449 2449 """show information detected about current filesystem"""
2450 2450 util.writefile('.debugfsinfo', '')
2451 2451 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2452 2452 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2453 2453 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2454 2454 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2455 2455 and 'yes' or 'no'))
2456 2456 os.unlink('.debugfsinfo')
2457 2457
2458 2458 @command('debuggetbundle',
2459 2459 [('H', 'head', [], _('id of head node'), _('ID')),
2460 2460 ('C', 'common', [], _('id of common node'), _('ID')),
2461 2461 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2462 2462 _('REPO FILE [-H|-C ID]...'),
2463 2463 norepo=True)
2464 2464 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2465 2465 """retrieves a bundle from a repo
2466 2466
2467 2467 Every ID must be a full-length hex node id string. Saves the bundle to the
2468 2468 given file.
2469 2469 """
2470 2470 repo = hg.peer(ui, opts, repopath)
2471 2471 if not repo.capable('getbundle'):
2472 2472 raise error.Abort("getbundle() not supported by target repository")
2473 2473 args = {}
2474 2474 if common:
2475 2475 args['common'] = [bin(s) for s in common]
2476 2476 if head:
2477 2477 args['heads'] = [bin(s) for s in head]
2478 2478 # TODO: get desired bundlecaps from command line.
2479 2479 args['bundlecaps'] = None
2480 2480 bundle = repo.getbundle('debug', **args)
2481 2481
2482 2482 bundletype = opts.get('type', 'bzip2').lower()
2483 2483 btypes = {'none': 'HG10UN',
2484 2484 'bzip2': 'HG10BZ',
2485 2485 'gzip': 'HG10GZ',
2486 2486 'bundle2': 'HG20'}
2487 2487 bundletype = btypes.get(bundletype)
2488 2488 if bundletype not in bundle2.bundletypes:
2489 2489 raise error.Abort(_('unknown bundle type specified with --type'))
2490 2490 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2491 2491
2492 2492 @command('debugignore', [], '[FILE]')
2493 2493 def debugignore(ui, repo, *files, **opts):
2494 2494 """display the combined ignore pattern and information about ignored files
2495 2495
2496 2496 With no argument display the combined ignore pattern.
2497 2497
2498 2498 Given space separated file names, shows if the given file is ignored and
2499 2499 if so, show the ignore rule (file and line number) that matched it.
2500 2500 """
2501 2501 ignore = repo.dirstate._ignore
2502 2502 if not files:
2503 2503 # Show all the patterns
2504 2504 includepat = getattr(ignore, 'includepat', None)
2505 2505 if includepat is not None:
2506 2506 ui.write("%s\n" % includepat)
2507 2507 else:
2508 2508 raise error.Abort(_("no ignore patterns found"))
2509 2509 else:
2510 2510 for f in files:
2511 2511 nf = util.normpath(f)
2512 2512 ignored = None
2513 2513 ignoredata = None
2514 2514 if nf != '.':
2515 2515 if ignore(nf):
2516 2516 ignored = nf
2517 2517 ignoredata = repo.dirstate._ignorefileandline(nf)
2518 2518 else:
2519 2519 for p in util.finddirs(nf):
2520 2520 if ignore(p):
2521 2521 ignored = p
2522 2522 ignoredata = repo.dirstate._ignorefileandline(p)
2523 2523 break
2524 2524 if ignored:
2525 2525 if ignored == nf:
2526 2526 ui.write("%s is ignored\n" % f)
2527 2527 else:
2528 2528 ui.write("%s is ignored because of containing folder %s\n"
2529 2529 % (f, ignored))
2530 2530 ignorefile, lineno, line = ignoredata
2531 2531 ui.write("(ignore rule in %s, line %d: '%s')\n"
2532 2532 % (ignorefile, lineno, line))
2533 2533 else:
2534 2534 ui.write("%s is not ignored\n" % f)
2535 2535
2536 2536 @command('debugindex', debugrevlogopts +
2537 2537 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2538 2538 _('[-f FORMAT] -c|-m|FILE'),
2539 2539 optionalrepo=True)
2540 2540 def debugindex(ui, repo, file_=None, **opts):
2541 2541 """dump the contents of an index file"""
2542 2542 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2543 2543 format = opts.get('format', 0)
2544 2544 if format not in (0, 1):
2545 2545 raise error.Abort(_("unknown format %d") % format)
2546 2546
2547 2547 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2548 2548 if generaldelta:
2549 2549 basehdr = ' delta'
2550 2550 else:
2551 2551 basehdr = ' base'
2552 2552
2553 2553 if ui.debugflag:
2554 2554 shortfn = hex
2555 2555 else:
2556 2556 shortfn = short
2557 2557
2558 2558 # There might not be anything in r, so have a sane default
2559 2559 idlen = 12
2560 2560 for i in r:
2561 2561 idlen = len(shortfn(r.node(i)))
2562 2562 break
2563 2563
2564 2564 if format == 0:
2565 2565 ui.write(" rev offset length " + basehdr + " linkrev"
2566 2566 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2567 2567 elif format == 1:
2568 2568 ui.write(" rev flag offset length"
2569 2569 " size " + basehdr + " link p1 p2"
2570 2570 " %s\n" % "nodeid".rjust(idlen))
2571 2571
2572 2572 for i in r:
2573 2573 node = r.node(i)
2574 2574 if generaldelta:
2575 2575 base = r.deltaparent(i)
2576 2576 else:
2577 2577 base = r.chainbase(i)
2578 2578 if format == 0:
2579 2579 try:
2580 2580 pp = r.parents(node)
2581 2581 except Exception:
2582 2582 pp = [nullid, nullid]
2583 2583 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2584 2584 i, r.start(i), r.length(i), base, r.linkrev(i),
2585 2585 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2586 2586 elif format == 1:
2587 2587 pr = r.parentrevs(i)
2588 2588 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2589 2589 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2590 2590 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2591 2591
2592 2592 @command('debugindexdot', debugrevlogopts,
2593 2593 _('-c|-m|FILE'), optionalrepo=True)
2594 2594 def debugindexdot(ui, repo, file_=None, **opts):
2595 2595 """dump an index DAG as a graphviz dot file"""
2596 2596 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2597 2597 ui.write(("digraph G {\n"))
2598 2598 for i in r:
2599 2599 node = r.node(i)
2600 2600 pp = r.parents(node)
2601 2601 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2602 2602 if pp[1] != nullid:
2603 2603 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2604 2604 ui.write("}\n")
2605 2605
2606 2606 @command('debugdeltachain',
2607 2607 debugrevlogopts + formatteropts,
2608 2608 _('-c|-m|FILE'),
2609 2609 optionalrepo=True)
2610 2610 def debugdeltachain(ui, repo, file_=None, **opts):
2611 2611 """dump information about delta chains in a revlog
2612 2612
2613 2613 Output can be templatized. Available template keywords are:
2614 2614
2615 2615 rev revision number
2616 2616 chainid delta chain identifier (numbered by unique base)
2617 2617 chainlen delta chain length to this revision
2618 2618 prevrev previous revision in delta chain
2619 2619 deltatype role of delta / how it was computed
2620 2620 compsize compressed size of revision
2621 2621 uncompsize uncompressed size of revision
2622 2622 chainsize total size of compressed revisions in chain
2623 2623 chainratio total chain size divided by uncompressed revision size
2624 2624 (new delta chains typically start at ratio 2.00)
2625 2625 lindist linear distance from base revision in delta chain to end
2626 2626 of this revision
2627 2627 extradist total size of revisions not part of this delta chain from
2628 2628 base of delta chain to end of this revision; a measurement
2629 2629 of how much extra data we need to read/seek across to read
2630 2630 the delta chain for this revision
2631 2631 extraratio extradist divided by chainsize; another representation of
2632 2632 how much unrelated data is needed to load this delta chain
2633 2633 """
2634 2634 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2635 2635 index = r.index
2636 2636 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2637 2637
2638 2638 def revinfo(rev):
2639 2639 e = index[rev]
2640 2640 compsize = e[1]
2641 2641 uncompsize = e[2]
2642 2642 chainsize = 0
2643 2643
2644 2644 if generaldelta:
2645 2645 if e[3] == e[5]:
2646 2646 deltatype = 'p1'
2647 2647 elif e[3] == e[6]:
2648 2648 deltatype = 'p2'
2649 2649 elif e[3] == rev - 1:
2650 2650 deltatype = 'prev'
2651 2651 elif e[3] == rev:
2652 2652 deltatype = 'base'
2653 2653 else:
2654 2654 deltatype = 'other'
2655 2655 else:
2656 2656 if e[3] == rev:
2657 2657 deltatype = 'base'
2658 2658 else:
2659 2659 deltatype = 'prev'
2660 2660
2661 2661 chain = r._deltachain(rev)[0]
2662 2662 for iterrev in chain:
2663 2663 e = index[iterrev]
2664 2664 chainsize += e[1]
2665 2665
2666 2666 return compsize, uncompsize, deltatype, chain, chainsize
2667 2667
2668 2668 fm = ui.formatter('debugdeltachain', opts)
2669 2669
2670 2670 fm.plain(' rev chain# chainlen prev delta '
2671 2671 'size rawsize chainsize ratio lindist extradist '
2672 2672 'extraratio\n')
2673 2673
2674 2674 chainbases = {}
2675 2675 for rev in r:
2676 2676 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2677 2677 chainbase = chain[0]
2678 2678 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2679 2679 basestart = r.start(chainbase)
2680 2680 revstart = r.start(rev)
2681 2681 lineardist = revstart + comp - basestart
2682 2682 extradist = lineardist - chainsize
2683 2683 try:
2684 2684 prevrev = chain[-2]
2685 2685 except IndexError:
2686 2686 prevrev = -1
2687 2687
2688 2688 chainratio = float(chainsize) / float(uncomp)
2689 2689 extraratio = float(extradist) / float(chainsize)
2690 2690
2691 2691 fm.startitem()
2692 2692 fm.write('rev chainid chainlen prevrev deltatype compsize '
2693 2693 'uncompsize chainsize chainratio lindist extradist '
2694 2694 'extraratio',
2695 2695 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2696 2696 rev, chainid, len(chain), prevrev, deltatype, comp,
2697 2697 uncomp, chainsize, chainratio, lineardist, extradist,
2698 2698 extraratio,
2699 2699 rev=rev, chainid=chainid, chainlen=len(chain),
2700 2700 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2701 2701 uncompsize=uncomp, chainsize=chainsize,
2702 2702 chainratio=chainratio, lindist=lineardist,
2703 2703 extradist=extradist, extraratio=extraratio)
2704 2704
2705 2705 fm.end()
2706 2706
2707 2707 @command('debuginstall', [] + formatteropts, '', norepo=True)
2708 2708 def debuginstall(ui, **opts):
2709 2709 '''test Mercurial installation
2710 2710
2711 2711 Returns 0 on success.
2712 2712 '''
2713 2713
2714 2714 def writetemp(contents):
2715 2715 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2716 2716 f = os.fdopen(fd, "wb")
2717 2717 f.write(contents)
2718 2718 f.close()
2719 2719 return name
2720 2720
2721 2721 problems = 0
2722 2722
2723 2723 fm = ui.formatter('debuginstall', opts)
2724 2724 fm.startitem()
2725 2725
2726 2726 # encoding
2727 2727 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2728 2728 err = None
2729 2729 try:
2730 2730 encoding.fromlocal("test")
2731 2731 except error.Abort as inst:
2732 2732 err = inst
2733 2733 problems += 1
2734 2734 fm.condwrite(err, 'encodingerror', _(" %s\n"
2735 2735 " (check that your locale is properly set)\n"), err)
2736 2736
2737 2737 # Python
2738 2738 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2739 2739 sys.executable)
2740 2740 fm.write('pythonver', _("checking Python version (%s)\n"),
2741 2741 ("%s.%s.%s" % sys.version_info[:3]))
2742 2742 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2743 2743 os.path.dirname(os.__file__))
2744 2744
2745 2745 # compiled modules
2746 2746 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2747 2747 os.path.dirname(__file__))
2748 2748
2749 2749 err = None
2750 2750 try:
2751 2751 from . import (
2752 2752 base85,
2753 2753 bdiff,
2754 2754 mpatch,
2755 2755 osutil,
2756 2756 )
2757 2757 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2758 2758 except Exception as inst:
2759 2759 err = inst
2760 2760 problems += 1
2761 2761 fm.condwrite(err, 'extensionserror', " %s\n", err)
2762 2762
2763 2763 # templates
2764 2764 p = templater.templatepaths()
2765 2765 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2766 2766 fm.condwrite(not p, '', _(" no template directories found\n"))
2767 2767 if p:
2768 2768 m = templater.templatepath("map-cmdline.default")
2769 2769 if m:
2770 2770 # template found, check if it is working
2771 2771 err = None
2772 2772 try:
2773 2773 templater.templater(m)
2774 2774 except Exception as inst:
2775 2775 err = inst
2776 2776 p = None
2777 2777 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2778 2778 else:
2779 2779 p = None
2780 2780 fm.condwrite(p, 'defaulttemplate',
2781 2781 _("checking default template (%s)\n"), m)
2782 2782 fm.condwrite(not m, 'defaulttemplatenotfound',
2783 2783 _(" template '%s' not found\n"), "default")
2784 2784 if not p:
2785 2785 problems += 1
2786 2786 fm.condwrite(not p, '',
2787 2787 _(" (templates seem to have been installed incorrectly)\n"))
2788 2788
2789 2789 # editor
2790 2790 editor = ui.geteditor()
2791 2791 editor = util.expandpath(editor)
2792 2792 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2793 2793 cmdpath = util.findexe(shlex.split(editor)[0])
2794 2794 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2795 2795 _(" No commit editor set and can't find %s in PATH\n"
2796 2796 " (specify a commit editor in your configuration"
2797 2797 " file)\n"), not cmdpath and editor == 'vi' and editor)
2798 2798 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2799 2799 _(" Can't find editor '%s' in PATH\n"
2800 2800 " (specify a commit editor in your configuration"
2801 2801 " file)\n"), not cmdpath and editor)
2802 2802 if not cmdpath and editor != 'vi':
2803 2803 problems += 1
2804 2804
2805 2805 # check username
2806 2806 username = None
2807 2807 err = None
2808 2808 try:
2809 2809 username = ui.username()
2810 2810 except error.Abort as e:
2811 2811 err = e
2812 2812 problems += 1
2813 2813
2814 2814 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2815 2815 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2816 2816 " (specify a username in your configuration file)\n"), err)
2817 2817
2818 2818 fm.condwrite(not problems, '',
2819 2819 _("no problems detected\n"))
2820 2820 if not problems:
2821 2821 fm.data(problems=problems)
2822 2822 fm.condwrite(problems, 'problems',
2823 2823 _("%s problems detected,"
2824 2824 " please check your install!\n"), problems)
2825 2825 fm.end()
2826 2826
2827 2827 return problems
2828 2828
2829 2829 @command('debugknown', [], _('REPO ID...'), norepo=True)
2830 2830 def debugknown(ui, repopath, *ids, **opts):
2831 2831 """test whether node ids are known to a repo
2832 2832
2833 2833 Every ID must be a full-length hex node id string. Returns a list of 0s
2834 2834 and 1s indicating unknown/known.
2835 2835 """
2836 2836 repo = hg.peer(ui, opts, repopath)
2837 2837 if not repo.capable('known'):
2838 2838 raise error.Abort("known() not supported by target repository")
2839 2839 flags = repo.known([bin(s) for s in ids])
2840 2840 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2841 2841
2842 2842 @command('debuglabelcomplete', [], _('LABEL...'))
2843 2843 def debuglabelcomplete(ui, repo, *args):
2844 2844 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2845 2845 debugnamecomplete(ui, repo, *args)
2846 2846
2847 2847 @command('debugmergestate', [], '')
2848 2848 def debugmergestate(ui, repo, *args):
2849 2849 """print merge state
2850 2850
2851 2851 Use --verbose to print out information about whether v1 or v2 merge state
2852 2852 was chosen."""
2853 2853 def _hashornull(h):
2854 2854 if h == nullhex:
2855 2855 return 'null'
2856 2856 else:
2857 2857 return h
2858 2858
2859 2859 def printrecords(version):
2860 2860 ui.write(('* version %s records\n') % version)
2861 2861 if version == 1:
2862 2862 records = v1records
2863 2863 else:
2864 2864 records = v2records
2865 2865
2866 2866 for rtype, record in records:
2867 2867 # pretty print some record types
2868 2868 if rtype == 'L':
2869 2869 ui.write(('local: %s\n') % record)
2870 2870 elif rtype == 'O':
2871 2871 ui.write(('other: %s\n') % record)
2872 2872 elif rtype == 'm':
2873 2873 driver, mdstate = record.split('\0', 1)
2874 2874 ui.write(('merge driver: %s (state "%s")\n')
2875 2875 % (driver, mdstate))
2876 2876 elif rtype in 'FDC':
2877 2877 r = record.split('\0')
2878 2878 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2879 2879 if version == 1:
2880 2880 onode = 'not stored in v1 format'
2881 2881 flags = r[7]
2882 2882 else:
2883 2883 onode, flags = r[7:9]
2884 2884 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2885 2885 % (f, rtype, state, _hashornull(hash)))
2886 2886 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2887 2887 ui.write((' ancestor path: %s (node %s)\n')
2888 2888 % (afile, _hashornull(anode)))
2889 2889 ui.write((' other path: %s (node %s)\n')
2890 2890 % (ofile, _hashornull(onode)))
2891 2891 elif rtype == 'f':
2892 2892 filename, rawextras = record.split('\0', 1)
2893 2893 extras = rawextras.split('\0')
2894 2894 i = 0
2895 2895 extrastrings = []
2896 2896 while i < len(extras):
2897 2897 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2898 2898 i += 2
2899 2899
2900 2900 ui.write(('file extras: %s (%s)\n')
2901 2901 % (filename, ', '.join(extrastrings)))
2902 2902 elif rtype == 'l':
2903 2903 labels = record.split('\0', 2)
2904 2904 labels = [l for l in labels if len(l) > 0]
2905 2905 ui.write(('labels:\n'))
2906 2906 ui.write((' local: %s\n' % labels[0]))
2907 2907 ui.write((' other: %s\n' % labels[1]))
2908 2908 if len(labels) > 2:
2909 2909 ui.write((' base: %s\n' % labels[2]))
2910 2910 else:
2911 2911 ui.write(('unrecognized entry: %s\t%s\n')
2912 2912 % (rtype, record.replace('\0', '\t')))
2913 2913
2914 2914 # Avoid mergestate.read() since it may raise an exception for unsupported
2915 2915 # merge state records. We shouldn't be doing this, but this is OK since this
2916 2916 # command is pretty low-level.
2917 2917 ms = mergemod.mergestate(repo)
2918 2918
2919 2919 # sort so that reasonable information is on top
2920 2920 v1records = ms._readrecordsv1()
2921 2921 v2records = ms._readrecordsv2()
2922 2922 order = 'LOml'
2923 2923 def key(r):
2924 2924 idx = order.find(r[0])
2925 2925 if idx == -1:
2926 2926 return (1, r[1])
2927 2927 else:
2928 2928 return (0, idx)
2929 2929 v1records.sort(key=key)
2930 2930 v2records.sort(key=key)
2931 2931
2932 2932 if not v1records and not v2records:
2933 2933 ui.write(('no merge state found\n'))
2934 2934 elif not v2records:
2935 2935 ui.note(('no version 2 merge state\n'))
2936 2936 printrecords(1)
2937 2937 elif ms._v1v2match(v1records, v2records):
2938 2938 ui.note(('v1 and v2 states match: using v2\n'))
2939 2939 printrecords(2)
2940 2940 else:
2941 2941 ui.note(('v1 and v2 states mismatch: using v1\n'))
2942 2942 printrecords(1)
2943 2943 if ui.verbose:
2944 2944 printrecords(2)
2945 2945
2946 2946 @command('debugnamecomplete', [], _('NAME...'))
2947 2947 def debugnamecomplete(ui, repo, *args):
2948 2948 '''complete "names" - tags, open branch names, bookmark names'''
2949 2949
2950 2950 names = set()
2951 2951 # since we previously only listed open branches, we will handle that
2952 2952 # specially (after this for loop)
2953 2953 for name, ns in repo.names.iteritems():
2954 2954 if name != 'branches':
2955 2955 names.update(ns.listnames(repo))
2956 2956 names.update(tag for (tag, heads, tip, closed)
2957 2957 in repo.branchmap().iterbranches() if not closed)
2958 2958 completions = set()
2959 2959 if not args:
2960 2960 args = ['']
2961 2961 for a in args:
2962 2962 completions.update(n for n in names if n.startswith(a))
2963 2963 ui.write('\n'.join(sorted(completions)))
2964 2964 ui.write('\n')
2965 2965
2966 2966 @command('debuglocks',
2967 2967 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2968 2968 ('W', 'force-wlock', None,
2969 2969 _('free the working state lock (DANGEROUS)'))],
2970 2970 _('[OPTION]...'))
2971 2971 def debuglocks(ui, repo, **opts):
2972 2972 """show or modify state of locks
2973 2973
2974 2974 By default, this command will show which locks are held. This
2975 2975 includes the user and process holding the lock, the amount of time
2976 2976 the lock has been held, and the machine name where the process is
2977 2977 running if it's not local.
2978 2978
2979 2979 Locks protect the integrity of Mercurial's data, so should be
2980 2980 treated with care. System crashes or other interruptions may cause
2981 2981 locks to not be properly released, though Mercurial will usually
2982 2982 detect and remove such stale locks automatically.
2983 2983
2984 2984 However, detecting stale locks may not always be possible (for
2985 2985 instance, on a shared filesystem). Removing locks may also be
2986 2986 blocked by filesystem permissions.
2987 2987
2988 2988 Returns 0 if no locks are held.
2989 2989
2990 2990 """
2991 2991
2992 2992 if opts.get('force_lock'):
2993 2993 repo.svfs.unlink('lock')
2994 2994 if opts.get('force_wlock'):
2995 2995 repo.vfs.unlink('wlock')
2996 2996 if opts.get('force_lock') or opts.get('force_lock'):
2997 2997 return 0
2998 2998
2999 2999 now = time.time()
3000 3000 held = 0
3001 3001
3002 3002 def report(vfs, name, method):
3003 3003 # this causes stale locks to get reaped for more accurate reporting
3004 3004 try:
3005 3005 l = method(False)
3006 3006 except error.LockHeld:
3007 3007 l = None
3008 3008
3009 3009 if l:
3010 3010 l.release()
3011 3011 else:
3012 3012 try:
3013 3013 stat = vfs.lstat(name)
3014 3014 age = now - stat.st_mtime
3015 3015 user = util.username(stat.st_uid)
3016 3016 locker = vfs.readlock(name)
3017 3017 if ":" in locker:
3018 3018 host, pid = locker.split(':')
3019 3019 if host == socket.gethostname():
3020 3020 locker = 'user %s, process %s' % (user, pid)
3021 3021 else:
3022 3022 locker = 'user %s, process %s, host %s' \
3023 3023 % (user, pid, host)
3024 3024 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
3025 3025 return 1
3026 3026 except OSError as e:
3027 3027 if e.errno != errno.ENOENT:
3028 3028 raise
3029 3029
3030 3030 ui.write("%-6s free\n" % (name + ":"))
3031 3031 return 0
3032 3032
3033 3033 held += report(repo.svfs, "lock", repo.lock)
3034 3034 held += report(repo.vfs, "wlock", repo.wlock)
3035 3035
3036 3036 return held
3037 3037
3038 3038 @command('debugobsolete',
3039 3039 [('', 'flags', 0, _('markers flag')),
3040 3040 ('', 'record-parents', False,
3041 3041 _('record parent information for the precursor')),
3042 3042 ('r', 'rev', [], _('display markers relevant to REV')),
3043 3043 ('', 'index', False, _('display index of the marker')),
3044 3044 ('', 'delete', [], _('delete markers specified by indices')),
3045 3045 ] + commitopts2,
3046 3046 _('[OBSOLETED [REPLACEMENT ...]]'))
3047 3047 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3048 3048 """create arbitrary obsolete marker
3049 3049
3050 3050 With no arguments, displays the list of obsolescence markers."""
3051 3051
3052 3052 def parsenodeid(s):
3053 3053 try:
3054 3054 # We do not use revsingle/revrange functions here to accept
3055 3055 # arbitrary node identifiers, possibly not present in the
3056 3056 # local repository.
3057 3057 n = bin(s)
3058 3058 if len(n) != len(nullid):
3059 3059 raise TypeError()
3060 3060 return n
3061 3061 except TypeError:
3062 3062 raise error.Abort('changeset references must be full hexadecimal '
3063 3063 'node identifiers')
3064 3064
3065 3065 if opts.get('delete'):
3066 3066 indices = []
3067 3067 for v in opts.get('delete'):
3068 3068 try:
3069 3069 indices.append(int(v))
3070 3070 except ValueError:
3071 3071 raise error.Abort(_('invalid index value: %r') % v,
3072 3072 hint=_('use integers for indices'))
3073 3073
3074 3074 if repo.currenttransaction():
3075 3075 raise error.Abort(_('cannot delete obsmarkers in the middle '
3076 3076 'of transaction.'))
3077 3077
3078 3078 with repo.lock():
3079 3079 n = repair.deleteobsmarkers(repo.obsstore, indices)
3080 3080 ui.write(_('deleted %i obsolescense markers\n') % n)
3081 3081
3082 3082 return
3083 3083
3084 3084 if precursor is not None:
3085 3085 if opts['rev']:
3086 3086 raise error.Abort('cannot select revision when creating marker')
3087 3087 metadata = {}
3088 3088 metadata['user'] = opts['user'] or ui.username()
3089 3089 succs = tuple(parsenodeid(succ) for succ in successors)
3090 3090 l = repo.lock()
3091 3091 try:
3092 3092 tr = repo.transaction('debugobsolete')
3093 3093 try:
3094 3094 date = opts.get('date')
3095 3095 if date:
3096 3096 date = util.parsedate(date)
3097 3097 else:
3098 3098 date = None
3099 3099 prec = parsenodeid(precursor)
3100 3100 parents = None
3101 3101 if opts['record_parents']:
3102 3102 if prec not in repo.unfiltered():
3103 3103 raise error.Abort('cannot used --record-parents on '
3104 3104 'unknown changesets')
3105 3105 parents = repo.unfiltered()[prec].parents()
3106 3106 parents = tuple(p.node() for p in parents)
3107 3107 repo.obsstore.create(tr, prec, succs, opts['flags'],
3108 3108 parents=parents, date=date,
3109 3109 metadata=metadata)
3110 3110 tr.close()
3111 3111 except ValueError as exc:
3112 3112 raise error.Abort(_('bad obsmarker input: %s') % exc)
3113 3113 finally:
3114 3114 tr.release()
3115 3115 finally:
3116 3116 l.release()
3117 3117 else:
3118 3118 if opts['rev']:
3119 3119 revs = scmutil.revrange(repo, opts['rev'])
3120 3120 nodes = [repo[r].node() for r in revs]
3121 3121 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3122 3122 markers.sort(key=lambda x: x._data)
3123 3123 else:
3124 3124 markers = obsolete.getmarkers(repo)
3125 3125
3126 3126 markerstoiter = markers
3127 3127 isrelevant = lambda m: True
3128 3128 if opts.get('rev') and opts.get('index'):
3129 3129 markerstoiter = obsolete.getmarkers(repo)
3130 3130 markerset = set(markers)
3131 3131 isrelevant = lambda m: m in markerset
3132 3132
3133 3133 for i, m in enumerate(markerstoiter):
3134 3134 if not isrelevant(m):
3135 3135 # marker can be irrelevant when we're iterating over a set
3136 3136 # of markers (markerstoiter) which is bigger than the set
3137 3137 # of markers we want to display (markers)
3138 3138 # this can happen if both --index and --rev options are
3139 3139 # provided and thus we need to iterate over all of the markers
3140 3140 # to get the correct indices, but only display the ones that
3141 3141 # are relevant to --rev value
3142 3142 continue
3143 3143 ind = i if opts.get('index') else None
3144 3144 cmdutil.showmarker(ui, m, index=ind)
3145 3145
3146 3146 @command('debugpathcomplete',
3147 3147 [('f', 'full', None, _('complete an entire path')),
3148 3148 ('n', 'normal', None, _('show only normal files')),
3149 3149 ('a', 'added', None, _('show only added files')),
3150 3150 ('r', 'removed', None, _('show only removed files'))],
3151 3151 _('FILESPEC...'))
3152 3152 def debugpathcomplete(ui, repo, *specs, **opts):
3153 3153 '''complete part or all of a tracked path
3154 3154
3155 3155 This command supports shells that offer path name completion. It
3156 3156 currently completes only files already known to the dirstate.
3157 3157
3158 3158 Completion extends only to the next path segment unless
3159 3159 --full is specified, in which case entire paths are used.'''
3160 3160
3161 3161 def complete(path, acceptable):
3162 3162 dirstate = repo.dirstate
3163 3163 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3164 3164 rootdir = repo.root + os.sep
3165 3165 if spec != repo.root and not spec.startswith(rootdir):
3166 3166 return [], []
3167 3167 if os.path.isdir(spec):
3168 3168 spec += '/'
3169 3169 spec = spec[len(rootdir):]
3170 3170 fixpaths = os.sep != '/'
3171 3171 if fixpaths:
3172 3172 spec = spec.replace(os.sep, '/')
3173 3173 speclen = len(spec)
3174 3174 fullpaths = opts['full']
3175 3175 files, dirs = set(), set()
3176 3176 adddir, addfile = dirs.add, files.add
3177 3177 for f, st in dirstate.iteritems():
3178 3178 if f.startswith(spec) and st[0] in acceptable:
3179 3179 if fixpaths:
3180 3180 f = f.replace('/', os.sep)
3181 3181 if fullpaths:
3182 3182 addfile(f)
3183 3183 continue
3184 3184 s = f.find(os.sep, speclen)
3185 3185 if s >= 0:
3186 3186 adddir(f[:s])
3187 3187 else:
3188 3188 addfile(f)
3189 3189 return files, dirs
3190 3190
3191 3191 acceptable = ''
3192 3192 if opts['normal']:
3193 3193 acceptable += 'nm'
3194 3194 if opts['added']:
3195 3195 acceptable += 'a'
3196 3196 if opts['removed']:
3197 3197 acceptable += 'r'
3198 3198 cwd = repo.getcwd()
3199 3199 if not specs:
3200 3200 specs = ['.']
3201 3201
3202 3202 files, dirs = set(), set()
3203 3203 for spec in specs:
3204 3204 f, d = complete(spec, acceptable or 'nmar')
3205 3205 files.update(f)
3206 3206 dirs.update(d)
3207 3207 files.update(dirs)
3208 3208 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3209 3209 ui.write('\n')
3210 3210
3211 3211 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3212 3212 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3213 3213 '''access the pushkey key/value protocol
3214 3214
3215 3215 With two args, list the keys in the given namespace.
3216 3216
3217 3217 With five args, set a key to new if it currently is set to old.
3218 3218 Reports success or failure.
3219 3219 '''
3220 3220
3221 3221 target = hg.peer(ui, {}, repopath)
3222 3222 if keyinfo:
3223 3223 key, old, new = keyinfo
3224 3224 r = target.pushkey(namespace, key, old, new)
3225 3225 ui.status(str(r) + '\n')
3226 3226 return not r
3227 3227 else:
3228 3228 for k, v in sorted(target.listkeys(namespace).iteritems()):
3229 3229 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3230 3230 v.encode('string-escape')))
3231 3231
3232 3232 @command('debugpvec', [], _('A B'))
3233 3233 def debugpvec(ui, repo, a, b=None):
3234 3234 ca = scmutil.revsingle(repo, a)
3235 3235 cb = scmutil.revsingle(repo, b)
3236 3236 pa = pvec.ctxpvec(ca)
3237 3237 pb = pvec.ctxpvec(cb)
3238 3238 if pa == pb:
3239 3239 rel = "="
3240 3240 elif pa > pb:
3241 3241 rel = ">"
3242 3242 elif pa < pb:
3243 3243 rel = "<"
3244 3244 elif pa | pb:
3245 3245 rel = "|"
3246 3246 ui.write(_("a: %s\n") % pa)
3247 3247 ui.write(_("b: %s\n") % pb)
3248 3248 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3249 3249 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3250 3250 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3251 3251 pa.distance(pb), rel))
3252 3252
3253 3253 @command('debugrebuilddirstate|debugrebuildstate',
3254 3254 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3255 3255 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3256 3256 'the working copy parent')),
3257 3257 ],
3258 3258 _('[-r REV]'))
3259 3259 def debugrebuilddirstate(ui, repo, rev, **opts):
3260 3260 """rebuild the dirstate as it would look like for the given revision
3261 3261
3262 3262 If no revision is specified the first current parent will be used.
3263 3263
3264 3264 The dirstate will be set to the files of the given revision.
3265 3265 The actual working directory content or existing dirstate
3266 3266 information such as adds or removes is not considered.
3267 3267
3268 3268 ``minimal`` will only rebuild the dirstate status for files that claim to be
3269 3269 tracked but are not in the parent manifest, or that exist in the parent
3270 3270 manifest but are not in the dirstate. It will not change adds, removes, or
3271 3271 modified files that are in the working copy parent.
3272 3272
3273 3273 One use of this command is to make the next :hg:`status` invocation
3274 3274 check the actual file content.
3275 3275 """
3276 3276 ctx = scmutil.revsingle(repo, rev)
3277 3277 with repo.wlock():
3278 3278 dirstate = repo.dirstate
3279 3279 changedfiles = None
3280 3280 # See command doc for what minimal does.
3281 3281 if opts.get('minimal'):
3282 3282 manifestfiles = set(ctx.manifest().keys())
3283 3283 dirstatefiles = set(dirstate)
3284 3284 manifestonly = manifestfiles - dirstatefiles
3285 3285 dsonly = dirstatefiles - manifestfiles
3286 3286 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3287 3287 changedfiles = manifestonly | dsnotadded
3288 3288
3289 3289 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3290 3290
3291 3291 @command('debugrebuildfncache', [], '')
3292 3292 def debugrebuildfncache(ui, repo):
3293 3293 """rebuild the fncache file"""
3294 3294 repair.rebuildfncache(ui, repo)
3295 3295
3296 3296 @command('debugrename',
3297 3297 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3298 3298 _('[-r REV] FILE'))
3299 3299 def debugrename(ui, repo, file1, *pats, **opts):
3300 3300 """dump rename information"""
3301 3301
3302 3302 ctx = scmutil.revsingle(repo, opts.get('rev'))
3303 3303 m = scmutil.match(ctx, (file1,) + pats, opts)
3304 3304 for abs in ctx.walk(m):
3305 3305 fctx = ctx[abs]
3306 3306 o = fctx.filelog().renamed(fctx.filenode())
3307 3307 rel = m.rel(abs)
3308 3308 if o:
3309 3309 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3310 3310 else:
3311 3311 ui.write(_("%s not renamed\n") % rel)
3312 3312
3313 3313 @command('debugrevlog', debugrevlogopts +
3314 3314 [('d', 'dump', False, _('dump index data'))],
3315 3315 _('-c|-m|FILE'),
3316 3316 optionalrepo=True)
3317 3317 def debugrevlog(ui, repo, file_=None, **opts):
3318 3318 """show data and statistics about a revlog"""
3319 3319 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3320 3320
3321 3321 if opts.get("dump"):
3322 3322 numrevs = len(r)
3323 3323 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3324 3324 " rawsize totalsize compression heads chainlen\n")
3325 3325 ts = 0
3326 3326 heads = set()
3327 3327
3328 3328 for rev in xrange(numrevs):
3329 3329 dbase = r.deltaparent(rev)
3330 3330 if dbase == -1:
3331 3331 dbase = rev
3332 3332 cbase = r.chainbase(rev)
3333 3333 clen = r.chainlen(rev)
3334 3334 p1, p2 = r.parentrevs(rev)
3335 3335 rs = r.rawsize(rev)
3336 3336 ts = ts + rs
3337 3337 heads -= set(r.parentrevs(rev))
3338 3338 heads.add(rev)
3339 3339 try:
3340 3340 compression = ts / r.end(rev)
3341 3341 except ZeroDivisionError:
3342 3342 compression = 0
3343 3343 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3344 3344 "%11d %5d %8d\n" %
3345 3345 (rev, p1, p2, r.start(rev), r.end(rev),
3346 3346 r.start(dbase), r.start(cbase),
3347 3347 r.start(p1), r.start(p2),
3348 3348 rs, ts, compression, len(heads), clen))
3349 3349 return 0
3350 3350
3351 3351 v = r.version
3352 3352 format = v & 0xFFFF
3353 3353 flags = []
3354 3354 gdelta = False
3355 3355 if v & revlog.REVLOGNGINLINEDATA:
3356 3356 flags.append('inline')
3357 3357 if v & revlog.REVLOGGENERALDELTA:
3358 3358 gdelta = True
3359 3359 flags.append('generaldelta')
3360 3360 if not flags:
3361 3361 flags = ['(none)']
3362 3362
3363 3363 nummerges = 0
3364 3364 numfull = 0
3365 3365 numprev = 0
3366 3366 nump1 = 0
3367 3367 nump2 = 0
3368 3368 numother = 0
3369 3369 nump1prev = 0
3370 3370 nump2prev = 0
3371 3371 chainlengths = []
3372 3372
3373 3373 datasize = [None, 0, 0L]
3374 3374 fullsize = [None, 0, 0L]
3375 3375 deltasize = [None, 0, 0L]
3376 3376
3377 3377 def addsize(size, l):
3378 3378 if l[0] is None or size < l[0]:
3379 3379 l[0] = size
3380 3380 if size > l[1]:
3381 3381 l[1] = size
3382 3382 l[2] += size
3383 3383
3384 3384 numrevs = len(r)
3385 3385 for rev in xrange(numrevs):
3386 3386 p1, p2 = r.parentrevs(rev)
3387 3387 delta = r.deltaparent(rev)
3388 3388 if format > 0:
3389 3389 addsize(r.rawsize(rev), datasize)
3390 3390 if p2 != nullrev:
3391 3391 nummerges += 1
3392 3392 size = r.length(rev)
3393 3393 if delta == nullrev:
3394 3394 chainlengths.append(0)
3395 3395 numfull += 1
3396 3396 addsize(size, fullsize)
3397 3397 else:
3398 3398 chainlengths.append(chainlengths[delta] + 1)
3399 3399 addsize(size, deltasize)
3400 3400 if delta == rev - 1:
3401 3401 numprev += 1
3402 3402 if delta == p1:
3403 3403 nump1prev += 1
3404 3404 elif delta == p2:
3405 3405 nump2prev += 1
3406 3406 elif delta == p1:
3407 3407 nump1 += 1
3408 3408 elif delta == p2:
3409 3409 nump2 += 1
3410 3410 elif delta != nullrev:
3411 3411 numother += 1
3412 3412
3413 3413 # Adjust size min value for empty cases
3414 3414 for size in (datasize, fullsize, deltasize):
3415 3415 if size[0] is None:
3416 3416 size[0] = 0
3417 3417
3418 3418 numdeltas = numrevs - numfull
3419 3419 numoprev = numprev - nump1prev - nump2prev
3420 3420 totalrawsize = datasize[2]
3421 3421 datasize[2] /= numrevs
3422 3422 fulltotal = fullsize[2]
3423 3423 fullsize[2] /= numfull
3424 3424 deltatotal = deltasize[2]
3425 3425 if numrevs - numfull > 0:
3426 3426 deltasize[2] /= numrevs - numfull
3427 3427 totalsize = fulltotal + deltatotal
3428 3428 avgchainlen = sum(chainlengths) / numrevs
3429 3429 maxchainlen = max(chainlengths)
3430 3430 compratio = 1
3431 3431 if totalsize:
3432 3432 compratio = totalrawsize / totalsize
3433 3433
3434 3434 basedfmtstr = '%%%dd\n'
3435 3435 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3436 3436
3437 3437 def dfmtstr(max):
3438 3438 return basedfmtstr % len(str(max))
3439 3439 def pcfmtstr(max, padding=0):
3440 3440 return basepcfmtstr % (len(str(max)), ' ' * padding)
3441 3441
3442 3442 def pcfmt(value, total):
3443 3443 if total:
3444 3444 return (value, 100 * float(value) / total)
3445 3445 else:
3446 3446 return value, 100.0
3447 3447
3448 3448 ui.write(('format : %d\n') % format)
3449 3449 ui.write(('flags : %s\n') % ', '.join(flags))
3450 3450
3451 3451 ui.write('\n')
3452 3452 fmt = pcfmtstr(totalsize)
3453 3453 fmt2 = dfmtstr(totalsize)
3454 3454 ui.write(('revisions : ') + fmt2 % numrevs)
3455 3455 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3456 3456 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3457 3457 ui.write(('revisions : ') + fmt2 % numrevs)
3458 3458 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3459 3459 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3460 3460 ui.write(('revision size : ') + fmt2 % totalsize)
3461 3461 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3462 3462 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3463 3463
3464 3464 ui.write('\n')
3465 3465 fmt = dfmtstr(max(avgchainlen, compratio))
3466 3466 ui.write(('avg chain length : ') + fmt % avgchainlen)
3467 3467 ui.write(('max chain length : ') + fmt % maxchainlen)
3468 3468 ui.write(('compression ratio : ') + fmt % compratio)
3469 3469
3470 3470 if format > 0:
3471 3471 ui.write('\n')
3472 3472 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3473 3473 % tuple(datasize))
3474 3474 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3475 3475 % tuple(fullsize))
3476 3476 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3477 3477 % tuple(deltasize))
3478 3478
3479 3479 if numdeltas > 0:
3480 3480 ui.write('\n')
3481 3481 fmt = pcfmtstr(numdeltas)
3482 3482 fmt2 = pcfmtstr(numdeltas, 4)
3483 3483 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3484 3484 if numprev > 0:
3485 3485 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3486 3486 numprev))
3487 3487 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3488 3488 numprev))
3489 3489 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3490 3490 numprev))
3491 3491 if gdelta:
3492 3492 ui.write(('deltas against p1 : ')
3493 3493 + fmt % pcfmt(nump1, numdeltas))
3494 3494 ui.write(('deltas against p2 : ')
3495 3495 + fmt % pcfmt(nump2, numdeltas))
3496 3496 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3497 3497 numdeltas))
3498 3498
3499 3499 @command('debugrevspec',
3500 3500 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3501 3501 ('REVSPEC'))
3502 3502 def debugrevspec(ui, repo, expr, **opts):
3503 3503 """parse and apply a revision specification
3504 3504
3505 3505 Use --verbose to print the parsed tree before and after aliases
3506 3506 expansion.
3507 3507 """
3508 3508 if ui.verbose:
3509 3509 tree = revset.parse(expr, lookup=repo.__contains__)
3510 3510 ui.note(revset.prettyformat(tree), "\n")
3511 3511 newtree = revset.expandaliases(ui, tree)
3512 3512 if newtree != tree:
3513 3513 ui.note("* expanded:\n", revset.prettyformat(newtree), "\n")
3514 3514 tree = newtree
3515 3515 newtree = revset.foldconcat(tree)
3516 3516 if newtree != tree:
3517 3517 ui.note("* concatenated:\n", revset.prettyformat(newtree), "\n")
3518 3518 if opts["optimize"]:
3519 3519 weight, optimizedtree = revset.optimize(newtree, True)
3520 3520 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3521 3521 func = revset.match(ui, expr, repo)
3522 3522 revs = func(repo)
3523 3523 if ui.verbose:
3524 3524 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3525 3525 for c in revs:
3526 3526 ui.write("%s\n" % c)
3527 3527
3528 3528 @command('debugsetparents', [], _('REV1 [REV2]'))
3529 3529 def debugsetparents(ui, repo, rev1, rev2=None):
3530 3530 """manually set the parents of the current working directory
3531 3531
3532 3532 This is useful for writing repository conversion tools, but should
3533 3533 be used with care. For example, neither the working directory nor the
3534 3534 dirstate is updated, so file status may be incorrect after running this
3535 3535 command.
3536 3536
3537 3537 Returns 0 on success.
3538 3538 """
3539 3539
3540 3540 r1 = scmutil.revsingle(repo, rev1).node()
3541 3541 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3542 3542
3543 3543 with repo.wlock():
3544 3544 repo.setparents(r1, r2)
3545 3545
3546 3546 @command('debugdirstate|debugstate',
3547 3547 [('', 'nodates', None, _('do not display the saved mtime')),
3548 3548 ('', 'datesort', None, _('sort by saved mtime'))],
3549 3549 _('[OPTION]...'))
3550 3550 def debugstate(ui, repo, **opts):
3551 3551 """show the contents of the current dirstate"""
3552 3552
3553 3553 nodates = opts.get('nodates')
3554 3554 datesort = opts.get('datesort')
3555 3555
3556 3556 timestr = ""
3557 3557 if datesort:
3558 3558 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3559 3559 else:
3560 3560 keyfunc = None # sort by filename
3561 3561 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3562 3562 if ent[3] == -1:
3563 3563 timestr = 'unset '
3564 3564 elif nodates:
3565 3565 timestr = 'set '
3566 3566 else:
3567 3567 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3568 3568 time.localtime(ent[3]))
3569 3569 if ent[1] & 0o20000:
3570 3570 mode = 'lnk'
3571 3571 else:
3572 3572 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3573 3573 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3574 3574 for f in repo.dirstate.copies():
3575 3575 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3576 3576
3577 3577 @command('debugsub',
3578 3578 [('r', 'rev', '',
3579 3579 _('revision to check'), _('REV'))],
3580 3580 _('[-r REV] [REV]'))
3581 3581 def debugsub(ui, repo, rev=None):
3582 3582 ctx = scmutil.revsingle(repo, rev, None)
3583 3583 for k, v in sorted(ctx.substate.items()):
3584 3584 ui.write(('path %s\n') % k)
3585 3585 ui.write((' source %s\n') % v[0])
3586 3586 ui.write((' revision %s\n') % v[1])
3587 3587
3588 3588 @command('debugsuccessorssets',
3589 3589 [],
3590 3590 _('[REV]'))
3591 3591 def debugsuccessorssets(ui, repo, *revs):
3592 3592 """show set of successors for revision
3593 3593
3594 3594 A successors set of changeset A is a consistent group of revisions that
3595 3595 succeed A. It contains non-obsolete changesets only.
3596 3596
3597 3597 In most cases a changeset A has a single successors set containing a single
3598 3598 successor (changeset A replaced by A').
3599 3599
3600 3600 A changeset that is made obsolete with no successors are called "pruned".
3601 3601 Such changesets have no successors sets at all.
3602 3602
3603 3603 A changeset that has been "split" will have a successors set containing
3604 3604 more than one successor.
3605 3605
3606 3606 A changeset that has been rewritten in multiple different ways is called
3607 3607 "divergent". Such changesets have multiple successor sets (each of which
3608 3608 may also be split, i.e. have multiple successors).
3609 3609
3610 3610 Results are displayed as follows::
3611 3611
3612 3612 <rev1>
3613 3613 <successors-1A>
3614 3614 <rev2>
3615 3615 <successors-2A>
3616 3616 <successors-2B1> <successors-2B2> <successors-2B3>
3617 3617
3618 3618 Here rev2 has two possible (i.e. divergent) successors sets. The first
3619 3619 holds one element, whereas the second holds three (i.e. the changeset has
3620 3620 been split).
3621 3621 """
3622 3622 # passed to successorssets caching computation from one call to another
3623 3623 cache = {}
3624 3624 ctx2str = str
3625 3625 node2str = short
3626 3626 if ui.debug():
3627 3627 def ctx2str(ctx):
3628 3628 return ctx.hex()
3629 3629 node2str = hex
3630 3630 for rev in scmutil.revrange(repo, revs):
3631 3631 ctx = repo[rev]
3632 3632 ui.write('%s\n'% ctx2str(ctx))
3633 3633 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3634 3634 if succsset:
3635 3635 ui.write(' ')
3636 3636 ui.write(node2str(succsset[0]))
3637 3637 for node in succsset[1:]:
3638 3638 ui.write(' ')
3639 3639 ui.write(node2str(node))
3640 3640 ui.write('\n')
3641 3641
3642 3642 @command('debugtemplate',
3643 3643 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3644 3644 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3645 3645 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3646 3646 optionalrepo=True)
3647 3647 def debugtemplate(ui, repo, tmpl, **opts):
3648 3648 """parse and apply a template
3649 3649
3650 3650 If -r/--rev is given, the template is processed as a log template and
3651 3651 applied to the given changesets. Otherwise, it is processed as a generic
3652 3652 template.
3653 3653
3654 3654 Use --verbose to print the parsed tree.
3655 3655 """
3656 3656 revs = None
3657 3657 if opts['rev']:
3658 3658 if repo is None:
3659 3659 raise error.RepoError(_('there is no Mercurial repository here '
3660 3660 '(.hg not found)'))
3661 3661 revs = scmutil.revrange(repo, opts['rev'])
3662 3662
3663 3663 props = {}
3664 3664 for d in opts['define']:
3665 3665 try:
3666 3666 k, v = (e.strip() for e in d.split('=', 1))
3667 3667 if not k:
3668 3668 raise ValueError
3669 3669 props[k] = v
3670 3670 except ValueError:
3671 3671 raise error.Abort(_('malformed keyword definition: %s') % d)
3672 3672
3673 3673 if ui.verbose:
3674 3674 tree = templater.parse(tmpl)
3675 3675 ui.note(templater.prettyformat(tree), '\n')
3676 3676
3677 3677 mapfile = None
3678 3678 if revs is None:
3679 3679 k = 'debugtemplate'
3680 3680 t = templater.templater(mapfile)
3681 3681 t.cache[k] = tmpl
3682 3682 ui.write(templater.stringify(t(k, **props)))
3683 3683 else:
3684 3684 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3685 3685 mapfile, buffered=False)
3686 3686 for r in revs:
3687 3687 displayer.show(repo[r], **props)
3688 3688 displayer.close()
3689 3689
3690 3690 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3691 3691 def debugwalk(ui, repo, *pats, **opts):
3692 3692 """show how files match on given patterns"""
3693 3693 m = scmutil.match(repo[None], pats, opts)
3694 3694 items = list(repo.walk(m))
3695 3695 if not items:
3696 3696 return
3697 3697 f = lambda fn: fn
3698 3698 if ui.configbool('ui', 'slash') and os.sep != '/':
3699 3699 f = lambda fn: util.normpath(fn)
3700 3700 fmt = 'f %%-%ds %%-%ds %%s' % (
3701 3701 max([len(abs) for abs in items]),
3702 3702 max([len(m.rel(abs)) for abs in items]))
3703 3703 for abs in items:
3704 3704 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3705 3705 ui.write("%s\n" % line.rstrip())
3706 3706
3707 3707 @command('debugwireargs',
3708 3708 [('', 'three', '', 'three'),
3709 3709 ('', 'four', '', 'four'),
3710 3710 ('', 'five', '', 'five'),
3711 3711 ] + remoteopts,
3712 3712 _('REPO [OPTIONS]... [ONE [TWO]]'),
3713 3713 norepo=True)
3714 3714 def debugwireargs(ui, repopath, *vals, **opts):
3715 3715 repo = hg.peer(ui, opts, repopath)
3716 3716 for opt in remoteopts:
3717 3717 del opts[opt[1]]
3718 3718 args = {}
3719 3719 for k, v in opts.iteritems():
3720 3720 if v:
3721 3721 args[k] = v
3722 3722 # run twice to check that we don't mess up the stream for the next command
3723 3723 res1 = repo.debugwireargs(*vals, **args)
3724 3724 res2 = repo.debugwireargs(*vals, **args)
3725 3725 ui.write("%s\n" % res1)
3726 3726 if res1 != res2:
3727 3727 ui.warn("%s\n" % res2)
3728 3728
3729 3729 @command('^diff',
3730 3730 [('r', 'rev', [], _('revision'), _('REV')),
3731 3731 ('c', 'change', '', _('change made by revision'), _('REV'))
3732 3732 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3733 3733 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3734 3734 inferrepo=True)
3735 3735 def diff(ui, repo, *pats, **opts):
3736 3736 """diff repository (or selected files)
3737 3737
3738 3738 Show differences between revisions for the specified files.
3739 3739
3740 3740 Differences between files are shown using the unified diff format.
3741 3741
3742 3742 .. note::
3743 3743
3744 3744 :hg:`diff` may generate unexpected results for merges, as it will
3745 3745 default to comparing against the working directory's first
3746 3746 parent changeset if no revisions are specified.
3747 3747
3748 3748 When two revision arguments are given, then changes are shown
3749 3749 between those revisions. If only one revision is specified then
3750 3750 that revision is compared to the working directory, and, when no
3751 3751 revisions are specified, the working directory files are compared
3752 3752 to its first parent.
3753 3753
3754 3754 Alternatively you can specify -c/--change with a revision to see
3755 3755 the changes in that changeset relative to its first parent.
3756 3756
3757 3757 Without the -a/--text option, diff will avoid generating diffs of
3758 3758 files it detects as binary. With -a, diff will generate a diff
3759 3759 anyway, probably with undesirable results.
3760 3760
3761 3761 Use the -g/--git option to generate diffs in the git extended diff
3762 3762 format. For more information, read :hg:`help diffs`.
3763 3763
3764 3764 .. container:: verbose
3765 3765
3766 3766 Examples:
3767 3767
3768 3768 - compare a file in the current working directory to its parent::
3769 3769
3770 3770 hg diff foo.c
3771 3771
3772 3772 - compare two historical versions of a directory, with rename info::
3773 3773
3774 3774 hg diff --git -r 1.0:1.2 lib/
3775 3775
3776 3776 - get change stats relative to the last change on some date::
3777 3777
3778 3778 hg diff --stat -r "date('may 2')"
3779 3779
3780 3780 - diff all newly-added files that contain a keyword::
3781 3781
3782 3782 hg diff "set:added() and grep(GNU)"
3783 3783
3784 3784 - compare a revision and its parents::
3785 3785
3786 3786 hg diff -c 9353 # compare against first parent
3787 3787 hg diff -r 9353^:9353 # same using revset syntax
3788 3788 hg diff -r 9353^2:9353 # compare against the second parent
3789 3789
3790 3790 Returns 0 on success.
3791 3791 """
3792 3792
3793 3793 revs = opts.get('rev')
3794 3794 change = opts.get('change')
3795 3795 stat = opts.get('stat')
3796 3796 reverse = opts.get('reverse')
3797 3797
3798 3798 if revs and change:
3799 3799 msg = _('cannot specify --rev and --change at the same time')
3800 3800 raise error.Abort(msg)
3801 3801 elif change:
3802 3802 node2 = scmutil.revsingle(repo, change, None).node()
3803 3803 node1 = repo[node2].p1().node()
3804 3804 else:
3805 3805 node1, node2 = scmutil.revpair(repo, revs)
3806 3806
3807 3807 if reverse:
3808 3808 node1, node2 = node2, node1
3809 3809
3810 3810 diffopts = patch.diffallopts(ui, opts)
3811 3811 m = scmutil.match(repo[node2], pats, opts)
3812 3812 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3813 3813 listsubrepos=opts.get('subrepos'),
3814 3814 root=opts.get('root'))
3815 3815
3816 3816 @command('^export',
3817 3817 [('o', 'output', '',
3818 3818 _('print output to file with formatted name'), _('FORMAT')),
3819 3819 ('', 'switch-parent', None, _('diff against the second parent')),
3820 3820 ('r', 'rev', [], _('revisions to export'), _('REV')),
3821 3821 ] + diffopts,
3822 3822 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3823 3823 def export(ui, repo, *changesets, **opts):
3824 3824 """dump the header and diffs for one or more changesets
3825 3825
3826 3826 Print the changeset header and diffs for one or more revisions.
3827 3827 If no revision is given, the parent of the working directory is used.
3828 3828
3829 3829 The information shown in the changeset header is: author, date,
3830 3830 branch name (if non-default), changeset hash, parent(s) and commit
3831 3831 comment.
3832 3832
3833 3833 .. note::
3834 3834
3835 3835 :hg:`export` may generate unexpected diff output for merge
3836 3836 changesets, as it will compare the merge changeset against its
3837 3837 first parent only.
3838 3838
3839 3839 Output may be to a file, in which case the name of the file is
3840 3840 given using a format string. The formatting rules are as follows:
3841 3841
3842 3842 :``%%``: literal "%" character
3843 3843 :``%H``: changeset hash (40 hexadecimal digits)
3844 3844 :``%N``: number of patches being generated
3845 3845 :``%R``: changeset revision number
3846 3846 :``%b``: basename of the exporting repository
3847 3847 :``%h``: short-form changeset hash (12 hexadecimal digits)
3848 3848 :``%m``: first line of the commit message (only alphanumeric characters)
3849 3849 :``%n``: zero-padded sequence number, starting at 1
3850 3850 :``%r``: zero-padded changeset revision number
3851 3851
3852 3852 Without the -a/--text option, export will avoid generating diffs
3853 3853 of files it detects as binary. With -a, export will generate a
3854 3854 diff anyway, probably with undesirable results.
3855 3855
3856 3856 Use the -g/--git option to generate diffs in the git extended diff
3857 3857 format. See :hg:`help diffs` for more information.
3858 3858
3859 3859 With the --switch-parent option, the diff will be against the
3860 3860 second parent. It can be useful to review a merge.
3861 3861
3862 3862 .. container:: verbose
3863 3863
3864 3864 Examples:
3865 3865
3866 3866 - use export and import to transplant a bugfix to the current
3867 3867 branch::
3868 3868
3869 3869 hg export -r 9353 | hg import -
3870 3870
3871 3871 - export all the changesets between two revisions to a file with
3872 3872 rename information::
3873 3873
3874 3874 hg export --git -r 123:150 > changes.txt
3875 3875
3876 3876 - split outgoing changes into a series of patches with
3877 3877 descriptive names::
3878 3878
3879 3879 hg export -r "outgoing()" -o "%n-%m.patch"
3880 3880
3881 3881 Returns 0 on success.
3882 3882 """
3883 3883 changesets += tuple(opts.get('rev', []))
3884 3884 if not changesets:
3885 3885 changesets = ['.']
3886 3886 revs = scmutil.revrange(repo, changesets)
3887 3887 if not revs:
3888 3888 raise error.Abort(_("export requires at least one changeset"))
3889 3889 if len(revs) > 1:
3890 3890 ui.note(_('exporting patches:\n'))
3891 3891 else:
3892 3892 ui.note(_('exporting patch:\n'))
3893 3893 cmdutil.export(repo, revs, template=opts.get('output'),
3894 3894 switch_parent=opts.get('switch_parent'),
3895 3895 opts=patch.diffallopts(ui, opts))
3896 3896
3897 3897 @command('files',
3898 3898 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3899 3899 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3900 3900 ] + walkopts + formatteropts + subrepoopts,
3901 3901 _('[OPTION]... [PATTERN]...'))
3902 3902 def files(ui, repo, *pats, **opts):
3903 3903 """list tracked files
3904 3904
3905 3905 Print files under Mercurial control in the working directory or
3906 3906 specified revision whose names match the given patterns (excluding
3907 3907 removed files).
3908 3908
3909 3909 If no patterns are given to match, this command prints the names
3910 3910 of all files under Mercurial control in the working directory.
3911 3911
3912 3912 .. container:: verbose
3913 3913
3914 3914 Examples:
3915 3915
3916 3916 - list all files under the current directory::
3917 3917
3918 3918 hg files .
3919 3919
3920 3920 - shows sizes and flags for current revision::
3921 3921
3922 3922 hg files -vr .
3923 3923
3924 3924 - list all files named README::
3925 3925
3926 3926 hg files -I "**/README"
3927 3927
3928 3928 - list all binary files::
3929 3929
3930 3930 hg files "set:binary()"
3931 3931
3932 3932 - find files containing a regular expression::
3933 3933
3934 3934 hg files "set:grep('bob')"
3935 3935
3936 3936 - search tracked file contents with xargs and grep::
3937 3937
3938 3938 hg files -0 | xargs -0 grep foo
3939 3939
3940 3940 See :hg:`help patterns` and :hg:`help filesets` for more information
3941 3941 on specifying file patterns.
3942 3942
3943 3943 Returns 0 if a match is found, 1 otherwise.
3944 3944
3945 3945 """
3946 3946 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3947 3947
3948 3948 end = '\n'
3949 3949 if opts.get('print0'):
3950 3950 end = '\0'
3951 3951 fm = ui.formatter('files', opts)
3952 3952 fmt = '%s' + end
3953 3953
3954 3954 m = scmutil.match(ctx, pats, opts)
3955 3955 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3956 3956
3957 3957 fm.end()
3958 3958
3959 3959 return ret
3960 3960
3961 3961 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3962 3962 def forget(ui, repo, *pats, **opts):
3963 3963 """forget the specified files on the next commit
3964 3964
3965 3965 Mark the specified files so they will no longer be tracked
3966 3966 after the next commit.
3967 3967
3968 3968 This only removes files from the current branch, not from the
3969 3969 entire project history, and it does not delete them from the
3970 3970 working directory.
3971 3971
3972 3972 To delete the file from the working directory, see :hg:`remove`.
3973 3973
3974 3974 To undo a forget before the next commit, see :hg:`add`.
3975 3975
3976 3976 .. container:: verbose
3977 3977
3978 3978 Examples:
3979 3979
3980 3980 - forget newly-added binary files::
3981 3981
3982 3982 hg forget "set:added() and binary()"
3983 3983
3984 3984 - forget files that would be excluded by .hgignore::
3985 3985
3986 3986 hg forget "set:hgignore()"
3987 3987
3988 3988 Returns 0 on success.
3989 3989 """
3990 3990
3991 3991 if not pats:
3992 3992 raise error.Abort(_('no files specified'))
3993 3993
3994 3994 m = scmutil.match(repo[None], pats, opts)
3995 3995 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3996 3996 return rejected and 1 or 0
3997 3997
3998 3998 @command(
3999 3999 'graft',
4000 4000 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4001 4001 ('c', 'continue', False, _('resume interrupted graft')),
4002 4002 ('e', 'edit', False, _('invoke editor on commit messages')),
4003 4003 ('', 'log', None, _('append graft info to log message')),
4004 4004 ('f', 'force', False, _('force graft')),
4005 4005 ('D', 'currentdate', False,
4006 4006 _('record the current date as commit date')),
4007 4007 ('U', 'currentuser', False,
4008 4008 _('record the current user as committer'), _('DATE'))]
4009 4009 + commitopts2 + mergetoolopts + dryrunopts,
4010 4010 _('[OPTION]... [-r REV]... REV...'))
4011 4011 def graft(ui, repo, *revs, **opts):
4012 4012 '''copy changes from other branches onto the current branch
4013 4013
4014 4014 This command uses Mercurial's merge logic to copy individual
4015 4015 changes from other branches without merging branches in the
4016 4016 history graph. This is sometimes known as 'backporting' or
4017 4017 'cherry-picking'. By default, graft will copy user, date, and
4018 4018 description from the source changesets.
4019 4019
4020 4020 Changesets that are ancestors of the current revision, that have
4021 4021 already been grafted, or that are merges will be skipped.
4022 4022
4023 4023 If --log is specified, log messages will have a comment appended
4024 4024 of the form::
4025 4025
4026 4026 (grafted from CHANGESETHASH)
4027 4027
4028 4028 If --force is specified, revisions will be grafted even if they
4029 4029 are already ancestors of or have been grafted to the destination.
4030 4030 This is useful when the revisions have since been backed out.
4031 4031
4032 4032 If a graft merge results in conflicts, the graft process is
4033 4033 interrupted so that the current merge can be manually resolved.
4034 4034 Once all conflicts are addressed, the graft process can be
4035 4035 continued with the -c/--continue option.
4036 4036
4037 4037 .. note::
4038 4038
4039 4039 The -c/--continue option does not reapply earlier options, except
4040 4040 for --force.
4041 4041
4042 4042 .. container:: verbose
4043 4043
4044 4044 Examples:
4045 4045
4046 4046 - copy a single change to the stable branch and edit its description::
4047 4047
4048 4048 hg update stable
4049 4049 hg graft --edit 9393
4050 4050
4051 4051 - graft a range of changesets with one exception, updating dates::
4052 4052
4053 4053 hg graft -D "2085::2093 and not 2091"
4054 4054
4055 4055 - continue a graft after resolving conflicts::
4056 4056
4057 4057 hg graft -c
4058 4058
4059 4059 - show the source of a grafted changeset::
4060 4060
4061 4061 hg log --debug -r .
4062 4062
4063 4063 - show revisions sorted by date::
4064 4064
4065 4065 hg log -r "sort(all(), date)"
4066 4066
4067 4067 See :hg:`help revisions` and :hg:`help revsets` for more about
4068 4068 specifying revisions.
4069 4069
4070 4070 Returns 0 on successful completion.
4071 4071 '''
4072 4072 with repo.wlock():
4073 4073 return _dograft(ui, repo, *revs, **opts)
4074 4074
4075 4075 def _dograft(ui, repo, *revs, **opts):
4076 4076 if revs and opts['rev']:
4077 4077 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4078 4078 'revision ordering!\n'))
4079 4079
4080 4080 revs = list(revs)
4081 4081 revs.extend(opts['rev'])
4082 4082
4083 4083 if not opts.get('user') and opts.get('currentuser'):
4084 4084 opts['user'] = ui.username()
4085 4085 if not opts.get('date') and opts.get('currentdate'):
4086 4086 opts['date'] = "%d %d" % util.makedate()
4087 4087
4088 4088 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4089 4089
4090 4090 cont = False
4091 4091 if opts['continue']:
4092 4092 cont = True
4093 4093 if revs:
4094 4094 raise error.Abort(_("can't specify --continue and revisions"))
4095 4095 # read in unfinished revisions
4096 4096 try:
4097 4097 nodes = repo.vfs.read('graftstate').splitlines()
4098 4098 revs = [repo[node].rev() for node in nodes]
4099 4099 except IOError as inst:
4100 4100 if inst.errno != errno.ENOENT:
4101 4101 raise
4102 4102 cmdutil.wrongtooltocontinue(repo, _('graft'))
4103 4103 else:
4104 4104 cmdutil.checkunfinished(repo)
4105 4105 cmdutil.bailifchanged(repo)
4106 4106 if not revs:
4107 4107 raise error.Abort(_('no revisions specified'))
4108 4108 revs = scmutil.revrange(repo, revs)
4109 4109
4110 4110 skipped = set()
4111 4111 # check for merges
4112 4112 for rev in repo.revs('%ld and merge()', revs):
4113 4113 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4114 4114 skipped.add(rev)
4115 4115 revs = [r for r in revs if r not in skipped]
4116 4116 if not revs:
4117 4117 return -1
4118 4118
4119 4119 # Don't check in the --continue case, in effect retaining --force across
4120 4120 # --continues. That's because without --force, any revisions we decided to
4121 4121 # skip would have been filtered out here, so they wouldn't have made their
4122 4122 # way to the graftstate. With --force, any revisions we would have otherwise
4123 4123 # skipped would not have been filtered out, and if they hadn't been applied
4124 4124 # already, they'd have been in the graftstate.
4125 4125 if not (cont or opts.get('force')):
4126 4126 # check for ancestors of dest branch
4127 4127 crev = repo['.'].rev()
4128 4128 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4129 4129 # Cannot use x.remove(y) on smart set, this has to be a list.
4130 4130 # XXX make this lazy in the future
4131 4131 revs = list(revs)
4132 4132 # don't mutate while iterating, create a copy
4133 4133 for rev in list(revs):
4134 4134 if rev in ancestors:
4135 4135 ui.warn(_('skipping ancestor revision %d:%s\n') %
4136 4136 (rev, repo[rev]))
4137 4137 # XXX remove on list is slow
4138 4138 revs.remove(rev)
4139 4139 if not revs:
4140 4140 return -1
4141 4141
4142 4142 # analyze revs for earlier grafts
4143 4143 ids = {}
4144 4144 for ctx in repo.set("%ld", revs):
4145 4145 ids[ctx.hex()] = ctx.rev()
4146 4146 n = ctx.extra().get('source')
4147 4147 if n:
4148 4148 ids[n] = ctx.rev()
4149 4149
4150 4150 # check ancestors for earlier grafts
4151 4151 ui.debug('scanning for duplicate grafts\n')
4152 4152
4153 4153 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4154 4154 ctx = repo[rev]
4155 4155 n = ctx.extra().get('source')
4156 4156 if n in ids:
4157 4157 try:
4158 4158 r = repo[n].rev()
4159 4159 except error.RepoLookupError:
4160 4160 r = None
4161 4161 if r in revs:
4162 4162 ui.warn(_('skipping revision %d:%s '
4163 4163 '(already grafted to %d:%s)\n')
4164 4164 % (r, repo[r], rev, ctx))
4165 4165 revs.remove(r)
4166 4166 elif ids[n] in revs:
4167 4167 if r is None:
4168 4168 ui.warn(_('skipping already grafted revision %d:%s '
4169 4169 '(%d:%s also has unknown origin %s)\n')
4170 4170 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4171 4171 else:
4172 4172 ui.warn(_('skipping already grafted revision %d:%s '
4173 4173 '(%d:%s also has origin %d:%s)\n')
4174 4174 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4175 4175 revs.remove(ids[n])
4176 4176 elif ctx.hex() in ids:
4177 4177 r = ids[ctx.hex()]
4178 4178 ui.warn(_('skipping already grafted revision %d:%s '
4179 4179 '(was grafted from %d:%s)\n') %
4180 4180 (r, repo[r], rev, ctx))
4181 4181 revs.remove(r)
4182 4182 if not revs:
4183 4183 return -1
4184 4184
4185 4185 for pos, ctx in enumerate(repo.set("%ld", revs)):
4186 4186 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4187 4187 ctx.description().split('\n', 1)[0])
4188 4188 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4189 4189 if names:
4190 4190 desc += ' (%s)' % ' '.join(names)
4191 4191 ui.status(_('grafting %s\n') % desc)
4192 4192 if opts.get('dry_run'):
4193 4193 continue
4194 4194
4195 4195 source = ctx.extra().get('source')
4196 4196 extra = {}
4197 4197 if source:
4198 4198 extra['source'] = source
4199 4199 extra['intermediate-source'] = ctx.hex()
4200 4200 else:
4201 4201 extra['source'] = ctx.hex()
4202 4202 user = ctx.user()
4203 4203 if opts.get('user'):
4204 4204 user = opts['user']
4205 4205 date = ctx.date()
4206 4206 if opts.get('date'):
4207 4207 date = opts['date']
4208 4208 message = ctx.description()
4209 4209 if opts.get('log'):
4210 4210 message += '\n(grafted from %s)' % ctx.hex()
4211 4211
4212 4212 # we don't merge the first commit when continuing
4213 4213 if not cont:
4214 4214 # perform the graft merge with p1(rev) as 'ancestor'
4215 4215 try:
4216 4216 # ui.forcemerge is an internal variable, do not document
4217 4217 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4218 4218 'graft')
4219 4219 stats = mergemod.graft(repo, ctx, ctx.p1(),
4220 4220 ['local', 'graft'])
4221 4221 finally:
4222 4222 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4223 4223 # report any conflicts
4224 4224 if stats and stats[3] > 0:
4225 4225 # write out state for --continue
4226 4226 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4227 4227 repo.vfs.write('graftstate', ''.join(nodelines))
4228 4228 extra = ''
4229 4229 if opts.get('user'):
4230 4230 extra += ' --user %s' % opts['user']
4231 4231 if opts.get('date'):
4232 4232 extra += ' --date %s' % opts['date']
4233 4233 if opts.get('log'):
4234 4234 extra += ' --log'
4235 4235 hint=_('use hg resolve and hg graft --continue%s') % extra
4236 4236 raise error.Abort(
4237 4237 _("unresolved conflicts, can't continue"),
4238 4238 hint=hint)
4239 4239 else:
4240 4240 cont = False
4241 4241
4242 4242 # commit
4243 4243 node = repo.commit(text=message, user=user,
4244 4244 date=date, extra=extra, editor=editor)
4245 4245 if node is None:
4246 4246 ui.warn(
4247 4247 _('note: graft of %d:%s created no changes to commit\n') %
4248 4248 (ctx.rev(), ctx))
4249 4249
4250 4250 # remove state when we complete successfully
4251 4251 if not opts.get('dry_run'):
4252 4252 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4253 4253
4254 4254 return 0
4255 4255
4256 4256 @command('grep',
4257 4257 [('0', 'print0', None, _('end fields with NUL')),
4258 4258 ('', 'all', None, _('print all revisions that match')),
4259 4259 ('a', 'text', None, _('treat all files as text')),
4260 4260 ('f', 'follow', None,
4261 4261 _('follow changeset history,'
4262 4262 ' or file history across copies and renames')),
4263 4263 ('i', 'ignore-case', None, _('ignore case when matching')),
4264 4264 ('l', 'files-with-matches', None,
4265 4265 _('print only filenames and revisions that match')),
4266 4266 ('n', 'line-number', None, _('print matching line numbers')),
4267 4267 ('r', 'rev', [],
4268 4268 _('only search files changed within revision range'), _('REV')),
4269 4269 ('u', 'user', None, _('list the author (long with -v)')),
4270 4270 ('d', 'date', None, _('list the date (short with -q)')),
4271 4271 ] + walkopts,
4272 4272 _('[OPTION]... PATTERN [FILE]...'),
4273 4273 inferrepo=True)
4274 4274 def grep(ui, repo, pattern, *pats, **opts):
4275 4275 """search for a pattern in specified files and revisions
4276 4276
4277 4277 Search revisions of files for a regular expression.
4278 4278
4279 4279 This command behaves differently than Unix grep. It only accepts
4280 4280 Python/Perl regexps. It searches repository history, not the
4281 4281 working directory. It always prints the revision number in which a
4282 4282 match appears.
4283 4283
4284 4284 By default, grep only prints output for the first revision of a
4285 4285 file in which it finds a match. To get it to print every revision
4286 4286 that contains a change in match status ("-" for a match that
4287 4287 becomes a non-match, or "+" for a non-match that becomes a match),
4288 4288 use the --all flag.
4289 4289
4290 4290 Returns 0 if a match is found, 1 otherwise.
4291 4291 """
4292 4292 reflags = re.M
4293 4293 if opts.get('ignore_case'):
4294 4294 reflags |= re.I
4295 4295 try:
4296 4296 regexp = util.re.compile(pattern, reflags)
4297 4297 except re.error as inst:
4298 4298 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4299 4299 return 1
4300 4300 sep, eol = ':', '\n'
4301 4301 if opts.get('print0'):
4302 4302 sep = eol = '\0'
4303 4303
4304 4304 getfile = util.lrucachefunc(repo.file)
4305 4305
4306 4306 def matchlines(body):
4307 4307 begin = 0
4308 4308 linenum = 0
4309 4309 while begin < len(body):
4310 4310 match = regexp.search(body, begin)
4311 4311 if not match:
4312 4312 break
4313 4313 mstart, mend = match.span()
4314 4314 linenum += body.count('\n', begin, mstart) + 1
4315 4315 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4316 4316 begin = body.find('\n', mend) + 1 or len(body) + 1
4317 4317 lend = begin - 1
4318 4318 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4319 4319
4320 4320 class linestate(object):
4321 4321 def __init__(self, line, linenum, colstart, colend):
4322 4322 self.line = line
4323 4323 self.linenum = linenum
4324 4324 self.colstart = colstart
4325 4325 self.colend = colend
4326 4326
4327 4327 def __hash__(self):
4328 4328 return hash((self.linenum, self.line))
4329 4329
4330 4330 def __eq__(self, other):
4331 4331 return self.line == other.line
4332 4332
4333 4333 def __iter__(self):
4334 4334 yield (self.line[:self.colstart], '')
4335 4335 yield (self.line[self.colstart:self.colend], 'grep.match')
4336 4336 rest = self.line[self.colend:]
4337 4337 while rest != '':
4338 4338 match = regexp.search(rest)
4339 4339 if not match:
4340 4340 yield (rest, '')
4341 4341 break
4342 4342 mstart, mend = match.span()
4343 4343 yield (rest[:mstart], '')
4344 4344 yield (rest[mstart:mend], 'grep.match')
4345 4345 rest = rest[mend:]
4346 4346
4347 4347 matches = {}
4348 4348 copies = {}
4349 4349 def grepbody(fn, rev, body):
4350 4350 matches[rev].setdefault(fn, [])
4351 4351 m = matches[rev][fn]
4352 4352 for lnum, cstart, cend, line in matchlines(body):
4353 4353 s = linestate(line, lnum, cstart, cend)
4354 4354 m.append(s)
4355 4355
4356 4356 def difflinestates(a, b):
4357 4357 sm = difflib.SequenceMatcher(None, a, b)
4358 4358 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4359 4359 if tag == 'insert':
4360 4360 for i in xrange(blo, bhi):
4361 4361 yield ('+', b[i])
4362 4362 elif tag == 'delete':
4363 4363 for i in xrange(alo, ahi):
4364 4364 yield ('-', a[i])
4365 4365 elif tag == 'replace':
4366 4366 for i in xrange(alo, ahi):
4367 4367 yield ('-', a[i])
4368 4368 for i in xrange(blo, bhi):
4369 4369 yield ('+', b[i])
4370 4370
4371 4371 def display(fn, ctx, pstates, states):
4372 4372 rev = ctx.rev()
4373 4373 if ui.quiet:
4374 4374 datefunc = util.shortdate
4375 4375 else:
4376 4376 datefunc = util.datestr
4377 4377 found = False
4378 4378 @util.cachefunc
4379 4379 def binary():
4380 4380 flog = getfile(fn)
4381 4381 return util.binary(flog.read(ctx.filenode(fn)))
4382 4382
4383 4383 if opts.get('all'):
4384 4384 iter = difflinestates(pstates, states)
4385 4385 else:
4386 4386 iter = [('', l) for l in states]
4387 4387 for change, l in iter:
4388 4388 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4389 4389
4390 4390 if opts.get('line_number'):
4391 4391 cols.append((str(l.linenum), 'grep.linenumber'))
4392 4392 if opts.get('all'):
4393 4393 cols.append((change, 'grep.change'))
4394 4394 if opts.get('user'):
4395 4395 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4396 4396 if opts.get('date'):
4397 4397 cols.append((datefunc(ctx.date()), 'grep.date'))
4398 4398 for col, label in cols[:-1]:
4399 4399 ui.write(col, label=label)
4400 4400 ui.write(sep, label='grep.sep')
4401 4401 ui.write(cols[-1][0], label=cols[-1][1])
4402 4402 if not opts.get('files_with_matches'):
4403 4403 ui.write(sep, label='grep.sep')
4404 4404 if not opts.get('text') and binary():
4405 4405 ui.write(" Binary file matches")
4406 4406 else:
4407 4407 for s, label in l:
4408 4408 ui.write(s, label=label)
4409 4409 ui.write(eol)
4410 4410 found = True
4411 4411 if opts.get('files_with_matches'):
4412 4412 break
4413 4413 return found
4414 4414
4415 4415 skip = {}
4416 4416 revfiles = {}
4417 4417 matchfn = scmutil.match(repo[None], pats, opts)
4418 4418 found = False
4419 4419 follow = opts.get('follow')
4420 4420
4421 4421 def prep(ctx, fns):
4422 4422 rev = ctx.rev()
4423 4423 pctx = ctx.p1()
4424 4424 parent = pctx.rev()
4425 4425 matches.setdefault(rev, {})
4426 4426 matches.setdefault(parent, {})
4427 4427 files = revfiles.setdefault(rev, [])
4428 4428 for fn in fns:
4429 4429 flog = getfile(fn)
4430 4430 try:
4431 4431 fnode = ctx.filenode(fn)
4432 4432 except error.LookupError:
4433 4433 continue
4434 4434
4435 4435 copied = flog.renamed(fnode)
4436 4436 copy = follow and copied and copied[0]
4437 4437 if copy:
4438 4438 copies.setdefault(rev, {})[fn] = copy
4439 4439 if fn in skip:
4440 4440 if copy:
4441 4441 skip[copy] = True
4442 4442 continue
4443 4443 files.append(fn)
4444 4444
4445 4445 if fn not in matches[rev]:
4446 4446 grepbody(fn, rev, flog.read(fnode))
4447 4447
4448 4448 pfn = copy or fn
4449 4449 if pfn not in matches[parent]:
4450 4450 try:
4451 4451 fnode = pctx.filenode(pfn)
4452 4452 grepbody(pfn, parent, flog.read(fnode))
4453 4453 except error.LookupError:
4454 4454 pass
4455 4455
4456 4456 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4457 4457 rev = ctx.rev()
4458 4458 parent = ctx.p1().rev()
4459 4459 for fn in sorted(revfiles.get(rev, [])):
4460 4460 states = matches[rev][fn]
4461 4461 copy = copies.get(rev, {}).get(fn)
4462 4462 if fn in skip:
4463 4463 if copy:
4464 4464 skip[copy] = True
4465 4465 continue
4466 4466 pstates = matches.get(parent, {}).get(copy or fn, [])
4467 4467 if pstates or states:
4468 4468 r = display(fn, ctx, pstates, states)
4469 4469 found = found or r
4470 4470 if r and not opts.get('all'):
4471 4471 skip[fn] = True
4472 4472 if copy:
4473 4473 skip[copy] = True
4474 4474 del matches[rev]
4475 4475 del revfiles[rev]
4476 4476
4477 4477 return not found
4478 4478
4479 4479 @command('heads',
4480 4480 [('r', 'rev', '',
4481 4481 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4482 4482 ('t', 'topo', False, _('show topological heads only')),
4483 4483 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4484 4484 ('c', 'closed', False, _('show normal and closed branch heads')),
4485 4485 ] + templateopts,
4486 4486 _('[-ct] [-r STARTREV] [REV]...'))
4487 4487 def heads(ui, repo, *branchrevs, **opts):
4488 4488 """show branch heads
4489 4489
4490 4490 With no arguments, show all open branch heads in the repository.
4491 4491 Branch heads are changesets that have no descendants on the
4492 4492 same branch. They are where development generally takes place and
4493 4493 are the usual targets for update and merge operations.
4494 4494
4495 4495 If one or more REVs are given, only open branch heads on the
4496 4496 branches associated with the specified changesets are shown. This
4497 4497 means that you can use :hg:`heads .` to see the heads on the
4498 4498 currently checked-out branch.
4499 4499
4500 4500 If -c/--closed is specified, also show branch heads marked closed
4501 4501 (see :hg:`commit --close-branch`).
4502 4502
4503 4503 If STARTREV is specified, only those heads that are descendants of
4504 4504 STARTREV will be displayed.
4505 4505
4506 4506 If -t/--topo is specified, named branch mechanics will be ignored and only
4507 4507 topological heads (changesets with no children) will be shown.
4508 4508
4509 4509 Returns 0 if matching heads are found, 1 if not.
4510 4510 """
4511 4511
4512 4512 start = None
4513 4513 if 'rev' in opts:
4514 4514 start = scmutil.revsingle(repo, opts['rev'], None).node()
4515 4515
4516 4516 if opts.get('topo'):
4517 4517 heads = [repo[h] for h in repo.heads(start)]
4518 4518 else:
4519 4519 heads = []
4520 4520 for branch in repo.branchmap():
4521 4521 heads += repo.branchheads(branch, start, opts.get('closed'))
4522 4522 heads = [repo[h] for h in heads]
4523 4523
4524 4524 if branchrevs:
4525 4525 branches = set(repo[br].branch() for br in branchrevs)
4526 4526 heads = [h for h in heads if h.branch() in branches]
4527 4527
4528 4528 if opts.get('active') and branchrevs:
4529 4529 dagheads = repo.heads(start)
4530 4530 heads = [h for h in heads if h.node() in dagheads]
4531 4531
4532 4532 if branchrevs:
4533 4533 haveheads = set(h.branch() for h in heads)
4534 4534 if branches - haveheads:
4535 4535 headless = ', '.join(b for b in branches - haveheads)
4536 4536 msg = _('no open branch heads found on branches %s')
4537 4537 if opts.get('rev'):
4538 4538 msg += _(' (started at %s)') % opts['rev']
4539 4539 ui.warn((msg + '\n') % headless)
4540 4540
4541 4541 if not heads:
4542 4542 return 1
4543 4543
4544 4544 heads = sorted(heads, key=lambda x: -x.rev())
4545 4545 displayer = cmdutil.show_changeset(ui, repo, opts)
4546 4546 for ctx in heads:
4547 4547 displayer.show(ctx)
4548 4548 displayer.close()
4549 4549
4550 4550 @command('help',
4551 4551 [('e', 'extension', None, _('show only help for extensions')),
4552 4552 ('c', 'command', None, _('show only help for commands')),
4553 4553 ('k', 'keyword', None, _('show topics matching keyword')),
4554 4554 ('s', 'system', [], _('show help for specific platform(s)')),
4555 4555 ],
4556 4556 _('[-ecks] [TOPIC]'),
4557 4557 norepo=True)
4558 4558 def help_(ui, name=None, **opts):
4559 4559 """show help for a given topic or a help overview
4560 4560
4561 4561 With no arguments, print a list of commands with short help messages.
4562 4562
4563 4563 Given a topic, extension, or command name, print help for that
4564 4564 topic.
4565 4565
4566 4566 Returns 0 if successful.
4567 4567 """
4568 4568
4569 4569 textwidth = min(ui.termwidth(), 80) - 2
4570 4570
4571 4571 keep = opts.get('system') or []
4572 4572 if len(keep) == 0:
4573 4573 if sys.platform.startswith('win'):
4574 4574 keep.append('windows')
4575 4575 elif sys.platform == 'OpenVMS':
4576 4576 keep.append('vms')
4577 4577 elif sys.platform == 'plan9':
4578 4578 keep.append('plan9')
4579 4579 else:
4580 4580 keep.append('unix')
4581 4581 keep.append(sys.platform.lower())
4582 4582 if ui.verbose:
4583 4583 keep.append('verbose')
4584 4584
4585 4585 section = None
4586 4586 subtopic = None
4587 4587 if name and '.' in name:
4588 4588 name, section = name.split('.', 1)
4589 4589 section = section.lower()
4590 4590 if '.' in section:
4591 4591 subtopic, section = section.split('.', 1)
4592 4592 else:
4593 4593 subtopic = section
4594 4594
4595 4595 text = help.help_(ui, name, subtopic=subtopic, **opts)
4596 4596
4597 4597 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4598 4598 section=section)
4599 4599
4600 4600 # We could have been given a weird ".foo" section without a name
4601 4601 # to look for, or we could have simply failed to found "foo.bar"
4602 4602 # because bar isn't a section of foo
4603 4603 if section and not (formatted and name):
4604 4604 raise error.Abort(_("help section not found"))
4605 4605
4606 4606 if 'verbose' in pruned:
4607 4607 keep.append('omitted')
4608 4608 else:
4609 4609 keep.append('notomitted')
4610 4610 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4611 4611 section=section)
4612 4612 ui.write(formatted)
4613 4613
4614 4614
4615 4615 @command('identify|id',
4616 4616 [('r', 'rev', '',
4617 4617 _('identify the specified revision'), _('REV')),
4618 4618 ('n', 'num', None, _('show local revision number')),
4619 4619 ('i', 'id', None, _('show global revision id')),
4620 4620 ('b', 'branch', None, _('show branch')),
4621 4621 ('t', 'tags', None, _('show tags')),
4622 4622 ('B', 'bookmarks', None, _('show bookmarks')),
4623 4623 ] + remoteopts,
4624 4624 _('[-nibtB] [-r REV] [SOURCE]'),
4625 4625 optionalrepo=True)
4626 4626 def identify(ui, repo, source=None, rev=None,
4627 4627 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4628 4628 """identify the working directory or specified revision
4629 4629
4630 4630 Print a summary identifying the repository state at REV using one or
4631 4631 two parent hash identifiers, followed by a "+" if the working
4632 4632 directory has uncommitted changes, the branch name (if not default),
4633 4633 a list of tags, and a list of bookmarks.
4634 4634
4635 4635 When REV is not given, print a summary of the current state of the
4636 4636 repository.
4637 4637
4638 4638 Specifying a path to a repository root or Mercurial bundle will
4639 4639 cause lookup to operate on that repository/bundle.
4640 4640
4641 4641 .. container:: verbose
4642 4642
4643 4643 Examples:
4644 4644
4645 4645 - generate a build identifier for the working directory::
4646 4646
4647 4647 hg id --id > build-id.dat
4648 4648
4649 4649 - find the revision corresponding to a tag::
4650 4650
4651 4651 hg id -n -r 1.3
4652 4652
4653 4653 - check the most recent revision of a remote repository::
4654 4654
4655 4655 hg id -r tip http://selenic.com/hg/
4656 4656
4657 4657 See :hg:`log` for generating more information about specific revisions,
4658 4658 including full hash identifiers.
4659 4659
4660 4660 Returns 0 if successful.
4661 4661 """
4662 4662
4663 4663 if not repo and not source:
4664 4664 raise error.Abort(_("there is no Mercurial repository here "
4665 4665 "(.hg not found)"))
4666 4666
4667 4667 if ui.debugflag:
4668 4668 hexfunc = hex
4669 4669 else:
4670 4670 hexfunc = short
4671 4671 default = not (num or id or branch or tags or bookmarks)
4672 4672 output = []
4673 4673 revs = []
4674 4674
4675 4675 if source:
4676 4676 source, branches = hg.parseurl(ui.expandpath(source))
4677 4677 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4678 4678 repo = peer.local()
4679 4679 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4680 4680
4681 4681 if not repo:
4682 4682 if num or branch or tags:
4683 4683 raise error.Abort(
4684 4684 _("can't query remote revision number, branch, or tags"))
4685 4685 if not rev and revs:
4686 4686 rev = revs[0]
4687 4687 if not rev:
4688 4688 rev = "tip"
4689 4689
4690 4690 remoterev = peer.lookup(rev)
4691 4691 if default or id:
4692 4692 output = [hexfunc(remoterev)]
4693 4693
4694 4694 def getbms():
4695 4695 bms = []
4696 4696
4697 4697 if 'bookmarks' in peer.listkeys('namespaces'):
4698 4698 hexremoterev = hex(remoterev)
4699 4699 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4700 4700 if bmr == hexremoterev]
4701 4701
4702 4702 return sorted(bms)
4703 4703
4704 4704 if bookmarks:
4705 4705 output.extend(getbms())
4706 4706 elif default and not ui.quiet:
4707 4707 # multiple bookmarks for a single parent separated by '/'
4708 4708 bm = '/'.join(getbms())
4709 4709 if bm:
4710 4710 output.append(bm)
4711 4711 else:
4712 4712 ctx = scmutil.revsingle(repo, rev, None)
4713 4713
4714 4714 if ctx.rev() is None:
4715 4715 ctx = repo[None]
4716 4716 parents = ctx.parents()
4717 4717 taglist = []
4718 4718 for p in parents:
4719 4719 taglist.extend(p.tags())
4720 4720
4721 4721 changed = ""
4722 4722 if default or id or num:
4723 4723 if (any(repo.status())
4724 4724 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4725 4725 changed = '+'
4726 4726 if default or id:
4727 4727 output = ["%s%s" %
4728 4728 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4729 4729 if num:
4730 4730 output.append("%s%s" %
4731 4731 ('+'.join([str(p.rev()) for p in parents]), changed))
4732 4732 else:
4733 4733 if default or id:
4734 4734 output = [hexfunc(ctx.node())]
4735 4735 if num:
4736 4736 output.append(str(ctx.rev()))
4737 4737 taglist = ctx.tags()
4738 4738
4739 4739 if default and not ui.quiet:
4740 4740 b = ctx.branch()
4741 4741 if b != 'default':
4742 4742 output.append("(%s)" % b)
4743 4743
4744 4744 # multiple tags for a single parent separated by '/'
4745 4745 t = '/'.join(taglist)
4746 4746 if t:
4747 4747 output.append(t)
4748 4748
4749 4749 # multiple bookmarks for a single parent separated by '/'
4750 4750 bm = '/'.join(ctx.bookmarks())
4751 4751 if bm:
4752 4752 output.append(bm)
4753 4753 else:
4754 4754 if branch:
4755 4755 output.append(ctx.branch())
4756 4756
4757 4757 if tags:
4758 4758 output.extend(taglist)
4759 4759
4760 4760 if bookmarks:
4761 4761 output.extend(ctx.bookmarks())
4762 4762
4763 4763 ui.write("%s\n" % ' '.join(output))
4764 4764
4765 4765 @command('import|patch',
4766 4766 [('p', 'strip', 1,
4767 4767 _('directory strip option for patch. This has the same '
4768 4768 'meaning as the corresponding patch option'), _('NUM')),
4769 4769 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4770 4770 ('e', 'edit', False, _('invoke editor on commit messages')),
4771 4771 ('f', 'force', None,
4772 4772 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4773 4773 ('', 'no-commit', None,
4774 4774 _("don't commit, just update the working directory")),
4775 4775 ('', 'bypass', None,
4776 4776 _("apply patch without touching the working directory")),
4777 4777 ('', 'partial', None,
4778 4778 _('commit even if some hunks fail')),
4779 4779 ('', 'exact', None,
4780 4780 _('abort if patch would apply lossily')),
4781 4781 ('', 'prefix', '',
4782 4782 _('apply patch to subdirectory'), _('DIR')),
4783 4783 ('', 'import-branch', None,
4784 4784 _('use any branch information in patch (implied by --exact)'))] +
4785 4785 commitopts + commitopts2 + similarityopts,
4786 4786 _('[OPTION]... PATCH...'))
4787 4787 def import_(ui, repo, patch1=None, *patches, **opts):
4788 4788 """import an ordered set of patches
4789 4789
4790 4790 Import a list of patches and commit them individually (unless
4791 4791 --no-commit is specified).
4792 4792
4793 4793 To read a patch from standard input, use "-" as the patch name. If
4794 4794 a URL is specified, the patch will be downloaded from there.
4795 4795
4796 4796 Import first applies changes to the working directory (unless
4797 4797 --bypass is specified), import will abort if there are outstanding
4798 4798 changes.
4799 4799
4800 4800 Use --bypass to apply and commit patches directly to the
4801 4801 repository, without affecting the working directory. Without
4802 4802 --exact, patches will be applied on top of the working directory
4803 4803 parent revision.
4804 4804
4805 4805 You can import a patch straight from a mail message. Even patches
4806 4806 as attachments work (to use the body part, it must have type
4807 4807 text/plain or text/x-patch). From and Subject headers of email
4808 4808 message are used as default committer and commit message. All
4809 4809 text/plain body parts before first diff are added to the commit
4810 4810 message.
4811 4811
4812 4812 If the imported patch was generated by :hg:`export`, user and
4813 4813 description from patch override values from message headers and
4814 4814 body. Values given on command line with -m/--message and -u/--user
4815 4815 override these.
4816 4816
4817 4817 If --exact is specified, import will set the working directory to
4818 4818 the parent of each patch before applying it, and will abort if the
4819 4819 resulting changeset has a different ID than the one recorded in
4820 4820 the patch. This will guard against various ways that portable
4821 4821 patch formats and mail systems might fail to transfer Mercurial
4822 4822 data or metadata. See ':hg: bundle' for lossless transmission.
4823 4823
4824 4824 Use --partial to ensure a changeset will be created from the patch
4825 4825 even if some hunks fail to apply. Hunks that fail to apply will be
4826 4826 written to a <target-file>.rej file. Conflicts can then be resolved
4827 4827 by hand before :hg:`commit --amend` is run to update the created
4828 4828 changeset. This flag exists to let people import patches that
4829 4829 partially apply without losing the associated metadata (author,
4830 4830 date, description, ...).
4831 4831
4832 4832 .. note::
4833 4833
4834 4834 When no hunks apply cleanly, :hg:`import --partial` will create
4835 4835 an empty changeset, importing only the patch metadata.
4836 4836
4837 4837 With -s/--similarity, hg will attempt to discover renames and
4838 4838 copies in the patch in the same way as :hg:`addremove`.
4839 4839
4840 4840 It is possible to use external patch programs to perform the patch
4841 4841 by setting the ``ui.patch`` configuration option. For the default
4842 4842 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4843 4843 See :hg:`help config` for more information about configuration
4844 4844 files and how to use these options.
4845 4845
4846 4846 See :hg:`help dates` for a list of formats valid for -d/--date.
4847 4847
4848 4848 .. container:: verbose
4849 4849
4850 4850 Examples:
4851 4851
4852 4852 - import a traditional patch from a website and detect renames::
4853 4853
4854 4854 hg import -s 80 http://example.com/bugfix.patch
4855 4855
4856 4856 - import a changeset from an hgweb server::
4857 4857
4858 4858 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4859 4859
4860 4860 - import all the patches in an Unix-style mbox::
4861 4861
4862 4862 hg import incoming-patches.mbox
4863 4863
4864 4864 - attempt to exactly restore an exported changeset (not always
4865 4865 possible)::
4866 4866
4867 4867 hg import --exact proposed-fix.patch
4868 4868
4869 4869 - use an external tool to apply a patch which is too fuzzy for
4870 4870 the default internal tool.
4871 4871
4872 4872 hg import --config ui.patch="patch --merge" fuzzy.patch
4873 4873
4874 4874 - change the default fuzzing from 2 to a less strict 7
4875 4875
4876 4876 hg import --config ui.fuzz=7 fuzz.patch
4877 4877
4878 4878 Returns 0 on success, 1 on partial success (see --partial).
4879 4879 """
4880 4880
4881 4881 if not patch1:
4882 4882 raise error.Abort(_('need at least one patch to import'))
4883 4883
4884 4884 patches = (patch1,) + patches
4885 4885
4886 4886 date = opts.get('date')
4887 4887 if date:
4888 4888 opts['date'] = util.parsedate(date)
4889 4889
4890 4890 exact = opts.get('exact')
4891 4891 update = not opts.get('bypass')
4892 4892 if not update and opts.get('no_commit'):
4893 4893 raise error.Abort(_('cannot use --no-commit with --bypass'))
4894 4894 try:
4895 4895 sim = float(opts.get('similarity') or 0)
4896 4896 except ValueError:
4897 4897 raise error.Abort(_('similarity must be a number'))
4898 4898 if sim < 0 or sim > 100:
4899 4899 raise error.Abort(_('similarity must be between 0 and 100'))
4900 4900 if sim and not update:
4901 4901 raise error.Abort(_('cannot use --similarity with --bypass'))
4902 4902 if exact:
4903 4903 if opts.get('edit'):
4904 4904 raise error.Abort(_('cannot use --exact with --edit'))
4905 4905 if opts.get('prefix'):
4906 4906 raise error.Abort(_('cannot use --exact with --prefix'))
4907 4907
4908 4908 base = opts["base"]
4909 4909 wlock = dsguard = lock = tr = None
4910 4910 msgs = []
4911 4911 ret = 0
4912 4912
4913 4913
4914 4914 try:
4915 4915 wlock = repo.wlock()
4916 4916
4917 4917 if update:
4918 4918 cmdutil.checkunfinished(repo)
4919 4919 if (exact or not opts.get('force')):
4920 4920 cmdutil.bailifchanged(repo)
4921 4921
4922 4922 if not opts.get('no_commit'):
4923 4923 lock = repo.lock()
4924 4924 tr = repo.transaction('import')
4925 4925 else:
4926 4926 dsguard = cmdutil.dirstateguard(repo, 'import')
4927 4927 parents = repo[None].parents()
4928 4928 for patchurl in patches:
4929 4929 if patchurl == '-':
4930 4930 ui.status(_('applying patch from stdin\n'))
4931 4931 patchfile = ui.fin
4932 4932 patchurl = 'stdin' # for error message
4933 4933 else:
4934 4934 patchurl = os.path.join(base, patchurl)
4935 4935 ui.status(_('applying %s\n') % patchurl)
4936 4936 patchfile = hg.openpath(ui, patchurl)
4937 4937
4938 4938 haspatch = False
4939 4939 for hunk in patch.split(patchfile):
4940 4940 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4941 4941 parents, opts,
4942 4942 msgs, hg.clean)
4943 4943 if msg:
4944 4944 haspatch = True
4945 4945 ui.note(msg + '\n')
4946 4946 if update or exact:
4947 4947 parents = repo[None].parents()
4948 4948 else:
4949 4949 parents = [repo[node]]
4950 4950 if rej:
4951 4951 ui.write_err(_("patch applied partially\n"))
4952 4952 ui.write_err(_("(fix the .rej files and run "
4953 4953 "`hg commit --amend`)\n"))
4954 4954 ret = 1
4955 4955 break
4956 4956
4957 4957 if not haspatch:
4958 4958 raise error.Abort(_('%s: no diffs found') % patchurl)
4959 4959
4960 4960 if tr:
4961 4961 tr.close()
4962 4962 if msgs:
4963 4963 repo.savecommitmessage('\n* * *\n'.join(msgs))
4964 4964 if dsguard:
4965 4965 dsguard.close()
4966 4966 return ret
4967 4967 finally:
4968 4968 if tr:
4969 4969 tr.release()
4970 4970 release(lock, dsguard, wlock)
4971 4971
4972 4972 @command('incoming|in',
4973 4973 [('f', 'force', None,
4974 4974 _('run even if remote repository is unrelated')),
4975 4975 ('n', 'newest-first', None, _('show newest record first')),
4976 4976 ('', 'bundle', '',
4977 4977 _('file to store the bundles into'), _('FILE')),
4978 4978 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4979 4979 ('B', 'bookmarks', False, _("compare bookmarks")),
4980 4980 ('b', 'branch', [],
4981 4981 _('a specific branch you would like to pull'), _('BRANCH')),
4982 4982 ] + logopts + remoteopts + subrepoopts,
4983 4983 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4984 4984 def incoming(ui, repo, source="default", **opts):
4985 4985 """show new changesets found in source
4986 4986
4987 4987 Show new changesets found in the specified path/URL or the default
4988 4988 pull location. These are the changesets that would have been pulled
4989 4989 if a pull at the time you issued this command.
4990 4990
4991 4991 See pull for valid source format details.
4992 4992
4993 4993 .. container:: verbose
4994 4994
4995 4995 With -B/--bookmarks, the result of bookmark comparison between
4996 4996 local and remote repositories is displayed. With -v/--verbose,
4997 4997 status is also displayed for each bookmark like below::
4998 4998
4999 4999 BM1 01234567890a added
5000 5000 BM2 1234567890ab advanced
5001 5001 BM3 234567890abc diverged
5002 5002 BM4 34567890abcd changed
5003 5003
5004 5004 The action taken locally when pulling depends on the
5005 5005 status of each bookmark:
5006 5006
5007 5007 :``added``: pull will create it
5008 5008 :``advanced``: pull will update it
5009 5009 :``diverged``: pull will create a divergent bookmark
5010 5010 :``changed``: result depends on remote changesets
5011 5011
5012 5012 From the point of view of pulling behavior, bookmark
5013 5013 existing only in the remote repository are treated as ``added``,
5014 5014 even if it is in fact locally deleted.
5015 5015
5016 5016 .. container:: verbose
5017 5017
5018 5018 For remote repository, using --bundle avoids downloading the
5019 5019 changesets twice if the incoming is followed by a pull.
5020 5020
5021 5021 Examples:
5022 5022
5023 5023 - show incoming changes with patches and full description::
5024 5024
5025 5025 hg incoming -vp
5026 5026
5027 5027 - show incoming changes excluding merges, store a bundle::
5028 5028
5029 5029 hg in -vpM --bundle incoming.hg
5030 5030 hg pull incoming.hg
5031 5031
5032 5032 - briefly list changes inside a bundle::
5033 5033
5034 5034 hg in changes.hg -T "{desc|firstline}\\n"
5035 5035
5036 5036 Returns 0 if there are incoming changes, 1 otherwise.
5037 5037 """
5038 5038 if opts.get('graph'):
5039 5039 cmdutil.checkunsupportedgraphflags([], opts)
5040 5040 def display(other, chlist, displayer):
5041 5041 revdag = cmdutil.graphrevs(other, chlist, opts)
5042 5042 cmdutil.displaygraph(ui, repo, revdag, displayer,
5043 5043 graphmod.asciiedges)
5044 5044
5045 5045 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5046 5046 return 0
5047 5047
5048 5048 if opts.get('bundle') and opts.get('subrepos'):
5049 5049 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5050 5050
5051 5051 if opts.get('bookmarks'):
5052 5052 source, branches = hg.parseurl(ui.expandpath(source),
5053 5053 opts.get('branch'))
5054 5054 other = hg.peer(repo, opts, source)
5055 5055 if 'bookmarks' not in other.listkeys('namespaces'):
5056 5056 ui.warn(_("remote doesn't support bookmarks\n"))
5057 5057 return 0
5058 5058 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5059 5059 return bookmarks.incoming(ui, repo, other)
5060 5060
5061 5061 repo._subtoppath = ui.expandpath(source)
5062 5062 try:
5063 5063 return hg.incoming(ui, repo, source, opts)
5064 5064 finally:
5065 5065 del repo._subtoppath
5066 5066
5067 5067
5068 5068 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5069 5069 norepo=True)
5070 5070 def init(ui, dest=".", **opts):
5071 5071 """create a new repository in the given directory
5072 5072
5073 5073 Initialize a new repository in the given directory. If the given
5074 5074 directory does not exist, it will be created.
5075 5075
5076 5076 If no directory is given, the current directory is used.
5077 5077
5078 5078 It is possible to specify an ``ssh://`` URL as the destination.
5079 5079 See :hg:`help urls` for more information.
5080 5080
5081 5081 Returns 0 on success.
5082 5082 """
5083 5083 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5084 5084
5085 5085 @command('locate',
5086 5086 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5087 5087 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5088 5088 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5089 5089 ] + walkopts,
5090 5090 _('[OPTION]... [PATTERN]...'))
5091 5091 def locate(ui, repo, *pats, **opts):
5092 5092 """locate files matching specific patterns (DEPRECATED)
5093 5093
5094 5094 Print files under Mercurial control in the working directory whose
5095 5095 names match the given patterns.
5096 5096
5097 5097 By default, this command searches all directories in the working
5098 5098 directory. To search just the current directory and its
5099 5099 subdirectories, use "--include .".
5100 5100
5101 5101 If no patterns are given to match, this command prints the names
5102 5102 of all files under Mercurial control in the working directory.
5103 5103
5104 5104 If you want to feed the output of this command into the "xargs"
5105 5105 command, use the -0 option to both this command and "xargs". This
5106 5106 will avoid the problem of "xargs" treating single filenames that
5107 5107 contain whitespace as multiple filenames.
5108 5108
5109 5109 See :hg:`help files` for a more versatile command.
5110 5110
5111 5111 Returns 0 if a match is found, 1 otherwise.
5112 5112 """
5113 5113 if opts.get('print0'):
5114 5114 end = '\0'
5115 5115 else:
5116 5116 end = '\n'
5117 5117 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5118 5118
5119 5119 ret = 1
5120 5120 ctx = repo[rev]
5121 5121 m = scmutil.match(ctx, pats, opts, default='relglob',
5122 5122 badfn=lambda x, y: False)
5123 5123
5124 5124 for abs in ctx.matches(m):
5125 5125 if opts.get('fullpath'):
5126 5126 ui.write(repo.wjoin(abs), end)
5127 5127 else:
5128 5128 ui.write(((pats and m.rel(abs)) or abs), end)
5129 5129 ret = 0
5130 5130
5131 5131 return ret
5132 5132
5133 5133 @command('^log|history',
5134 5134 [('f', 'follow', None,
5135 5135 _('follow changeset history, or file history across copies and renames')),
5136 5136 ('', 'follow-first', None,
5137 5137 _('only follow the first parent of merge changesets (DEPRECATED)')),
5138 5138 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5139 5139 ('C', 'copies', None, _('show copied files')),
5140 5140 ('k', 'keyword', [],
5141 5141 _('do case-insensitive search for a given text'), _('TEXT')),
5142 5142 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5143 5143 ('', 'removed', None, _('include revisions where files were removed')),
5144 5144 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5145 5145 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5146 5146 ('', 'only-branch', [],
5147 5147 _('show only changesets within the given named branch (DEPRECATED)'),
5148 5148 _('BRANCH')),
5149 5149 ('b', 'branch', [],
5150 5150 _('show changesets within the given named branch'), _('BRANCH')),
5151 5151 ('P', 'prune', [],
5152 5152 _('do not display revision or any of its ancestors'), _('REV')),
5153 5153 ] + logopts + walkopts,
5154 5154 _('[OPTION]... [FILE]'),
5155 5155 inferrepo=True)
5156 5156 def log(ui, repo, *pats, **opts):
5157 5157 """show revision history of entire repository or files
5158 5158
5159 5159 Print the revision history of the specified files or the entire
5160 5160 project.
5161 5161
5162 5162 If no revision range is specified, the default is ``tip:0`` unless
5163 5163 --follow is set, in which case the working directory parent is
5164 5164 used as the starting revision.
5165 5165
5166 5166 File history is shown without following rename or copy history of
5167 5167 files. Use -f/--follow with a filename to follow history across
5168 5168 renames and copies. --follow without a filename will only show
5169 5169 ancestors or descendants of the starting revision.
5170 5170
5171 5171 By default this command prints revision number and changeset id,
5172 5172 tags, non-trivial parents, user, date and time, and a summary for
5173 5173 each commit. When the -v/--verbose switch is used, the list of
5174 5174 changed files and full commit message are shown.
5175 5175
5176 5176 With --graph the revisions are shown as an ASCII art DAG with the most
5177 5177 recent changeset at the top.
5178 5178 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5179 5179 and '+' represents a fork where the changeset from the lines below is a
5180 5180 parent of the 'o' merge on the same line.
5181 5181
5182 5182 .. note::
5183 5183
5184 5184 :hg:`log --patch` may generate unexpected diff output for merge
5185 5185 changesets, as it will only compare the merge changeset against
5186 5186 its first parent. Also, only files different from BOTH parents
5187 5187 will appear in files:.
5188 5188
5189 5189 .. note::
5190 5190
5191 5191 For performance reasons, :hg:`log FILE` may omit duplicate changes
5192 5192 made on branches and will not show removals or mode changes. To
5193 5193 see all such changes, use the --removed switch.
5194 5194
5195 5195 .. container:: verbose
5196 5196
5197 5197 Some examples:
5198 5198
5199 5199 - changesets with full descriptions and file lists::
5200 5200
5201 5201 hg log -v
5202 5202
5203 5203 - changesets ancestral to the working directory::
5204 5204
5205 5205 hg log -f
5206 5206
5207 5207 - last 10 commits on the current branch::
5208 5208
5209 5209 hg log -l 10 -b .
5210 5210
5211 5211 - changesets showing all modifications of a file, including removals::
5212 5212
5213 5213 hg log --removed file.c
5214 5214
5215 5215 - all changesets that touch a directory, with diffs, excluding merges::
5216 5216
5217 5217 hg log -Mp lib/
5218 5218
5219 5219 - all revision numbers that match a keyword::
5220 5220
5221 5221 hg log -k bug --template "{rev}\\n"
5222 5222
5223 5223 - the full hash identifier of the working directory parent::
5224 5224
5225 5225 hg log -r . --template "{node}\\n"
5226 5226
5227 5227 - list available log templates::
5228 5228
5229 5229 hg log -T list
5230 5230
5231 5231 - check if a given changeset is included in a tagged release::
5232 5232
5233 5233 hg log -r "a21ccf and ancestor(1.9)"
5234 5234
5235 5235 - find all changesets by some user in a date range::
5236 5236
5237 5237 hg log -k alice -d "may 2008 to jul 2008"
5238 5238
5239 5239 - summary of all changesets after the last tag::
5240 5240
5241 5241 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5242 5242
5243 5243 See :hg:`help dates` for a list of formats valid for -d/--date.
5244 5244
5245 5245 See :hg:`help revisions` and :hg:`help revsets` for more about
5246 5246 specifying and ordering revisions.
5247 5247
5248 5248 See :hg:`help templates` for more about pre-packaged styles and
5249 5249 specifying custom templates.
5250 5250
5251 5251 Returns 0 on success.
5252 5252
5253 5253 """
5254 5254 if opts.get('follow') and opts.get('rev'):
5255 5255 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5256 5256 del opts['follow']
5257 5257
5258 5258 if opts.get('graph'):
5259 5259 return cmdutil.graphlog(ui, repo, *pats, **opts)
5260 5260
5261 5261 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5262 5262 limit = cmdutil.loglimit(opts)
5263 5263 count = 0
5264 5264
5265 5265 getrenamed = None
5266 5266 if opts.get('copies'):
5267 5267 endrev = None
5268 5268 if opts.get('rev'):
5269 5269 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5270 5270 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5271 5271
5272 5272 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5273 5273 for rev in revs:
5274 5274 if count == limit:
5275 5275 break
5276 5276 ctx = repo[rev]
5277 5277 copies = None
5278 5278 if getrenamed is not None and rev:
5279 5279 copies = []
5280 5280 for fn in ctx.files():
5281 5281 rename = getrenamed(fn, rev)
5282 5282 if rename:
5283 5283 copies.append((fn, rename[0]))
5284 5284 if filematcher:
5285 5285 revmatchfn = filematcher(ctx.rev())
5286 5286 else:
5287 5287 revmatchfn = None
5288 5288 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5289 5289 if displayer.flush(ctx):
5290 5290 count += 1
5291 5291
5292 5292 displayer.close()
5293 5293
5294 5294 @command('manifest',
5295 5295 [('r', 'rev', '', _('revision to display'), _('REV')),
5296 5296 ('', 'all', False, _("list files from all revisions"))]
5297 5297 + formatteropts,
5298 5298 _('[-r REV]'))
5299 5299 def manifest(ui, repo, node=None, rev=None, **opts):
5300 5300 """output the current or given revision of the project manifest
5301 5301
5302 5302 Print a list of version controlled files for the given revision.
5303 5303 If no revision is given, the first parent of the working directory
5304 5304 is used, or the null revision if no revision is checked out.
5305 5305
5306 5306 With -v, print file permissions, symlink and executable bits.
5307 5307 With --debug, print file revision hashes.
5308 5308
5309 5309 If option --all is specified, the list of all files from all revisions
5310 5310 is printed. This includes deleted and renamed files.
5311 5311
5312 5312 Returns 0 on success.
5313 5313 """
5314 5314
5315 5315 fm = ui.formatter('manifest', opts)
5316 5316
5317 5317 if opts.get('all'):
5318 5318 if rev or node:
5319 5319 raise error.Abort(_("can't specify a revision with --all"))
5320 5320
5321 5321 res = []
5322 5322 prefix = "data/"
5323 5323 suffix = ".i"
5324 5324 plen = len(prefix)
5325 5325 slen = len(suffix)
5326 5326 with repo.lock():
5327 5327 for fn, b, size in repo.store.datafiles():
5328 5328 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5329 5329 res.append(fn[plen:-slen])
5330 5330 for f in res:
5331 5331 fm.startitem()
5332 5332 fm.write("path", '%s\n', f)
5333 5333 fm.end()
5334 5334 return
5335 5335
5336 5336 if rev and node:
5337 5337 raise error.Abort(_("please specify just one revision"))
5338 5338
5339 5339 if not node:
5340 5340 node = rev
5341 5341
5342 5342 char = {'l': '@', 'x': '*', '': ''}
5343 5343 mode = {'l': '644', 'x': '755', '': '644'}
5344 5344 ctx = scmutil.revsingle(repo, node)
5345 5345 mf = ctx.manifest()
5346 5346 for f in ctx:
5347 5347 fm.startitem()
5348 5348 fl = ctx[f].flags()
5349 5349 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5350 5350 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5351 5351 fm.write('path', '%s\n', f)
5352 5352 fm.end()
5353 5353
5354 5354 @command('^merge',
5355 5355 [('f', 'force', None,
5356 5356 _('force a merge including outstanding changes (DEPRECATED)')),
5357 5357 ('r', 'rev', '', _('revision to merge'), _('REV')),
5358 5358 ('P', 'preview', None,
5359 5359 _('review revisions to merge (no merge is performed)'))
5360 5360 ] + mergetoolopts,
5361 5361 _('[-P] [[-r] REV]'))
5362 5362 def merge(ui, repo, node=None, **opts):
5363 5363 """merge another revision into working directory
5364 5364
5365 5365 The current working directory is updated with all changes made in
5366 5366 the requested revision since the last common predecessor revision.
5367 5367
5368 5368 Files that changed between either parent are marked as changed for
5369 5369 the next commit and a commit must be performed before any further
5370 5370 updates to the repository are allowed. The next commit will have
5371 5371 two parents.
5372 5372
5373 5373 ``--tool`` can be used to specify the merge tool used for file
5374 5374 merges. It overrides the HGMERGE environment variable and your
5375 5375 configuration files. See :hg:`help merge-tools` for options.
5376 5376
5377 5377 If no revision is specified, the working directory's parent is a
5378 5378 head revision, and the current branch contains exactly one other
5379 5379 head, the other head is merged with by default. Otherwise, an
5380 5380 explicit revision with which to merge with must be provided.
5381 5381
5382 5382 See :hg:`help resolve` for information on handling file conflicts.
5383 5383
5384 5384 To undo an uncommitted merge, use :hg:`update --clean .` which
5385 5385 will check out a clean copy of the original merge parent, losing
5386 5386 all changes.
5387 5387
5388 5388 Returns 0 on success, 1 if there are unresolved files.
5389 5389 """
5390 5390
5391 5391 if opts.get('rev') and node:
5392 5392 raise error.Abort(_("please specify just one revision"))
5393 5393 if not node:
5394 5394 node = opts.get('rev')
5395 5395
5396 5396 if node:
5397 5397 node = scmutil.revsingle(repo, node).node()
5398 5398
5399 5399 if not node:
5400 5400 node = repo[destutil.destmerge(repo)].node()
5401 5401
5402 5402 if opts.get('preview'):
5403 5403 # find nodes that are ancestors of p2 but not of p1
5404 5404 p1 = repo.lookup('.')
5405 5405 p2 = repo.lookup(node)
5406 5406 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5407 5407
5408 5408 displayer = cmdutil.show_changeset(ui, repo, opts)
5409 5409 for node in nodes:
5410 5410 displayer.show(repo[node])
5411 5411 displayer.close()
5412 5412 return 0
5413 5413
5414 5414 try:
5415 5415 # ui.forcemerge is an internal variable, do not document
5416 5416 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5417 5417 force = opts.get('force')
5418 5418 return hg.merge(repo, node, force=force, mergeforce=force)
5419 5419 finally:
5420 5420 ui.setconfig('ui', 'forcemerge', '', 'merge')
5421 5421
5422 5422 @command('outgoing|out',
5423 5423 [('f', 'force', None, _('run even when the destination is unrelated')),
5424 5424 ('r', 'rev', [],
5425 5425 _('a changeset intended to be included in the destination'), _('REV')),
5426 5426 ('n', 'newest-first', None, _('show newest record first')),
5427 5427 ('B', 'bookmarks', False, _('compare bookmarks')),
5428 5428 ('b', 'branch', [], _('a specific branch you would like to push'),
5429 5429 _('BRANCH')),
5430 5430 ] + logopts + remoteopts + subrepoopts,
5431 5431 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5432 5432 def outgoing(ui, repo, dest=None, **opts):
5433 5433 """show changesets not found in the destination
5434 5434
5435 5435 Show changesets not found in the specified destination repository
5436 5436 or the default push location. These are the changesets that would
5437 5437 be pushed if a push was requested.
5438 5438
5439 5439 See pull for details of valid destination formats.
5440 5440
5441 5441 .. container:: verbose
5442 5442
5443 5443 With -B/--bookmarks, the result of bookmark comparison between
5444 5444 local and remote repositories is displayed. With -v/--verbose,
5445 5445 status is also displayed for each bookmark like below::
5446 5446
5447 5447 BM1 01234567890a added
5448 5448 BM2 deleted
5449 5449 BM3 234567890abc advanced
5450 5450 BM4 34567890abcd diverged
5451 5451 BM5 4567890abcde changed
5452 5452
5453 5453 The action taken when pushing depends on the
5454 5454 status of each bookmark:
5455 5455
5456 5456 :``added``: push with ``-B`` will create it
5457 5457 :``deleted``: push with ``-B`` will delete it
5458 5458 :``advanced``: push will update it
5459 5459 :``diverged``: push with ``-B`` will update it
5460 5460 :``changed``: push with ``-B`` will update it
5461 5461
5462 5462 From the point of view of pushing behavior, bookmarks
5463 5463 existing only in the remote repository are treated as
5464 5464 ``deleted``, even if it is in fact added remotely.
5465 5465
5466 5466 Returns 0 if there are outgoing changes, 1 otherwise.
5467 5467 """
5468 5468 if opts.get('graph'):
5469 5469 cmdutil.checkunsupportedgraphflags([], opts)
5470 5470 o, other = hg._outgoing(ui, repo, dest, opts)
5471 5471 if not o:
5472 5472 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5473 5473 return
5474 5474
5475 5475 revdag = cmdutil.graphrevs(repo, o, opts)
5476 5476 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5477 5477 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5478 5478 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5479 5479 return 0
5480 5480
5481 5481 if opts.get('bookmarks'):
5482 5482 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5483 5483 dest, branches = hg.parseurl(dest, opts.get('branch'))
5484 5484 other = hg.peer(repo, opts, dest)
5485 5485 if 'bookmarks' not in other.listkeys('namespaces'):
5486 5486 ui.warn(_("remote doesn't support bookmarks\n"))
5487 5487 return 0
5488 5488 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5489 5489 return bookmarks.outgoing(ui, repo, other)
5490 5490
5491 5491 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5492 5492 try:
5493 5493 return hg.outgoing(ui, repo, dest, opts)
5494 5494 finally:
5495 5495 del repo._subtoppath
5496 5496
5497 5497 @command('parents',
5498 5498 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5499 5499 ] + templateopts,
5500 5500 _('[-r REV] [FILE]'),
5501 5501 inferrepo=True)
5502 5502 def parents(ui, repo, file_=None, **opts):
5503 5503 """show the parents of the working directory or revision (DEPRECATED)
5504 5504
5505 5505 Print the working directory's parent revisions. If a revision is
5506 5506 given via -r/--rev, the parent of that revision will be printed.
5507 5507 If a file argument is given, the revision in which the file was
5508 5508 last changed (before the working directory revision or the
5509 5509 argument to --rev if given) is printed.
5510 5510
5511 5511 This command is equivalent to::
5512 5512
5513 5513 hg log -r "p1()+p2()" or
5514 5514 hg log -r "p1(REV)+p2(REV)" or
5515 5515 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5516 5516 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5517 5517
5518 5518 See :hg:`summary` and :hg:`help revsets` for related information.
5519 5519
5520 5520 Returns 0 on success.
5521 5521 """
5522 5522
5523 5523 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5524 5524
5525 5525 if file_:
5526 5526 m = scmutil.match(ctx, (file_,), opts)
5527 5527 if m.anypats() or len(m.files()) != 1:
5528 5528 raise error.Abort(_('can only specify an explicit filename'))
5529 5529 file_ = m.files()[0]
5530 5530 filenodes = []
5531 5531 for cp in ctx.parents():
5532 5532 if not cp:
5533 5533 continue
5534 5534 try:
5535 5535 filenodes.append(cp.filenode(file_))
5536 5536 except error.LookupError:
5537 5537 pass
5538 5538 if not filenodes:
5539 5539 raise error.Abort(_("'%s' not found in manifest!") % file_)
5540 5540 p = []
5541 5541 for fn in filenodes:
5542 5542 fctx = repo.filectx(file_, fileid=fn)
5543 5543 p.append(fctx.node())
5544 5544 else:
5545 5545 p = [cp.node() for cp in ctx.parents()]
5546 5546
5547 5547 displayer = cmdutil.show_changeset(ui, repo, opts)
5548 5548 for n in p:
5549 5549 if n != nullid:
5550 5550 displayer.show(repo[n])
5551 5551 displayer.close()
5552 5552
5553 5553 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5554 5554 def paths(ui, repo, search=None, **opts):
5555 5555 """show aliases for remote repositories
5556 5556
5557 5557 Show definition of symbolic path name NAME. If no name is given,
5558 5558 show definition of all available names.
5559 5559
5560 5560 Option -q/--quiet suppresses all output when searching for NAME
5561 5561 and shows only the path names when listing all definitions.
5562 5562
5563 5563 Path names are defined in the [paths] section of your
5564 5564 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5565 5565 repository, ``.hg/hgrc`` is used, too.
5566 5566
5567 5567 The path names ``default`` and ``default-push`` have a special
5568 5568 meaning. When performing a push or pull operation, they are used
5569 5569 as fallbacks if no location is specified on the command-line.
5570 5570 When ``default-push`` is set, it will be used for push and
5571 5571 ``default`` will be used for pull; otherwise ``default`` is used
5572 5572 as the fallback for both. When cloning a repository, the clone
5573 5573 source is written as ``default`` in ``.hg/hgrc``.
5574 5574
5575 5575 .. note::
5576 5576
5577 5577 ``default`` and ``default-push`` apply to all inbound (e.g.
5578 5578 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5579 5579 and :hg:`bundle`) operations.
5580 5580
5581 5581 See :hg:`help urls` for more information.
5582 5582
5583 5583 Returns 0 on success.
5584 5584 """
5585 5585 if search:
5586 5586 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5587 5587 if name == search]
5588 5588 else:
5589 5589 pathitems = sorted(ui.paths.iteritems())
5590 5590
5591 5591 fm = ui.formatter('paths', opts)
5592 5592 if fm:
5593 5593 hidepassword = str
5594 5594 else:
5595 5595 hidepassword = util.hidepassword
5596 5596 if ui.quiet:
5597 5597 namefmt = '%s\n'
5598 5598 else:
5599 5599 namefmt = '%s = '
5600 5600 showsubopts = not search and not ui.quiet
5601 5601
5602 5602 for name, path in pathitems:
5603 5603 fm.startitem()
5604 5604 fm.condwrite(not search, 'name', namefmt, name)
5605 5605 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5606 5606 for subopt, value in sorted(path.suboptions.items()):
5607 5607 assert subopt not in ('name', 'url')
5608 5608 if showsubopts:
5609 5609 fm.plain('%s:%s = ' % (name, subopt))
5610 5610 fm.condwrite(showsubopts, subopt, '%s\n', value)
5611 5611
5612 5612 fm.end()
5613 5613
5614 5614 if search and not pathitems:
5615 5615 if not ui.quiet:
5616 5616 ui.warn(_("not found!\n"))
5617 5617 return 1
5618 5618 else:
5619 5619 return 0
5620 5620
5621 5621 @command('phase',
5622 5622 [('p', 'public', False, _('set changeset phase to public')),
5623 5623 ('d', 'draft', False, _('set changeset phase to draft')),
5624 5624 ('s', 'secret', False, _('set changeset phase to secret')),
5625 5625 ('f', 'force', False, _('allow to move boundary backward')),
5626 5626 ('r', 'rev', [], _('target revision'), _('REV')),
5627 5627 ],
5628 5628 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5629 5629 def phase(ui, repo, *revs, **opts):
5630 5630 """set or show the current phase name
5631 5631
5632 5632 With no argument, show the phase name of the current revision(s).
5633 5633
5634 5634 With one of -p/--public, -d/--draft or -s/--secret, change the
5635 5635 phase value of the specified revisions.
5636 5636
5637 5637 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5638 5638 lower phase to an higher phase. Phases are ordered as follows::
5639 5639
5640 5640 public < draft < secret
5641 5641
5642 5642 Returns 0 on success, 1 if some phases could not be changed.
5643 5643
5644 5644 (For more information about the phases concept, see :hg:`help phases`.)
5645 5645 """
5646 5646 # search for a unique phase argument
5647 5647 targetphase = None
5648 5648 for idx, name in enumerate(phases.phasenames):
5649 5649 if opts[name]:
5650 5650 if targetphase is not None:
5651 5651 raise error.Abort(_('only one phase can be specified'))
5652 5652 targetphase = idx
5653 5653
5654 5654 # look for specified revision
5655 5655 revs = list(revs)
5656 5656 revs.extend(opts['rev'])
5657 5657 if not revs:
5658 5658 # display both parents as the second parent phase can influence
5659 5659 # the phase of a merge commit
5660 5660 revs = [c.rev() for c in repo[None].parents()]
5661 5661
5662 5662 revs = scmutil.revrange(repo, revs)
5663 5663
5664 5664 lock = None
5665 5665 ret = 0
5666 5666 if targetphase is None:
5667 5667 # display
5668 5668 for r in revs:
5669 5669 ctx = repo[r]
5670 5670 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5671 5671 else:
5672 5672 tr = None
5673 5673 lock = repo.lock()
5674 5674 try:
5675 5675 tr = repo.transaction("phase")
5676 5676 # set phase
5677 5677 if not revs:
5678 5678 raise error.Abort(_('empty revision set'))
5679 5679 nodes = [repo[r].node() for r in revs]
5680 5680 # moving revision from public to draft may hide them
5681 5681 # We have to check result on an unfiltered repository
5682 5682 unfi = repo.unfiltered()
5683 5683 getphase = unfi._phasecache.phase
5684 5684 olddata = [getphase(unfi, r) for r in unfi]
5685 5685 phases.advanceboundary(repo, tr, targetphase, nodes)
5686 5686 if opts['force']:
5687 5687 phases.retractboundary(repo, tr, targetphase, nodes)
5688 5688 tr.close()
5689 5689 finally:
5690 5690 if tr is not None:
5691 5691 tr.release()
5692 5692 lock.release()
5693 5693 getphase = unfi._phasecache.phase
5694 5694 newdata = [getphase(unfi, r) for r in unfi]
5695 5695 changes = sum(newdata[r] != olddata[r] for r in unfi)
5696 5696 cl = unfi.changelog
5697 5697 rejected = [n for n in nodes
5698 5698 if newdata[cl.rev(n)] < targetphase]
5699 5699 if rejected:
5700 5700 ui.warn(_('cannot move %i changesets to a higher '
5701 5701 'phase, use --force\n') % len(rejected))
5702 5702 ret = 1
5703 5703 if changes:
5704 5704 msg = _('phase changed for %i changesets\n') % changes
5705 5705 if ret:
5706 5706 ui.status(msg)
5707 5707 else:
5708 5708 ui.note(msg)
5709 5709 else:
5710 5710 ui.warn(_('no phases changed\n'))
5711 5711 return ret
5712 5712
5713 5713 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5714 5714 """Run after a changegroup has been added via pull/unbundle
5715 5715
5716 5716 This takes arguments below:
5717 5717
5718 5718 :modheads: change of heads by pull/unbundle
5719 5719 :optupdate: updating working directory is needed or not
5720 5720 :checkout: update destination revision (or None to default destination)
5721 5721 :brev: a name, which might be a bookmark to be activated after updating
5722 5722 """
5723 5723 if modheads == 0:
5724 5724 return
5725 5725 if optupdate:
5726 5726 try:
5727 5727 return hg.updatetotally(ui, repo, checkout, brev)
5728 5728 except error.UpdateAbort as inst:
5729 5729 msg = _("not updating: %s") % str(inst)
5730 5730 hint = inst.hint
5731 5731 raise error.UpdateAbort(msg, hint=hint)
5732 5732 if modheads > 1:
5733 5733 currentbranchheads = len(repo.branchheads())
5734 5734 if currentbranchheads == modheads:
5735 5735 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5736 5736 elif currentbranchheads > 1:
5737 5737 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5738 5738 "merge)\n"))
5739 5739 else:
5740 5740 ui.status(_("(run 'hg heads' to see heads)\n"))
5741 5741 else:
5742 5742 ui.status(_("(run 'hg update' to get a working copy)\n"))
5743 5743
5744 5744 @command('^pull',
5745 5745 [('u', 'update', None,
5746 5746 _('update to new branch head if changesets were pulled')),
5747 5747 ('f', 'force', None, _('run even when remote repository is unrelated')),
5748 5748 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5749 5749 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5750 5750 ('b', 'branch', [], _('a specific branch you would like to pull'),
5751 5751 _('BRANCH')),
5752 5752 ] + remoteopts,
5753 5753 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5754 5754 def pull(ui, repo, source="default", **opts):
5755 5755 """pull changes from the specified source
5756 5756
5757 5757 Pull changes from a remote repository to a local one.
5758 5758
5759 5759 This finds all changes from the repository at the specified path
5760 5760 or URL and adds them to a local repository (the current one unless
5761 5761 -R is specified). By default, this does not update the copy of the
5762 5762 project in the working directory.
5763 5763
5764 5764 Use :hg:`incoming` if you want to see what would have been added
5765 5765 by a pull at the time you issued this command. If you then decide
5766 5766 to add those changes to the repository, you should use :hg:`pull
5767 5767 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5768 5768
5769 5769 If SOURCE is omitted, the 'default' path will be used.
5770 5770 See :hg:`help urls` for more information.
5771 5771
5772 5772 Returns 0 on success, 1 if an update had unresolved files.
5773 5773 """
5774 5774 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5775 5775 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5776 5776 other = hg.peer(repo, opts, source)
5777 5777 try:
5778 5778 revs, checkout = hg.addbranchrevs(repo, other, branches,
5779 5779 opts.get('rev'))
5780 5780
5781 5781
5782 5782 pullopargs = {}
5783 5783 if opts.get('bookmark'):
5784 5784 if not revs:
5785 5785 revs = []
5786 5786 # The list of bookmark used here is not the one used to actually
5787 5787 # update the bookmark name. This can result in the revision pulled
5788 5788 # not ending up with the name of the bookmark because of a race
5789 5789 # condition on the server. (See issue 4689 for details)
5790 5790 remotebookmarks = other.listkeys('bookmarks')
5791 5791 pullopargs['remotebookmarks'] = remotebookmarks
5792 5792 for b in opts['bookmark']:
5793 5793 if b not in remotebookmarks:
5794 5794 raise error.Abort(_('remote bookmark %s not found!') % b)
5795 5795 revs.append(remotebookmarks[b])
5796 5796
5797 5797 if revs:
5798 5798 try:
5799 5799 # When 'rev' is a bookmark name, we cannot guarantee that it
5800 5800 # will be updated with that name because of a race condition
5801 5801 # server side. (See issue 4689 for details)
5802 5802 oldrevs = revs
5803 5803 revs = [] # actually, nodes
5804 5804 for r in oldrevs:
5805 5805 node = other.lookup(r)
5806 5806 revs.append(node)
5807 5807 if r == checkout:
5808 5808 checkout = node
5809 5809 except error.CapabilityError:
5810 5810 err = _("other repository doesn't support revision lookup, "
5811 5811 "so a rev cannot be specified.")
5812 5812 raise error.Abort(err)
5813 5813
5814 5814 pullopargs.update(opts.get('opargs', {}))
5815 5815 modheads = exchange.pull(repo, other, heads=revs,
5816 5816 force=opts.get('force'),
5817 5817 bookmarks=opts.get('bookmark', ()),
5818 5818 opargs=pullopargs).cgresult
5819 5819
5820 5820 # brev is a name, which might be a bookmark to be activated at
5821 5821 # the end of the update. In other words, it is an explicit
5822 5822 # destination of the update
5823 5823 brev = None
5824 5824
5825 5825 if checkout:
5826 5826 checkout = str(repo.changelog.rev(checkout))
5827 5827
5828 5828 # order below depends on implementation of
5829 5829 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5830 5830 # because 'checkout' is determined without it.
5831 5831 if opts.get('rev'):
5832 5832 brev = opts['rev'][0]
5833 5833 elif opts.get('branch'):
5834 5834 brev = opts['branch'][0]
5835 5835 else:
5836 5836 brev = branches[0]
5837 5837 repo._subtoppath = source
5838 5838 try:
5839 5839 ret = postincoming(ui, repo, modheads, opts.get('update'),
5840 5840 checkout, brev)
5841 5841
5842 5842 finally:
5843 5843 del repo._subtoppath
5844 5844
5845 5845 finally:
5846 5846 other.close()
5847 5847 return ret
5848 5848
5849 5849 @command('^push',
5850 5850 [('f', 'force', None, _('force push')),
5851 5851 ('r', 'rev', [],
5852 5852 _('a changeset intended to be included in the destination'),
5853 5853 _('REV')),
5854 5854 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5855 5855 ('b', 'branch', [],
5856 5856 _('a specific branch you would like to push'), _('BRANCH')),
5857 5857 ('', 'new-branch', False, _('allow pushing a new branch')),
5858 5858 ] + remoteopts,
5859 5859 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5860 5860 def push(ui, repo, dest=None, **opts):
5861 5861 """push changes to the specified destination
5862 5862
5863 5863 Push changesets from the local repository to the specified
5864 5864 destination.
5865 5865
5866 5866 This operation is symmetrical to pull: it is identical to a pull
5867 5867 in the destination repository from the current one.
5868 5868
5869 5869 By default, push will not allow creation of new heads at the
5870 5870 destination, since multiple heads would make it unclear which head
5871 5871 to use. In this situation, it is recommended to pull and merge
5872 5872 before pushing.
5873 5873
5874 5874 Use --new-branch if you want to allow push to create a new named
5875 5875 branch that is not present at the destination. This allows you to
5876 5876 only create a new branch without forcing other changes.
5877 5877
5878 5878 .. note::
5879 5879
5880 5880 Extra care should be taken with the -f/--force option,
5881 5881 which will push all new heads on all branches, an action which will
5882 5882 almost always cause confusion for collaborators.
5883 5883
5884 5884 If -r/--rev is used, the specified revision and all its ancestors
5885 5885 will be pushed to the remote repository.
5886 5886
5887 5887 If -B/--bookmark is used, the specified bookmarked revision, its
5888 5888 ancestors, and the bookmark will be pushed to the remote
5889 5889 repository. Specifying ``.`` is equivalent to specifying the active
5890 5890 bookmark's name.
5891 5891
5892 5892 Please see :hg:`help urls` for important details about ``ssh://``
5893 5893 URLs. If DESTINATION is omitted, a default path will be used.
5894 5894
5895 5895 Returns 0 if push was successful, 1 if nothing to push.
5896 5896 """
5897 5897
5898 5898 if opts.get('bookmark'):
5899 5899 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5900 5900 for b in opts['bookmark']:
5901 5901 # translate -B options to -r so changesets get pushed
5902 5902 b = repo._bookmarks.expandname(b)
5903 5903 if b in repo._bookmarks:
5904 5904 opts.setdefault('rev', []).append(b)
5905 5905 else:
5906 5906 # if we try to push a deleted bookmark, translate it to null
5907 5907 # this lets simultaneous -r, -b options continue working
5908 5908 opts.setdefault('rev', []).append("null")
5909 5909
5910 5910 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5911 5911 if not path:
5912 5912 raise error.Abort(_('default repository not configured!'),
5913 5913 hint=_('see the "path" section in "hg help config"'))
5914 5914 dest = path.pushloc or path.loc
5915 5915 branches = (path.branch, opts.get('branch') or [])
5916 5916 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5917 5917 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5918 5918 other = hg.peer(repo, opts, dest)
5919 5919
5920 5920 if revs:
5921 5921 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5922 5922 if not revs:
5923 5923 raise error.Abort(_("specified revisions evaluate to an empty set"),
5924 5924 hint=_("use different revision arguments"))
5925 5925
5926 5926 repo._subtoppath = dest
5927 5927 try:
5928 5928 # push subrepos depth-first for coherent ordering
5929 5929 c = repo['']
5930 5930 subs = c.substate # only repos that are committed
5931 5931 for s in sorted(subs):
5932 5932 result = c.sub(s).push(opts)
5933 5933 if result == 0:
5934 5934 return not result
5935 5935 finally:
5936 5936 del repo._subtoppath
5937 5937 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5938 5938 newbranch=opts.get('new_branch'),
5939 5939 bookmarks=opts.get('bookmark', ()),
5940 5940 opargs=opts.get('opargs'))
5941 5941
5942 5942 result = not pushop.cgresult
5943 5943
5944 5944 if pushop.bkresult is not None:
5945 5945 if pushop.bkresult == 2:
5946 5946 result = 2
5947 5947 elif not result and pushop.bkresult:
5948 5948 result = 2
5949 5949
5950 5950 return result
5951 5951
5952 5952 @command('recover', [])
5953 5953 def recover(ui, repo):
5954 5954 """roll back an interrupted transaction
5955 5955
5956 5956 Recover from an interrupted commit or pull.
5957 5957
5958 5958 This command tries to fix the repository status after an
5959 5959 interrupted operation. It should only be necessary when Mercurial
5960 5960 suggests it.
5961 5961
5962 5962 Returns 0 if successful, 1 if nothing to recover or verify fails.
5963 5963 """
5964 5964 if repo.recover():
5965 5965 return hg.verify(repo)
5966 5966 return 1
5967 5967
5968 5968 @command('^remove|rm',
5969 5969 [('A', 'after', None, _('record delete for missing files')),
5970 5970 ('f', 'force', None,
5971 _('remove (and delete) file even if added or modified')),
5971 _('forget added files, delete modified files')),
5972 5972 ] + subrepoopts + walkopts,
5973 5973 _('[OPTION]... FILE...'),
5974 5974 inferrepo=True)
5975 5975 def remove(ui, repo, *pats, **opts):
5976 5976 """remove the specified files on the next commit
5977 5977
5978 5978 Schedule the indicated files for removal from the current branch.
5979 5979
5980 5980 This command schedules the files to be removed at the next commit.
5981 5981 To undo a remove before that, see :hg:`revert`. To undo added
5982 5982 files, see :hg:`forget`.
5983 5983
5984 5984 .. container:: verbose
5985 5985
5986 5986 -A/--after can be used to remove only files that have already
5987 5987 been deleted, -f/--force can be used to force deletion, and -Af
5988 5988 can be used to remove files from the next revision without
5989 5989 deleting them from the working directory.
5990 5990
5991 5991 The following table details the behavior of remove for different
5992 5992 file states (columns) and option combinations (rows). The file
5993 5993 states are Added [A], Clean [C], Modified [M] and Missing [!]
5994 5994 (as reported by :hg:`status`). The actions are Warn, Remove
5995 5995 (from branch) and Delete (from disk):
5996 5996
5997 5997 ========= == == == ==
5998 5998 opt/state A C M !
5999 5999 ========= == == == ==
6000 6000 none W RD W R
6001 6001 -f R RD RD R
6002 6002 -A W W W R
6003 6003 -Af R R R R
6004 6004 ========= == == == ==
6005 6005
6006 6006 .. note::
6007 6007
6008 6008 :hg:`remove` never deletes files in Added [A] state from the
6009 6009 working directory, not even if ``--force`` is specified.
6010 6010
6011 6011 Returns 0 on success, 1 if any warnings encountered.
6012 6012 """
6013 6013
6014 6014 after, force = opts.get('after'), opts.get('force')
6015 6015 if not pats and not after:
6016 6016 raise error.Abort(_('no files specified'))
6017 6017
6018 6018 m = scmutil.match(repo[None], pats, opts)
6019 6019 subrepos = opts.get('subrepos')
6020 6020 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6021 6021
6022 6022 @command('rename|move|mv',
6023 6023 [('A', 'after', None, _('record a rename that has already occurred')),
6024 6024 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6025 6025 ] + walkopts + dryrunopts,
6026 6026 _('[OPTION]... SOURCE... DEST'))
6027 6027 def rename(ui, repo, *pats, **opts):
6028 6028 """rename files; equivalent of copy + remove
6029 6029
6030 6030 Mark dest as copies of sources; mark sources for deletion. If dest
6031 6031 is a directory, copies are put in that directory. If dest is a
6032 6032 file, there can only be one source.
6033 6033
6034 6034 By default, this command copies the contents of files as they
6035 6035 exist in the working directory. If invoked with -A/--after, the
6036 6036 operation is recorded, but no copying is performed.
6037 6037
6038 6038 This command takes effect at the next commit. To undo a rename
6039 6039 before that, see :hg:`revert`.
6040 6040
6041 6041 Returns 0 on success, 1 if errors are encountered.
6042 6042 """
6043 6043 with repo.wlock(False):
6044 6044 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6045 6045
6046 6046 @command('resolve',
6047 6047 [('a', 'all', None, _('select all unresolved files')),
6048 6048 ('l', 'list', None, _('list state of files needing merge')),
6049 6049 ('m', 'mark', None, _('mark files as resolved')),
6050 6050 ('u', 'unmark', None, _('mark files as unresolved')),
6051 6051 ('n', 'no-status', None, _('hide status prefix'))]
6052 6052 + mergetoolopts + walkopts + formatteropts,
6053 6053 _('[OPTION]... [FILE]...'),
6054 6054 inferrepo=True)
6055 6055 def resolve(ui, repo, *pats, **opts):
6056 6056 """redo merges or set/view the merge status of files
6057 6057
6058 6058 Merges with unresolved conflicts are often the result of
6059 6059 non-interactive merging using the ``internal:merge`` configuration
6060 6060 setting, or a command-line merge tool like ``diff3``. The resolve
6061 6061 command is used to manage the files involved in a merge, after
6062 6062 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6063 6063 working directory must have two parents). See :hg:`help
6064 6064 merge-tools` for information on configuring merge tools.
6065 6065
6066 6066 The resolve command can be used in the following ways:
6067 6067
6068 6068 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6069 6069 files, discarding any previous merge attempts. Re-merging is not
6070 6070 performed for files already marked as resolved. Use ``--all/-a``
6071 6071 to select all unresolved files. ``--tool`` can be used to specify
6072 6072 the merge tool used for the given files. It overrides the HGMERGE
6073 6073 environment variable and your configuration files. Previous file
6074 6074 contents are saved with a ``.orig`` suffix.
6075 6075
6076 6076 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6077 6077 (e.g. after having manually fixed-up the files). The default is
6078 6078 to mark all unresolved files.
6079 6079
6080 6080 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6081 6081 default is to mark all resolved files.
6082 6082
6083 6083 - :hg:`resolve -l`: list files which had or still have conflicts.
6084 6084 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6085 6085
6086 6086 .. note::
6087 6087
6088 6088 Mercurial will not let you commit files with unresolved merge
6089 6089 conflicts. You must use :hg:`resolve -m ...` before you can
6090 6090 commit after a conflicting merge.
6091 6091
6092 6092 Returns 0 on success, 1 if any files fail a resolve attempt.
6093 6093 """
6094 6094
6095 6095 flaglist = 'all mark unmark list no_status'.split()
6096 6096 all, mark, unmark, show, nostatus = \
6097 6097 [opts.get(o) for o in flaglist]
6098 6098
6099 6099 if (show and (mark or unmark)) or (mark and unmark):
6100 6100 raise error.Abort(_("too many options specified"))
6101 6101 if pats and all:
6102 6102 raise error.Abort(_("can't specify --all and patterns"))
6103 6103 if not (all or pats or show or mark or unmark):
6104 6104 raise error.Abort(_('no files or directories specified'),
6105 6105 hint=('use --all to re-merge all unresolved files'))
6106 6106
6107 6107 if show:
6108 6108 fm = ui.formatter('resolve', opts)
6109 6109 ms = mergemod.mergestate.read(repo)
6110 6110 m = scmutil.match(repo[None], pats, opts)
6111 6111 for f in ms:
6112 6112 if not m(f):
6113 6113 continue
6114 6114 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6115 6115 'd': 'driverresolved'}[ms[f]]
6116 6116 fm.startitem()
6117 6117 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6118 6118 fm.write('path', '%s\n', f, label=l)
6119 6119 fm.end()
6120 6120 return 0
6121 6121
6122 6122 with repo.wlock():
6123 6123 ms = mergemod.mergestate.read(repo)
6124 6124
6125 6125 if not (ms.active() or repo.dirstate.p2() != nullid):
6126 6126 raise error.Abort(
6127 6127 _('resolve command not applicable when not merging'))
6128 6128
6129 6129 wctx = repo[None]
6130 6130
6131 6131 if ms.mergedriver and ms.mdstate() == 'u':
6132 6132 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6133 6133 ms.commit()
6134 6134 # allow mark and unmark to go through
6135 6135 if not mark and not unmark and not proceed:
6136 6136 return 1
6137 6137
6138 6138 m = scmutil.match(wctx, pats, opts)
6139 6139 ret = 0
6140 6140 didwork = False
6141 6141 runconclude = False
6142 6142
6143 6143 tocomplete = []
6144 6144 for f in ms:
6145 6145 if not m(f):
6146 6146 continue
6147 6147
6148 6148 didwork = True
6149 6149
6150 6150 # don't let driver-resolved files be marked, and run the conclude
6151 6151 # step if asked to resolve
6152 6152 if ms[f] == "d":
6153 6153 exact = m.exact(f)
6154 6154 if mark:
6155 6155 if exact:
6156 6156 ui.warn(_('not marking %s as it is driver-resolved\n')
6157 6157 % f)
6158 6158 elif unmark:
6159 6159 if exact:
6160 6160 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6161 6161 % f)
6162 6162 else:
6163 6163 runconclude = True
6164 6164 continue
6165 6165
6166 6166 if mark:
6167 6167 ms.mark(f, "r")
6168 6168 elif unmark:
6169 6169 ms.mark(f, "u")
6170 6170 else:
6171 6171 # backup pre-resolve (merge uses .orig for its own purposes)
6172 6172 a = repo.wjoin(f)
6173 6173 try:
6174 6174 util.copyfile(a, a + ".resolve")
6175 6175 except (IOError, OSError) as inst:
6176 6176 if inst.errno != errno.ENOENT:
6177 6177 raise
6178 6178
6179 6179 try:
6180 6180 # preresolve file
6181 6181 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6182 6182 'resolve')
6183 6183 complete, r = ms.preresolve(f, wctx)
6184 6184 if not complete:
6185 6185 tocomplete.append(f)
6186 6186 elif r:
6187 6187 ret = 1
6188 6188 finally:
6189 6189 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6190 6190 ms.commit()
6191 6191
6192 6192 # replace filemerge's .orig file with our resolve file, but only
6193 6193 # for merges that are complete
6194 6194 if complete:
6195 6195 try:
6196 6196 util.rename(a + ".resolve",
6197 6197 scmutil.origpath(ui, repo, a))
6198 6198 except OSError as inst:
6199 6199 if inst.errno != errno.ENOENT:
6200 6200 raise
6201 6201
6202 6202 for f in tocomplete:
6203 6203 try:
6204 6204 # resolve file
6205 6205 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6206 6206 'resolve')
6207 6207 r = ms.resolve(f, wctx)
6208 6208 if r:
6209 6209 ret = 1
6210 6210 finally:
6211 6211 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6212 6212 ms.commit()
6213 6213
6214 6214 # replace filemerge's .orig file with our resolve file
6215 6215 a = repo.wjoin(f)
6216 6216 try:
6217 6217 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6218 6218 except OSError as inst:
6219 6219 if inst.errno != errno.ENOENT:
6220 6220 raise
6221 6221
6222 6222 ms.commit()
6223 6223 ms.recordactions()
6224 6224
6225 6225 if not didwork and pats:
6226 6226 hint = None
6227 6227 if not any([p for p in pats if p.find(':') >= 0]):
6228 6228 pats = ['path:%s' % p for p in pats]
6229 6229 m = scmutil.match(wctx, pats, opts)
6230 6230 for f in ms:
6231 6231 if not m(f):
6232 6232 continue
6233 6233 flags = ''.join(['-%s ' % o[0] for o in flaglist
6234 6234 if opts.get(o)])
6235 6235 hint = _("(try: hg resolve %s%s)\n") % (
6236 6236 flags,
6237 6237 ' '.join(pats))
6238 6238 break
6239 6239 ui.warn(_("arguments do not match paths that need resolving\n"))
6240 6240 if hint:
6241 6241 ui.warn(hint)
6242 6242 elif ms.mergedriver and ms.mdstate() != 's':
6243 6243 # run conclude step when either a driver-resolved file is requested
6244 6244 # or there are no driver-resolved files
6245 6245 # we can't use 'ret' to determine whether any files are unresolved
6246 6246 # because we might not have tried to resolve some
6247 6247 if ((runconclude or not list(ms.driverresolved()))
6248 6248 and not list(ms.unresolved())):
6249 6249 proceed = mergemod.driverconclude(repo, ms, wctx)
6250 6250 ms.commit()
6251 6251 if not proceed:
6252 6252 return 1
6253 6253
6254 6254 # Nudge users into finishing an unfinished operation
6255 6255 unresolvedf = list(ms.unresolved())
6256 6256 driverresolvedf = list(ms.driverresolved())
6257 6257 if not unresolvedf and not driverresolvedf:
6258 6258 ui.status(_('(no more unresolved files)\n'))
6259 6259 cmdutil.checkafterresolved(repo)
6260 6260 elif not unresolvedf:
6261 6261 ui.status(_('(no more unresolved files -- '
6262 6262 'run "hg resolve --all" to conclude)\n'))
6263 6263
6264 6264 return ret
6265 6265
6266 6266 @command('revert',
6267 6267 [('a', 'all', None, _('revert all changes when no arguments given')),
6268 6268 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6269 6269 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6270 6270 ('C', 'no-backup', None, _('do not save backup copies of files')),
6271 6271 ('i', 'interactive', None,
6272 6272 _('interactively select the changes (EXPERIMENTAL)')),
6273 6273 ] + walkopts + dryrunopts,
6274 6274 _('[OPTION]... [-r REV] [NAME]...'))
6275 6275 def revert(ui, repo, *pats, **opts):
6276 6276 """restore files to their checkout state
6277 6277
6278 6278 .. note::
6279 6279
6280 6280 To check out earlier revisions, you should use :hg:`update REV`.
6281 6281 To cancel an uncommitted merge (and lose your changes),
6282 6282 use :hg:`update --clean .`.
6283 6283
6284 6284 With no revision specified, revert the specified files or directories
6285 6285 to the contents they had in the parent of the working directory.
6286 6286 This restores the contents of files to an unmodified
6287 6287 state and unschedules adds, removes, copies, and renames. If the
6288 6288 working directory has two parents, you must explicitly specify a
6289 6289 revision.
6290 6290
6291 6291 Using the -r/--rev or -d/--date options, revert the given files or
6292 6292 directories to their states as of a specific revision. Because
6293 6293 revert does not change the working directory parents, this will
6294 6294 cause these files to appear modified. This can be helpful to "back
6295 6295 out" some or all of an earlier change. See :hg:`backout` for a
6296 6296 related method.
6297 6297
6298 6298 Modified files are saved with a .orig suffix before reverting.
6299 6299 To disable these backups, use --no-backup.
6300 6300
6301 6301 See :hg:`help dates` for a list of formats valid for -d/--date.
6302 6302
6303 6303 See :hg:`help backout` for a way to reverse the effect of an
6304 6304 earlier changeset.
6305 6305
6306 6306 Returns 0 on success.
6307 6307 """
6308 6308
6309 6309 if opts.get("date"):
6310 6310 if opts.get("rev"):
6311 6311 raise error.Abort(_("you can't specify a revision and a date"))
6312 6312 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6313 6313
6314 6314 parent, p2 = repo.dirstate.parents()
6315 6315 if not opts.get('rev') and p2 != nullid:
6316 6316 # revert after merge is a trap for new users (issue2915)
6317 6317 raise error.Abort(_('uncommitted merge with no revision specified'),
6318 6318 hint=_('use "hg update" or see "hg help revert"'))
6319 6319
6320 6320 ctx = scmutil.revsingle(repo, opts.get('rev'))
6321 6321
6322 6322 if (not (pats or opts.get('include') or opts.get('exclude') or
6323 6323 opts.get('all') or opts.get('interactive'))):
6324 6324 msg = _("no files or directories specified")
6325 6325 if p2 != nullid:
6326 6326 hint = _("uncommitted merge, use --all to discard all changes,"
6327 6327 " or 'hg update -C .' to abort the merge")
6328 6328 raise error.Abort(msg, hint=hint)
6329 6329 dirty = any(repo.status())
6330 6330 node = ctx.node()
6331 6331 if node != parent:
6332 6332 if dirty:
6333 6333 hint = _("uncommitted changes, use --all to discard all"
6334 6334 " changes, or 'hg update %s' to update") % ctx.rev()
6335 6335 else:
6336 6336 hint = _("use --all to revert all files,"
6337 6337 " or 'hg update %s' to update") % ctx.rev()
6338 6338 elif dirty:
6339 6339 hint = _("uncommitted changes, use --all to discard all changes")
6340 6340 else:
6341 6341 hint = _("use --all to revert all files")
6342 6342 raise error.Abort(msg, hint=hint)
6343 6343
6344 6344 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6345 6345
6346 6346 @command('rollback', dryrunopts +
6347 6347 [('f', 'force', False, _('ignore safety measures'))])
6348 6348 def rollback(ui, repo, **opts):
6349 6349 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6350 6350
6351 6351 Please use :hg:`commit --amend` instead of rollback to correct
6352 6352 mistakes in the last commit.
6353 6353
6354 6354 This command should be used with care. There is only one level of
6355 6355 rollback, and there is no way to undo a rollback. It will also
6356 6356 restore the dirstate at the time of the last transaction, losing
6357 6357 any dirstate changes since that time. This command does not alter
6358 6358 the working directory.
6359 6359
6360 6360 Transactions are used to encapsulate the effects of all commands
6361 6361 that create new changesets or propagate existing changesets into a
6362 6362 repository.
6363 6363
6364 6364 .. container:: verbose
6365 6365
6366 6366 For example, the following commands are transactional, and their
6367 6367 effects can be rolled back:
6368 6368
6369 6369 - commit
6370 6370 - import
6371 6371 - pull
6372 6372 - push (with this repository as the destination)
6373 6373 - unbundle
6374 6374
6375 6375 To avoid permanent data loss, rollback will refuse to rollback a
6376 6376 commit transaction if it isn't checked out. Use --force to
6377 6377 override this protection.
6378 6378
6379 6379 This command is not intended for use on public repositories. Once
6380 6380 changes are visible for pull by other users, rolling a transaction
6381 6381 back locally is ineffective (someone else may already have pulled
6382 6382 the changes). Furthermore, a race is possible with readers of the
6383 6383 repository; for example an in-progress pull from the repository
6384 6384 may fail if a rollback is performed.
6385 6385
6386 6386 Returns 0 on success, 1 if no rollback data is available.
6387 6387 """
6388 6388 return repo.rollback(dryrun=opts.get('dry_run'),
6389 6389 force=opts.get('force'))
6390 6390
6391 6391 @command('root', [])
6392 6392 def root(ui, repo):
6393 6393 """print the root (top) of the current working directory
6394 6394
6395 6395 Print the root directory of the current repository.
6396 6396
6397 6397 Returns 0 on success.
6398 6398 """
6399 6399 ui.write(repo.root + "\n")
6400 6400
6401 6401 @command('^serve',
6402 6402 [('A', 'accesslog', '', _('name of access log file to write to'),
6403 6403 _('FILE')),
6404 6404 ('d', 'daemon', None, _('run server in background')),
6405 6405 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6406 6406 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6407 6407 # use string type, then we can check if something was passed
6408 6408 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6409 6409 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6410 6410 _('ADDR')),
6411 6411 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6412 6412 _('PREFIX')),
6413 6413 ('n', 'name', '',
6414 6414 _('name to show in web pages (default: working directory)'), _('NAME')),
6415 6415 ('', 'web-conf', '',
6416 6416 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6417 6417 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6418 6418 _('FILE')),
6419 6419 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6420 6420 ('', 'stdio', None, _('for remote clients')),
6421 6421 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6422 6422 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6423 6423 ('', 'style', '', _('template style to use'), _('STYLE')),
6424 6424 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6425 6425 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6426 6426 _('[OPTION]...'),
6427 6427 optionalrepo=True)
6428 6428 def serve(ui, repo, **opts):
6429 6429 """start stand-alone webserver
6430 6430
6431 6431 Start a local HTTP repository browser and pull server. You can use
6432 6432 this for ad-hoc sharing and browsing of repositories. It is
6433 6433 recommended to use a real web server to serve a repository for
6434 6434 longer periods of time.
6435 6435
6436 6436 Please note that the server does not implement access control.
6437 6437 This means that, by default, anybody can read from the server and
6438 6438 nobody can write to it by default. Set the ``web.allow_push``
6439 6439 option to ``*`` to allow everybody to push to the server. You
6440 6440 should use a real web server if you need to authenticate users.
6441 6441
6442 6442 By default, the server logs accesses to stdout and errors to
6443 6443 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6444 6444 files.
6445 6445
6446 6446 To have the server choose a free port number to listen on, specify
6447 6447 a port number of 0; in this case, the server will print the port
6448 6448 number it uses.
6449 6449
6450 6450 Returns 0 on success.
6451 6451 """
6452 6452
6453 6453 if opts["stdio"] and opts["cmdserver"]:
6454 6454 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6455 6455
6456 6456 if opts["stdio"]:
6457 6457 if repo is None:
6458 6458 raise error.RepoError(_("there is no Mercurial repository here"
6459 6459 " (.hg not found)"))
6460 6460 s = sshserver.sshserver(ui, repo)
6461 6461 s.serve_forever()
6462 6462
6463 6463 if opts["cmdserver"]:
6464 6464 service = commandserver.createservice(ui, repo, opts)
6465 6465 else:
6466 6466 service = hgweb.createservice(ui, repo, opts)
6467 6467 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6468 6468
6469 6469 @command('^status|st',
6470 6470 [('A', 'all', None, _('show status of all files')),
6471 6471 ('m', 'modified', None, _('show only modified files')),
6472 6472 ('a', 'added', None, _('show only added files')),
6473 6473 ('r', 'removed', None, _('show only removed files')),
6474 6474 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6475 6475 ('c', 'clean', None, _('show only files without changes')),
6476 6476 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6477 6477 ('i', 'ignored', None, _('show only ignored files')),
6478 6478 ('n', 'no-status', None, _('hide status prefix')),
6479 6479 ('C', 'copies', None, _('show source of copied files')),
6480 6480 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6481 6481 ('', 'rev', [], _('show difference from revision'), _('REV')),
6482 6482 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6483 6483 ] + walkopts + subrepoopts + formatteropts,
6484 6484 _('[OPTION]... [FILE]...'),
6485 6485 inferrepo=True)
6486 6486 def status(ui, repo, *pats, **opts):
6487 6487 """show changed files in the working directory
6488 6488
6489 6489 Show status of files in the repository. If names are given, only
6490 6490 files that match are shown. Files that are clean or ignored or
6491 6491 the source of a copy/move operation, are not listed unless
6492 6492 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6493 6493 Unless options described with "show only ..." are given, the
6494 6494 options -mardu are used.
6495 6495
6496 6496 Option -q/--quiet hides untracked (unknown and ignored) files
6497 6497 unless explicitly requested with -u/--unknown or -i/--ignored.
6498 6498
6499 6499 .. note::
6500 6500
6501 6501 :hg:`status` may appear to disagree with diff if permissions have
6502 6502 changed or a merge has occurred. The standard diff format does
6503 6503 not report permission changes and diff only reports changes
6504 6504 relative to one merge parent.
6505 6505
6506 6506 If one revision is given, it is used as the base revision.
6507 6507 If two revisions are given, the differences between them are
6508 6508 shown. The --change option can also be used as a shortcut to list
6509 6509 the changed files of a revision from its first parent.
6510 6510
6511 6511 The codes used to show the status of files are::
6512 6512
6513 6513 M = modified
6514 6514 A = added
6515 6515 R = removed
6516 6516 C = clean
6517 6517 ! = missing (deleted by non-hg command, but still tracked)
6518 6518 ? = not tracked
6519 6519 I = ignored
6520 6520 = origin of the previous file (with --copies)
6521 6521
6522 6522 .. container:: verbose
6523 6523
6524 6524 Examples:
6525 6525
6526 6526 - show changes in the working directory relative to a
6527 6527 changeset::
6528 6528
6529 6529 hg status --rev 9353
6530 6530
6531 6531 - show changes in the working directory relative to the
6532 6532 current directory (see :hg:`help patterns` for more information)::
6533 6533
6534 6534 hg status re:
6535 6535
6536 6536 - show all changes including copies in an existing changeset::
6537 6537
6538 6538 hg status --copies --change 9353
6539 6539
6540 6540 - get a NUL separated list of added files, suitable for xargs::
6541 6541
6542 6542 hg status -an0
6543 6543
6544 6544 Returns 0 on success.
6545 6545 """
6546 6546
6547 6547 revs = opts.get('rev')
6548 6548 change = opts.get('change')
6549 6549
6550 6550 if revs and change:
6551 6551 msg = _('cannot specify --rev and --change at the same time')
6552 6552 raise error.Abort(msg)
6553 6553 elif change:
6554 6554 node2 = scmutil.revsingle(repo, change, None).node()
6555 6555 node1 = repo[node2].p1().node()
6556 6556 else:
6557 6557 node1, node2 = scmutil.revpair(repo, revs)
6558 6558
6559 6559 if pats:
6560 6560 cwd = repo.getcwd()
6561 6561 else:
6562 6562 cwd = ''
6563 6563
6564 6564 if opts.get('print0'):
6565 6565 end = '\0'
6566 6566 else:
6567 6567 end = '\n'
6568 6568 copy = {}
6569 6569 states = 'modified added removed deleted unknown ignored clean'.split()
6570 6570 show = [k for k in states if opts.get(k)]
6571 6571 if opts.get('all'):
6572 6572 show += ui.quiet and (states[:4] + ['clean']) or states
6573 6573 if not show:
6574 6574 if ui.quiet:
6575 6575 show = states[:4]
6576 6576 else:
6577 6577 show = states[:5]
6578 6578
6579 6579 m = scmutil.match(repo[node2], pats, opts)
6580 6580 stat = repo.status(node1, node2, m,
6581 6581 'ignored' in show, 'clean' in show, 'unknown' in show,
6582 6582 opts.get('subrepos'))
6583 6583 changestates = zip(states, 'MAR!?IC', stat)
6584 6584
6585 6585 if (opts.get('all') or opts.get('copies')
6586 6586 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6587 6587 copy = copies.pathcopies(repo[node1], repo[node2], m)
6588 6588
6589 6589 fm = ui.formatter('status', opts)
6590 6590 fmt = '%s' + end
6591 6591 showchar = not opts.get('no_status')
6592 6592
6593 6593 for state, char, files in changestates:
6594 6594 if state in show:
6595 6595 label = 'status.' + state
6596 6596 for f in files:
6597 6597 fm.startitem()
6598 6598 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6599 6599 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6600 6600 if f in copy:
6601 6601 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6602 6602 label='status.copied')
6603 6603 fm.end()
6604 6604
6605 6605 @command('^summary|sum',
6606 6606 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6607 6607 def summary(ui, repo, **opts):
6608 6608 """summarize working directory state
6609 6609
6610 6610 This generates a brief summary of the working directory state,
6611 6611 including parents, branch, commit status, phase and available updates.
6612 6612
6613 6613 With the --remote option, this will check the default paths for
6614 6614 incoming and outgoing changes. This can be time-consuming.
6615 6615
6616 6616 Returns 0 on success.
6617 6617 """
6618 6618
6619 6619 ctx = repo[None]
6620 6620 parents = ctx.parents()
6621 6621 pnode = parents[0].node()
6622 6622 marks = []
6623 6623
6624 6624 ms = None
6625 6625 try:
6626 6626 ms = mergemod.mergestate.read(repo)
6627 6627 except error.UnsupportedMergeRecords as e:
6628 6628 s = ' '.join(e.recordtypes)
6629 6629 ui.warn(
6630 6630 _('warning: merge state has unsupported record types: %s\n') % s)
6631 6631 unresolved = 0
6632 6632 else:
6633 6633 unresolved = [f for f in ms if ms[f] == 'u']
6634 6634
6635 6635 for p in parents:
6636 6636 # label with log.changeset (instead of log.parent) since this
6637 6637 # shows a working directory parent *changeset*:
6638 6638 # i18n: column positioning for "hg summary"
6639 6639 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6640 6640 label='log.changeset changeset.%s' % p.phasestr())
6641 6641 ui.write(' '.join(p.tags()), label='log.tag')
6642 6642 if p.bookmarks():
6643 6643 marks.extend(p.bookmarks())
6644 6644 if p.rev() == -1:
6645 6645 if not len(repo):
6646 6646 ui.write(_(' (empty repository)'))
6647 6647 else:
6648 6648 ui.write(_(' (no revision checked out)'))
6649 6649 ui.write('\n')
6650 6650 if p.description():
6651 6651 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6652 6652 label='log.summary')
6653 6653
6654 6654 branch = ctx.branch()
6655 6655 bheads = repo.branchheads(branch)
6656 6656 # i18n: column positioning for "hg summary"
6657 6657 m = _('branch: %s\n') % branch
6658 6658 if branch != 'default':
6659 6659 ui.write(m, label='log.branch')
6660 6660 else:
6661 6661 ui.status(m, label='log.branch')
6662 6662
6663 6663 if marks:
6664 6664 active = repo._activebookmark
6665 6665 # i18n: column positioning for "hg summary"
6666 6666 ui.write(_('bookmarks:'), label='log.bookmark')
6667 6667 if active is not None:
6668 6668 if active in marks:
6669 6669 ui.write(' *' + active, label=activebookmarklabel)
6670 6670 marks.remove(active)
6671 6671 else:
6672 6672 ui.write(' [%s]' % active, label=activebookmarklabel)
6673 6673 for m in marks:
6674 6674 ui.write(' ' + m, label='log.bookmark')
6675 6675 ui.write('\n', label='log.bookmark')
6676 6676
6677 6677 status = repo.status(unknown=True)
6678 6678
6679 6679 c = repo.dirstate.copies()
6680 6680 copied, renamed = [], []
6681 6681 for d, s in c.iteritems():
6682 6682 if s in status.removed:
6683 6683 status.removed.remove(s)
6684 6684 renamed.append(d)
6685 6685 else:
6686 6686 copied.append(d)
6687 6687 if d in status.added:
6688 6688 status.added.remove(d)
6689 6689
6690 6690 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6691 6691
6692 6692 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6693 6693 (ui.label(_('%d added'), 'status.added'), status.added),
6694 6694 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6695 6695 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6696 6696 (ui.label(_('%d copied'), 'status.copied'), copied),
6697 6697 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6698 6698 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6699 6699 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6700 6700 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6701 6701 t = []
6702 6702 for l, s in labels:
6703 6703 if s:
6704 6704 t.append(l % len(s))
6705 6705
6706 6706 t = ', '.join(t)
6707 6707 cleanworkdir = False
6708 6708
6709 6709 if repo.vfs.exists('graftstate'):
6710 6710 t += _(' (graft in progress)')
6711 6711 if repo.vfs.exists('updatestate'):
6712 6712 t += _(' (interrupted update)')
6713 6713 elif len(parents) > 1:
6714 6714 t += _(' (merge)')
6715 6715 elif branch != parents[0].branch():
6716 6716 t += _(' (new branch)')
6717 6717 elif (parents[0].closesbranch() and
6718 6718 pnode in repo.branchheads(branch, closed=True)):
6719 6719 t += _(' (head closed)')
6720 6720 elif not (status.modified or status.added or status.removed or renamed or
6721 6721 copied or subs):
6722 6722 t += _(' (clean)')
6723 6723 cleanworkdir = True
6724 6724 elif pnode not in bheads:
6725 6725 t += _(' (new branch head)')
6726 6726
6727 6727 if parents:
6728 6728 pendingphase = max(p.phase() for p in parents)
6729 6729 else:
6730 6730 pendingphase = phases.public
6731 6731
6732 6732 if pendingphase > phases.newcommitphase(ui):
6733 6733 t += ' (%s)' % phases.phasenames[pendingphase]
6734 6734
6735 6735 if cleanworkdir:
6736 6736 # i18n: column positioning for "hg summary"
6737 6737 ui.status(_('commit: %s\n') % t.strip())
6738 6738 else:
6739 6739 # i18n: column positioning for "hg summary"
6740 6740 ui.write(_('commit: %s\n') % t.strip())
6741 6741
6742 6742 # all ancestors of branch heads - all ancestors of parent = new csets
6743 6743 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6744 6744 bheads))
6745 6745
6746 6746 if new == 0:
6747 6747 # i18n: column positioning for "hg summary"
6748 6748 ui.status(_('update: (current)\n'))
6749 6749 elif pnode not in bheads:
6750 6750 # i18n: column positioning for "hg summary"
6751 6751 ui.write(_('update: %d new changesets (update)\n') % new)
6752 6752 else:
6753 6753 # i18n: column positioning for "hg summary"
6754 6754 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6755 6755 (new, len(bheads)))
6756 6756
6757 6757 t = []
6758 6758 draft = len(repo.revs('draft()'))
6759 6759 if draft:
6760 6760 t.append(_('%d draft') % draft)
6761 6761 secret = len(repo.revs('secret()'))
6762 6762 if secret:
6763 6763 t.append(_('%d secret') % secret)
6764 6764
6765 6765 if draft or secret:
6766 6766 ui.status(_('phases: %s\n') % ', '.join(t))
6767 6767
6768 6768 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6769 6769 for trouble in ("unstable", "divergent", "bumped"):
6770 6770 numtrouble = len(repo.revs(trouble + "()"))
6771 6771 # We write all the possibilities to ease translation
6772 6772 troublemsg = {
6773 6773 "unstable": _("unstable: %d changesets"),
6774 6774 "divergent": _("divergent: %d changesets"),
6775 6775 "bumped": _("bumped: %d changesets"),
6776 6776 }
6777 6777 if numtrouble > 0:
6778 6778 ui.status(troublemsg[trouble] % numtrouble + "\n")
6779 6779
6780 6780 cmdutil.summaryhooks(ui, repo)
6781 6781
6782 6782 if opts.get('remote'):
6783 6783 needsincoming, needsoutgoing = True, True
6784 6784 else:
6785 6785 needsincoming, needsoutgoing = False, False
6786 6786 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6787 6787 if i:
6788 6788 needsincoming = True
6789 6789 if o:
6790 6790 needsoutgoing = True
6791 6791 if not needsincoming and not needsoutgoing:
6792 6792 return
6793 6793
6794 6794 def getincoming():
6795 6795 source, branches = hg.parseurl(ui.expandpath('default'))
6796 6796 sbranch = branches[0]
6797 6797 try:
6798 6798 other = hg.peer(repo, {}, source)
6799 6799 except error.RepoError:
6800 6800 if opts.get('remote'):
6801 6801 raise
6802 6802 return source, sbranch, None, None, None
6803 6803 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6804 6804 if revs:
6805 6805 revs = [other.lookup(rev) for rev in revs]
6806 6806 ui.debug('comparing with %s\n' % util.hidepassword(source))
6807 6807 repo.ui.pushbuffer()
6808 6808 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6809 6809 repo.ui.popbuffer()
6810 6810 return source, sbranch, other, commoninc, commoninc[1]
6811 6811
6812 6812 if needsincoming:
6813 6813 source, sbranch, sother, commoninc, incoming = getincoming()
6814 6814 else:
6815 6815 source = sbranch = sother = commoninc = incoming = None
6816 6816
6817 6817 def getoutgoing():
6818 6818 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6819 6819 dbranch = branches[0]
6820 6820 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6821 6821 if source != dest:
6822 6822 try:
6823 6823 dother = hg.peer(repo, {}, dest)
6824 6824 except error.RepoError:
6825 6825 if opts.get('remote'):
6826 6826 raise
6827 6827 return dest, dbranch, None, None
6828 6828 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6829 6829 elif sother is None:
6830 6830 # there is no explicit destination peer, but source one is invalid
6831 6831 return dest, dbranch, None, None
6832 6832 else:
6833 6833 dother = sother
6834 6834 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6835 6835 common = None
6836 6836 else:
6837 6837 common = commoninc
6838 6838 if revs:
6839 6839 revs = [repo.lookup(rev) for rev in revs]
6840 6840 repo.ui.pushbuffer()
6841 6841 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6842 6842 commoninc=common)
6843 6843 repo.ui.popbuffer()
6844 6844 return dest, dbranch, dother, outgoing
6845 6845
6846 6846 if needsoutgoing:
6847 6847 dest, dbranch, dother, outgoing = getoutgoing()
6848 6848 else:
6849 6849 dest = dbranch = dother = outgoing = None
6850 6850
6851 6851 if opts.get('remote'):
6852 6852 t = []
6853 6853 if incoming:
6854 6854 t.append(_('1 or more incoming'))
6855 6855 o = outgoing.missing
6856 6856 if o:
6857 6857 t.append(_('%d outgoing') % len(o))
6858 6858 other = dother or sother
6859 6859 if 'bookmarks' in other.listkeys('namespaces'):
6860 6860 counts = bookmarks.summary(repo, other)
6861 6861 if counts[0] > 0:
6862 6862 t.append(_('%d incoming bookmarks') % counts[0])
6863 6863 if counts[1] > 0:
6864 6864 t.append(_('%d outgoing bookmarks') % counts[1])
6865 6865
6866 6866 if t:
6867 6867 # i18n: column positioning for "hg summary"
6868 6868 ui.write(_('remote: %s\n') % (', '.join(t)))
6869 6869 else:
6870 6870 # i18n: column positioning for "hg summary"
6871 6871 ui.status(_('remote: (synced)\n'))
6872 6872
6873 6873 cmdutil.summaryremotehooks(ui, repo, opts,
6874 6874 ((source, sbranch, sother, commoninc),
6875 6875 (dest, dbranch, dother, outgoing)))
6876 6876
6877 6877 @command('tag',
6878 6878 [('f', 'force', None, _('force tag')),
6879 6879 ('l', 'local', None, _('make the tag local')),
6880 6880 ('r', 'rev', '', _('revision to tag'), _('REV')),
6881 6881 ('', 'remove', None, _('remove a tag')),
6882 6882 # -l/--local is already there, commitopts cannot be used
6883 6883 ('e', 'edit', None, _('invoke editor on commit messages')),
6884 6884 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6885 6885 ] + commitopts2,
6886 6886 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6887 6887 def tag(ui, repo, name1, *names, **opts):
6888 6888 """add one or more tags for the current or given revision
6889 6889
6890 6890 Name a particular revision using <name>.
6891 6891
6892 6892 Tags are used to name particular revisions of the repository and are
6893 6893 very useful to compare different revisions, to go back to significant
6894 6894 earlier versions or to mark branch points as releases, etc. Changing
6895 6895 an existing tag is normally disallowed; use -f/--force to override.
6896 6896
6897 6897 If no revision is given, the parent of the working directory is
6898 6898 used.
6899 6899
6900 6900 To facilitate version control, distribution, and merging of tags,
6901 6901 they are stored as a file named ".hgtags" which is managed similarly
6902 6902 to other project files and can be hand-edited if necessary. This
6903 6903 also means that tagging creates a new commit. The file
6904 6904 ".hg/localtags" is used for local tags (not shared among
6905 6905 repositories).
6906 6906
6907 6907 Tag commits are usually made at the head of a branch. If the parent
6908 6908 of the working directory is not a branch head, :hg:`tag` aborts; use
6909 6909 -f/--force to force the tag commit to be based on a non-head
6910 6910 changeset.
6911 6911
6912 6912 See :hg:`help dates` for a list of formats valid for -d/--date.
6913 6913
6914 6914 Since tag names have priority over branch names during revision
6915 6915 lookup, using an existing branch name as a tag name is discouraged.
6916 6916
6917 6917 Returns 0 on success.
6918 6918 """
6919 6919 wlock = lock = None
6920 6920 try:
6921 6921 wlock = repo.wlock()
6922 6922 lock = repo.lock()
6923 6923 rev_ = "."
6924 6924 names = [t.strip() for t in (name1,) + names]
6925 6925 if len(names) != len(set(names)):
6926 6926 raise error.Abort(_('tag names must be unique'))
6927 6927 for n in names:
6928 6928 scmutil.checknewlabel(repo, n, 'tag')
6929 6929 if not n:
6930 6930 raise error.Abort(_('tag names cannot consist entirely of '
6931 6931 'whitespace'))
6932 6932 if opts.get('rev') and opts.get('remove'):
6933 6933 raise error.Abort(_("--rev and --remove are incompatible"))
6934 6934 if opts.get('rev'):
6935 6935 rev_ = opts['rev']
6936 6936 message = opts.get('message')
6937 6937 if opts.get('remove'):
6938 6938 if opts.get('local'):
6939 6939 expectedtype = 'local'
6940 6940 else:
6941 6941 expectedtype = 'global'
6942 6942
6943 6943 for n in names:
6944 6944 if not repo.tagtype(n):
6945 6945 raise error.Abort(_("tag '%s' does not exist") % n)
6946 6946 if repo.tagtype(n) != expectedtype:
6947 6947 if expectedtype == 'global':
6948 6948 raise error.Abort(_("tag '%s' is not a global tag") % n)
6949 6949 else:
6950 6950 raise error.Abort(_("tag '%s' is not a local tag") % n)
6951 6951 rev_ = 'null'
6952 6952 if not message:
6953 6953 # we don't translate commit messages
6954 6954 message = 'Removed tag %s' % ', '.join(names)
6955 6955 elif not opts.get('force'):
6956 6956 for n in names:
6957 6957 if n in repo.tags():
6958 6958 raise error.Abort(_("tag '%s' already exists "
6959 6959 "(use -f to force)") % n)
6960 6960 if not opts.get('local'):
6961 6961 p1, p2 = repo.dirstate.parents()
6962 6962 if p2 != nullid:
6963 6963 raise error.Abort(_('uncommitted merge'))
6964 6964 bheads = repo.branchheads()
6965 6965 if not opts.get('force') and bheads and p1 not in bheads:
6966 6966 raise error.Abort(_('not at a branch head (use -f to force)'))
6967 6967 r = scmutil.revsingle(repo, rev_).node()
6968 6968
6969 6969 if not message:
6970 6970 # we don't translate commit messages
6971 6971 message = ('Added tag %s for changeset %s' %
6972 6972 (', '.join(names), short(r)))
6973 6973
6974 6974 date = opts.get('date')
6975 6975 if date:
6976 6976 date = util.parsedate(date)
6977 6977
6978 6978 if opts.get('remove'):
6979 6979 editform = 'tag.remove'
6980 6980 else:
6981 6981 editform = 'tag.add'
6982 6982 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6983 6983
6984 6984 # don't allow tagging the null rev
6985 6985 if (not opts.get('remove') and
6986 6986 scmutil.revsingle(repo, rev_).rev() == nullrev):
6987 6987 raise error.Abort(_("cannot tag null revision"))
6988 6988
6989 6989 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6990 6990 editor=editor)
6991 6991 finally:
6992 6992 release(lock, wlock)
6993 6993
6994 6994 @command('tags', formatteropts, '')
6995 6995 def tags(ui, repo, **opts):
6996 6996 """list repository tags
6997 6997
6998 6998 This lists both regular and local tags. When the -v/--verbose
6999 6999 switch is used, a third column "local" is printed for local tags.
7000 7000 When the -q/--quiet switch is used, only the tag name is printed.
7001 7001
7002 7002 Returns 0 on success.
7003 7003 """
7004 7004
7005 7005 fm = ui.formatter('tags', opts)
7006 7006 hexfunc = fm.hexfunc
7007 7007 tagtype = ""
7008 7008
7009 7009 for t, n in reversed(repo.tagslist()):
7010 7010 hn = hexfunc(n)
7011 7011 label = 'tags.normal'
7012 7012 tagtype = ''
7013 7013 if repo.tagtype(t) == 'local':
7014 7014 label = 'tags.local'
7015 7015 tagtype = 'local'
7016 7016
7017 7017 fm.startitem()
7018 7018 fm.write('tag', '%s', t, label=label)
7019 7019 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7020 7020 fm.condwrite(not ui.quiet, 'rev node', fmt,
7021 7021 repo.changelog.rev(n), hn, label=label)
7022 7022 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7023 7023 tagtype, label=label)
7024 7024 fm.plain('\n')
7025 7025 fm.end()
7026 7026
7027 7027 @command('tip',
7028 7028 [('p', 'patch', None, _('show patch')),
7029 7029 ('g', 'git', None, _('use git extended diff format')),
7030 7030 ] + templateopts,
7031 7031 _('[-p] [-g]'))
7032 7032 def tip(ui, repo, **opts):
7033 7033 """show the tip revision (DEPRECATED)
7034 7034
7035 7035 The tip revision (usually just called the tip) is the changeset
7036 7036 most recently added to the repository (and therefore the most
7037 7037 recently changed head).
7038 7038
7039 7039 If you have just made a commit, that commit will be the tip. If
7040 7040 you have just pulled changes from another repository, the tip of
7041 7041 that repository becomes the current tip. The "tip" tag is special
7042 7042 and cannot be renamed or assigned to a different changeset.
7043 7043
7044 7044 This command is deprecated, please use :hg:`heads` instead.
7045 7045
7046 7046 Returns 0 on success.
7047 7047 """
7048 7048 displayer = cmdutil.show_changeset(ui, repo, opts)
7049 7049 displayer.show(repo['tip'])
7050 7050 displayer.close()
7051 7051
7052 7052 @command('unbundle',
7053 7053 [('u', 'update', None,
7054 7054 _('update to new branch head if changesets were unbundled'))],
7055 7055 _('[-u] FILE...'))
7056 7056 def unbundle(ui, repo, fname1, *fnames, **opts):
7057 7057 """apply one or more changegroup files
7058 7058
7059 7059 Apply one or more compressed changegroup files generated by the
7060 7060 bundle command.
7061 7061
7062 7062 Returns 0 on success, 1 if an update has unresolved files.
7063 7063 """
7064 7064 fnames = (fname1,) + fnames
7065 7065
7066 7066 with repo.lock():
7067 7067 for fname in fnames:
7068 7068 f = hg.openpath(ui, fname)
7069 7069 gen = exchange.readbundle(ui, f, fname)
7070 7070 if isinstance(gen, bundle2.unbundle20):
7071 7071 tr = repo.transaction('unbundle')
7072 7072 try:
7073 7073 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7074 7074 url='bundle:' + fname)
7075 7075 tr.close()
7076 7076 except error.BundleUnknownFeatureError as exc:
7077 7077 raise error.Abort(_('%s: unknown bundle feature, %s')
7078 7078 % (fname, exc),
7079 7079 hint=_("see https://mercurial-scm.org/"
7080 7080 "wiki/BundleFeature for more "
7081 7081 "information"))
7082 7082 finally:
7083 7083 if tr:
7084 7084 tr.release()
7085 7085 changes = [r.get('return', 0)
7086 7086 for r in op.records['changegroup']]
7087 7087 modheads = changegroup.combineresults(changes)
7088 7088 elif isinstance(gen, streamclone.streamcloneapplier):
7089 7089 raise error.Abort(
7090 7090 _('packed bundles cannot be applied with '
7091 7091 '"hg unbundle"'),
7092 7092 hint=_('use "hg debugapplystreamclonebundle"'))
7093 7093 else:
7094 7094 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7095 7095
7096 7096 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7097 7097
7098 7098 @command('^update|up|checkout|co',
7099 7099 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7100 7100 ('c', 'check', None,
7101 7101 _('update across branches if no uncommitted changes')),
7102 7102 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7103 7103 ('r', 'rev', '', _('revision'), _('REV'))
7104 7104 ] + mergetoolopts,
7105 7105 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7106 7106 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7107 7107 tool=None):
7108 7108 """update working directory (or switch revisions)
7109 7109
7110 7110 Update the repository's working directory to the specified
7111 7111 changeset. If no changeset is specified, update to the tip of the
7112 7112 current named branch and move the active bookmark (see :hg:`help
7113 7113 bookmarks`).
7114 7114
7115 7115 Update sets the working directory's parent revision to the specified
7116 7116 changeset (see :hg:`help parents`).
7117 7117
7118 7118 If the changeset is not a descendant or ancestor of the working
7119 7119 directory's parent, the update is aborted. With the -c/--check
7120 7120 option, the working directory is checked for uncommitted changes; if
7121 7121 none are found, the working directory is updated to the specified
7122 7122 changeset.
7123 7123
7124 7124 .. container:: verbose
7125 7125
7126 7126 The following rules apply when the working directory contains
7127 7127 uncommitted changes:
7128 7128
7129 7129 1. If neither -c/--check nor -C/--clean is specified, and if
7130 7130 the requested changeset is an ancestor or descendant of
7131 7131 the working directory's parent, the uncommitted changes
7132 7132 are merged into the requested changeset and the merged
7133 7133 result is left uncommitted. If the requested changeset is
7134 7134 not an ancestor or descendant (that is, it is on another
7135 7135 branch), the update is aborted and the uncommitted changes
7136 7136 are preserved.
7137 7137
7138 7138 2. With the -c/--check option, the update is aborted and the
7139 7139 uncommitted changes are preserved.
7140 7140
7141 7141 3. With the -C/--clean option, uncommitted changes are discarded and
7142 7142 the working directory is updated to the requested changeset.
7143 7143
7144 7144 To cancel an uncommitted merge (and lose your changes), use
7145 7145 :hg:`update --clean .`.
7146 7146
7147 7147 Use null as the changeset to remove the working directory (like
7148 7148 :hg:`clone -U`).
7149 7149
7150 7150 If you want to revert just one file to an older revision, use
7151 7151 :hg:`revert [-r REV] NAME`.
7152 7152
7153 7153 See :hg:`help dates` for a list of formats valid for -d/--date.
7154 7154
7155 7155 Returns 0 on success, 1 if there are unresolved files.
7156 7156 """
7157 7157 if rev and node:
7158 7158 raise error.Abort(_("please specify just one revision"))
7159 7159
7160 7160 if rev is None or rev == '':
7161 7161 rev = node
7162 7162
7163 7163 if date and rev is not None:
7164 7164 raise error.Abort(_("you can't specify a revision and a date"))
7165 7165
7166 7166 if check and clean:
7167 7167 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7168 7168
7169 7169 with repo.wlock():
7170 7170 cmdutil.clearunfinished(repo)
7171 7171
7172 7172 if date:
7173 7173 rev = cmdutil.finddate(ui, repo, date)
7174 7174
7175 7175 # if we defined a bookmark, we have to remember the original name
7176 7176 brev = rev
7177 7177 rev = scmutil.revsingle(repo, rev, rev).rev()
7178 7178
7179 7179 if check:
7180 7180 cmdutil.bailifchanged(repo, merge=False)
7181 7181
7182 7182 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7183 7183
7184 7184 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7185 7185
7186 7186 @command('verify', [])
7187 7187 def verify(ui, repo):
7188 7188 """verify the integrity of the repository
7189 7189
7190 7190 Verify the integrity of the current repository.
7191 7191
7192 7192 This will perform an extensive check of the repository's
7193 7193 integrity, validating the hashes and checksums of each entry in
7194 7194 the changelog, manifest, and tracked files, as well as the
7195 7195 integrity of their crosslinks and indices.
7196 7196
7197 7197 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7198 7198 for more information about recovery from corruption of the
7199 7199 repository.
7200 7200
7201 7201 Returns 0 on success, 1 if errors are encountered.
7202 7202 """
7203 7203 return hg.verify(repo)
7204 7204
7205 7205 @command('version', [], norepo=True)
7206 7206 def version_(ui):
7207 7207 """output version and copyright information"""
7208 7208 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7209 7209 % util.version())
7210 7210 ui.status(_(
7211 7211 "(see https://mercurial-scm.org for more information)\n"
7212 7212 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7213 7213 "This is free software; see the source for copying conditions. "
7214 7214 "There is NO\nwarranty; "
7215 7215 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7216 7216 ))
7217 7217
7218 7218 ui.note(_("\nEnabled extensions:\n\n"))
7219 7219 if ui.verbose:
7220 7220 # format names and versions into columns
7221 7221 names = []
7222 7222 vers = []
7223 7223 place = []
7224 7224 for name, module in extensions.extensions():
7225 7225 names.append(name)
7226 7226 vers.append(extensions.moduleversion(module))
7227 7227 if extensions.ismoduleinternal(module):
7228 7228 place.append(_("internal"))
7229 7229 else:
7230 7230 place.append(_("external"))
7231 7231 if names:
7232 7232 maxnamelen = max(len(n) for n in names)
7233 7233 for i, name in enumerate(names):
7234 7234 ui.write(" %-*s %s %s\n" %
7235 7235 (maxnamelen, name, place[i], vers[i]))
7236 7236
7237 7237 def loadcmdtable(ui, name, cmdtable):
7238 7238 """Load command functions from specified cmdtable
7239 7239 """
7240 7240 overrides = [cmd for cmd in cmdtable if cmd in table]
7241 7241 if overrides:
7242 7242 ui.warn(_("extension '%s' overrides commands: %s\n")
7243 7243 % (name, " ".join(overrides)))
7244 7244 table.update(cmdtable)
@@ -1,3057 +1,3057
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use "hg help" for the full list of commands or "hg -v" for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks create a new bookmark or list existing bookmarks
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 files list tracked files
70 70 forget forget the specified files on the next commit
71 71 graft copy changes from other branches onto the current branch
72 72 grep search for a pattern in specified files and revisions
73 73 heads show branch heads
74 74 help show help for a given topic or a help overview
75 75 identify identify the working directory or specified revision
76 76 import import an ordered set of patches
77 77 incoming show new changesets found in source
78 78 init create a new repository in the given directory
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge another revision into working directory
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 diffs Diff Formats
108 108 environment Environment Variables
109 109 extensions Using Additional Features
110 110 filesets Specifying File Sets
111 111 glossary Glossary
112 112 hgignore Syntax for Mercurial Ignore Files
113 113 hgweb Configuring hgweb
114 114 internals Technical implementation topics
115 115 merge-tools Merge Tools
116 116 multirevs Specifying Multiple Revisions
117 117 patterns File Name Patterns
118 118 phases Working with Phases
119 119 revisions Specifying Single Revisions
120 120 revsets Specifying Revision Sets
121 121 scripting Using Mercurial from scripts and automation
122 122 subrepos Subrepositories
123 123 templating Template Usage
124 124 urls URL Paths
125 125
126 126 (use "hg help -v" to show built-in aliases and global options)
127 127
128 128 $ hg -q help
129 129 add add the specified files on the next commit
130 130 addremove add all new files, delete all missing files
131 131 annotate show changeset information by line for each file
132 132 archive create an unversioned archive of a repository revision
133 133 backout reverse effect of earlier changeset
134 134 bisect subdivision search of changesets
135 135 bookmarks create a new bookmark or list existing bookmarks
136 136 branch set or show the current branch name
137 137 branches list repository named branches
138 138 bundle create a changegroup file
139 139 cat output the current or given revision of files
140 140 clone make a copy of an existing repository
141 141 commit commit the specified files or all outstanding changes
142 142 config show combined config settings from all hgrc files
143 143 copy mark files as copied for the next commit
144 144 diff diff repository (or selected files)
145 145 export dump the header and diffs for one or more changesets
146 146 files list tracked files
147 147 forget forget the specified files on the next commit
148 148 graft copy changes from other branches onto the current branch
149 149 grep search for a pattern in specified files and revisions
150 150 heads show branch heads
151 151 help show help for a given topic or a help overview
152 152 identify identify the working directory or specified revision
153 153 import import an ordered set of patches
154 154 incoming show new changesets found in source
155 155 init create a new repository in the given directory
156 156 log show revision history of entire repository or files
157 157 manifest output the current or given revision of the project manifest
158 158 merge merge another revision into working directory
159 159 outgoing show changesets not found in the destination
160 160 paths show aliases for remote repositories
161 161 phase set or show the current phase name
162 162 pull pull changes from the specified source
163 163 push push changes to the specified destination
164 164 recover roll back an interrupted transaction
165 165 remove remove the specified files on the next commit
166 166 rename rename files; equivalent of copy + remove
167 167 resolve redo merges or set/view the merge status of files
168 168 revert restore files to their checkout state
169 169 root print the root (top) of the current working directory
170 170 serve start stand-alone webserver
171 171 status show changed files in the working directory
172 172 summary summarize working directory state
173 173 tag add one or more tags for the current or given revision
174 174 tags list repository tags
175 175 unbundle apply one or more changegroup files
176 176 update update working directory (or switch revisions)
177 177 verify verify the integrity of the repository
178 178 version output version and copyright information
179 179
180 180 additional help topics:
181 181
182 182 config Configuration Files
183 183 dates Date Formats
184 184 diffs Diff Formats
185 185 environment Environment Variables
186 186 extensions Using Additional Features
187 187 filesets Specifying File Sets
188 188 glossary Glossary
189 189 hgignore Syntax for Mercurial Ignore Files
190 190 hgweb Configuring hgweb
191 191 internals Technical implementation topics
192 192 merge-tools Merge Tools
193 193 multirevs Specifying Multiple Revisions
194 194 patterns File Name Patterns
195 195 phases Working with Phases
196 196 revisions Specifying Single Revisions
197 197 revsets Specifying Revision Sets
198 198 scripting Using Mercurial from scripts and automation
199 199 subrepos Subrepositories
200 200 templating Template Usage
201 201 urls URL Paths
202 202
203 203 Test extension help:
204 204 $ hg help extensions --config extensions.rebase= --config extensions.children=
205 205 Using Additional Features
206 206 """""""""""""""""""""""""
207 207
208 208 Mercurial has the ability to add new features through the use of
209 209 extensions. Extensions may add new commands, add options to existing
210 210 commands, change the default behavior of commands, or implement hooks.
211 211
212 212 To enable the "foo" extension, either shipped with Mercurial or in the
213 213 Python search path, create an entry for it in your configuration file,
214 214 like this:
215 215
216 216 [extensions]
217 217 foo =
218 218
219 219 You may also specify the full path to an extension:
220 220
221 221 [extensions]
222 222 myfeature = ~/.hgext/myfeature.py
223 223
224 224 See 'hg help config' for more information on configuration files.
225 225
226 226 Extensions are not loaded by default for a variety of reasons: they can
227 227 increase startup overhead; they may be meant for advanced usage only; they
228 228 may provide potentially dangerous abilities (such as letting you destroy
229 229 or modify history); they might not be ready for prime time; or they may
230 230 alter some usual behaviors of stock Mercurial. It is thus up to the user
231 231 to activate extensions as needed.
232 232
233 233 To explicitly disable an extension enabled in a configuration file of
234 234 broader scope, prepend its path with !:
235 235
236 236 [extensions]
237 237 # disabling extension bar residing in /path/to/extension/bar.py
238 238 bar = !/path/to/extension/bar.py
239 239 # ditto, but no path was supplied for extension baz
240 240 baz = !
241 241
242 242 enabled extensions:
243 243
244 244 chgserver command server extension for cHg (EXPERIMENTAL) (?)
245 245 children command to display child changesets (DEPRECATED)
246 246 rebase command to move sets of revisions to a different ancestor
247 247
248 248 disabled extensions:
249 249
250 250 acl hooks for controlling repository access
251 251 blackbox log repository events to a blackbox for debugging
252 252 bugzilla hooks for integrating with the Bugzilla bug tracker
253 253 censor erase file content at a given revision
254 254 churn command to display statistics about repository history
255 255 clonebundles advertise pre-generated bundles to seed clones
256 256 color colorize output from some commands
257 257 convert import revisions from foreign VCS repositories into
258 258 Mercurial
259 259 eol automatically manage newlines in repository files
260 260 extdiff command to allow external programs to compare revisions
261 261 factotum http authentication with factotum
262 262 gpg commands to sign and verify changesets
263 263 hgcia hooks for integrating with the CIA.vc notification service
264 264 hgk browse the repository in a graphical way
265 265 highlight syntax highlighting for hgweb (requires Pygments)
266 266 histedit interactive history editing
267 267 keyword expand keywords in tracked files
268 268 largefiles track large binary files
269 269 mq manage a stack of patches
270 270 notify hooks for sending email push notifications
271 271 pager browse command output with an external pager
272 272 patchbomb command to send changesets as (a series of) patch emails
273 273 purge command to delete untracked files from the working
274 274 directory
275 275 relink recreates hardlinks between repository clones
276 276 schemes extend schemes with shortcuts to repository swarms
277 277 share share a common history between several working directories
278 278 shelve save and restore changes to the working directory
279 279 strip strip changesets and their descendants from history
280 280 transplant command to transplant changesets from another branch
281 281 win32mbcs allow the use of MBCS paths with problematic encodings
282 282 zeroconf discover and advertise repositories on the local network
283 283
284 284 Verify that extension keywords appear in help templates
285 285
286 286 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
287 287
288 288 Test short command list with verbose option
289 289
290 290 $ hg -v help shortlist
291 291 Mercurial Distributed SCM
292 292
293 293 basic commands:
294 294
295 295 add add the specified files on the next commit
296 296 annotate, blame
297 297 show changeset information by line for each file
298 298 clone make a copy of an existing repository
299 299 commit, ci commit the specified files or all outstanding changes
300 300 diff diff repository (or selected files)
301 301 export dump the header and diffs for one or more changesets
302 302 forget forget the specified files on the next commit
303 303 init create a new repository in the given directory
304 304 log, history show revision history of entire repository or files
305 305 merge merge another revision into working directory
306 306 pull pull changes from the specified source
307 307 push push changes to the specified destination
308 308 remove, rm remove the specified files on the next commit
309 309 serve start stand-alone webserver
310 310 status, st show changed files in the working directory
311 311 summary, sum summarize working directory state
312 312 update, up, checkout, co
313 313 update working directory (or switch revisions)
314 314
315 315 global options ([+] can be repeated):
316 316
317 317 -R --repository REPO repository root directory or name of overlay bundle
318 318 file
319 319 --cwd DIR change working directory
320 320 -y --noninteractive do not prompt, automatically pick the first choice for
321 321 all prompts
322 322 -q --quiet suppress output
323 323 -v --verbose enable additional output
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
336 336 (use "hg help" for the full list of commands)
337 337
338 338 $ hg add -h
339 339 hg add [OPTION]... [FILE]...
340 340
341 341 add the specified files on the next commit
342 342
343 343 Schedule files to be version controlled and added to the repository.
344 344
345 345 The files will be added to the repository at the next commit. To undo an
346 346 add before that, see 'hg forget'.
347 347
348 348 If no names are given, add all files to the repository (except files
349 349 matching ".hgignore").
350 350
351 351 Returns 0 if all files are successfully added.
352 352
353 353 options ([+] can be repeated):
354 354
355 355 -I --include PATTERN [+] include names matching the given patterns
356 356 -X --exclude PATTERN [+] exclude names matching the given patterns
357 357 -S --subrepos recurse into subrepositories
358 358 -n --dry-run do not perform actions, just print output
359 359
360 360 (some details hidden, use --verbose to show complete help)
361 361
362 362 Verbose help for add
363 363
364 364 $ hg add -hv
365 365 hg add [OPTION]... [FILE]...
366 366
367 367 add the specified files on the next commit
368 368
369 369 Schedule files to be version controlled and added to the repository.
370 370
371 371 The files will be added to the repository at the next commit. To undo an
372 372 add before that, see 'hg forget'.
373 373
374 374 If no names are given, add all files to the repository (except files
375 375 matching ".hgignore").
376 376
377 377 Examples:
378 378
379 379 - New (unknown) files are added automatically by 'hg add':
380 380
381 381 $ ls
382 382 foo.c
383 383 $ hg status
384 384 ? foo.c
385 385 $ hg add
386 386 adding foo.c
387 387 $ hg status
388 388 A foo.c
389 389
390 390 - Specific files to be added can be specified:
391 391
392 392 $ ls
393 393 bar.c foo.c
394 394 $ hg status
395 395 ? bar.c
396 396 ? foo.c
397 397 $ hg add bar.c
398 398 $ hg status
399 399 A bar.c
400 400 ? foo.c
401 401
402 402 Returns 0 if all files are successfully added.
403 403
404 404 options ([+] can be repeated):
405 405
406 406 -I --include PATTERN [+] include names matching the given patterns
407 407 -X --exclude PATTERN [+] exclude names matching the given patterns
408 408 -S --subrepos recurse into subrepositories
409 409 -n --dry-run do not perform actions, just print output
410 410
411 411 global options ([+] can be repeated):
412 412
413 413 -R --repository REPO repository root directory or name of overlay bundle
414 414 file
415 415 --cwd DIR change working directory
416 416 -y --noninteractive do not prompt, automatically pick the first choice for
417 417 all prompts
418 418 -q --quiet suppress output
419 419 -v --verbose enable additional output
420 420 --config CONFIG [+] set/override config option (use 'section.name=value')
421 421 --debug enable debugging output
422 422 --debugger start debugger
423 423 --encoding ENCODE set the charset encoding (default: ascii)
424 424 --encodingmode MODE set the charset encoding mode (default: strict)
425 425 --traceback always print a traceback on exception
426 426 --time time how long the command takes
427 427 --profile print command execution profile
428 428 --version output version information and exit
429 429 -h --help display help and exit
430 430 --hidden consider hidden changesets
431 431
432 432 Test help option with version option
433 433
434 434 $ hg add -h --version
435 435 Mercurial Distributed SCM (version *) (glob)
436 436 (see https://mercurial-scm.org for more information)
437 437
438 438 Copyright (C) 2005-2016 Matt Mackall and others
439 439 This is free software; see the source for copying conditions. There is NO
440 440 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
441 441
442 442 $ hg add --skjdfks
443 443 hg add: option --skjdfks not recognized
444 444 hg add [OPTION]... [FILE]...
445 445
446 446 add the specified files on the next commit
447 447
448 448 options ([+] can be repeated):
449 449
450 450 -I --include PATTERN [+] include names matching the given patterns
451 451 -X --exclude PATTERN [+] exclude names matching the given patterns
452 452 -S --subrepos recurse into subrepositories
453 453 -n --dry-run do not perform actions, just print output
454 454
455 455 (use "hg add -h" to show more help)
456 456 [255]
457 457
458 458 Test ambiguous command help
459 459
460 460 $ hg help ad
461 461 list of commands:
462 462
463 463 add add the specified files on the next commit
464 464 addremove add all new files, delete all missing files
465 465
466 466 (use "hg help -v ad" to show built-in aliases and global options)
467 467
468 468 Test command without options
469 469
470 470 $ hg help verify
471 471 hg verify
472 472
473 473 verify the integrity of the repository
474 474
475 475 Verify the integrity of the current repository.
476 476
477 477 This will perform an extensive check of the repository's integrity,
478 478 validating the hashes and checksums of each entry in the changelog,
479 479 manifest, and tracked files, as well as the integrity of their crosslinks
480 480 and indices.
481 481
482 482 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
483 483 information about recovery from corruption of the repository.
484 484
485 485 Returns 0 on success, 1 if errors are encountered.
486 486
487 487 (some details hidden, use --verbose to show complete help)
488 488
489 489 $ hg help diff
490 490 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
491 491
492 492 diff repository (or selected files)
493 493
494 494 Show differences between revisions for the specified files.
495 495
496 496 Differences between files are shown using the unified diff format.
497 497
498 498 Note:
499 499 'hg diff' may generate unexpected results for merges, as it will
500 500 default to comparing against the working directory's first parent
501 501 changeset if no revisions are specified.
502 502
503 503 When two revision arguments are given, then changes are shown between
504 504 those revisions. If only one revision is specified then that revision is
505 505 compared to the working directory, and, when no revisions are specified,
506 506 the working directory files are compared to its first parent.
507 507
508 508 Alternatively you can specify -c/--change with a revision to see the
509 509 changes in that changeset relative to its first parent.
510 510
511 511 Without the -a/--text option, diff will avoid generating diffs of files it
512 512 detects as binary. With -a, diff will generate a diff anyway, probably
513 513 with undesirable results.
514 514
515 515 Use the -g/--git option to generate diffs in the git extended diff format.
516 516 For more information, read 'hg help diffs'.
517 517
518 518 Returns 0 on success.
519 519
520 520 options ([+] can be repeated):
521 521
522 522 -r --rev REV [+] revision
523 523 -c --change REV change made by revision
524 524 -a --text treat all files as text
525 525 -g --git use git extended diff format
526 526 --nodates omit dates from diff headers
527 527 --noprefix omit a/ and b/ prefixes from filenames
528 528 -p --show-function show which function each change is in
529 529 --reverse produce a diff that undoes the changes
530 530 -w --ignore-all-space ignore white space when comparing lines
531 531 -b --ignore-space-change ignore changes in the amount of white space
532 532 -B --ignore-blank-lines ignore changes whose lines are all blank
533 533 -U --unified NUM number of lines of context to show
534 534 --stat output diffstat-style summary of changes
535 535 --root DIR produce diffs relative to subdirectory
536 536 -I --include PATTERN [+] include names matching the given patterns
537 537 -X --exclude PATTERN [+] exclude names matching the given patterns
538 538 -S --subrepos recurse into subrepositories
539 539
540 540 (some details hidden, use --verbose to show complete help)
541 541
542 542 $ hg help status
543 543 hg status [OPTION]... [FILE]...
544 544
545 545 aliases: st
546 546
547 547 show changed files in the working directory
548 548
549 549 Show status of files in the repository. If names are given, only files
550 550 that match are shown. Files that are clean or ignored or the source of a
551 551 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
552 552 -C/--copies or -A/--all are given. Unless options described with "show
553 553 only ..." are given, the options -mardu are used.
554 554
555 555 Option -q/--quiet hides untracked (unknown and ignored) files unless
556 556 explicitly requested with -u/--unknown or -i/--ignored.
557 557
558 558 Note:
559 559 'hg status' may appear to disagree with diff if permissions have
560 560 changed or a merge has occurred. The standard diff format does not
561 561 report permission changes and diff only reports changes relative to one
562 562 merge parent.
563 563
564 564 If one revision is given, it is used as the base revision. If two
565 565 revisions are given, the differences between them are shown. The --change
566 566 option can also be used as a shortcut to list the changed files of a
567 567 revision from its first parent.
568 568
569 569 The codes used to show the status of files are:
570 570
571 571 M = modified
572 572 A = added
573 573 R = removed
574 574 C = clean
575 575 ! = missing (deleted by non-hg command, but still tracked)
576 576 ? = not tracked
577 577 I = ignored
578 578 = origin of the previous file (with --copies)
579 579
580 580 Returns 0 on success.
581 581
582 582 options ([+] can be repeated):
583 583
584 584 -A --all show status of all files
585 585 -m --modified show only modified files
586 586 -a --added show only added files
587 587 -r --removed show only removed files
588 588 -d --deleted show only deleted (but tracked) files
589 589 -c --clean show only files without changes
590 590 -u --unknown show only unknown (not tracked) files
591 591 -i --ignored show only ignored files
592 592 -n --no-status hide status prefix
593 593 -C --copies show source of copied files
594 594 -0 --print0 end filenames with NUL, for use with xargs
595 595 --rev REV [+] show difference from revision
596 596 --change REV list the changed files of a revision
597 597 -I --include PATTERN [+] include names matching the given patterns
598 598 -X --exclude PATTERN [+] exclude names matching the given patterns
599 599 -S --subrepos recurse into subrepositories
600 600
601 601 (some details hidden, use --verbose to show complete help)
602 602
603 603 $ hg -q help status
604 604 hg status [OPTION]... [FILE]...
605 605
606 606 show changed files in the working directory
607 607
608 608 $ hg help foo
609 609 abort: no such help topic: foo
610 610 (try "hg help --keyword foo")
611 611 [255]
612 612
613 613 $ hg skjdfks
614 614 hg: unknown command 'skjdfks'
615 615 Mercurial Distributed SCM
616 616
617 617 basic commands:
618 618
619 619 add add the specified files on the next commit
620 620 annotate show changeset information by line for each file
621 621 clone make a copy of an existing repository
622 622 commit commit the specified files or all outstanding changes
623 623 diff diff repository (or selected files)
624 624 export dump the header and diffs for one or more changesets
625 625 forget forget the specified files on the next commit
626 626 init create a new repository in the given directory
627 627 log show revision history of entire repository or files
628 628 merge merge another revision into working directory
629 629 pull pull changes from the specified source
630 630 push push changes to the specified destination
631 631 remove remove the specified files on the next commit
632 632 serve start stand-alone webserver
633 633 status show changed files in the working directory
634 634 summary summarize working directory state
635 635 update update working directory (or switch revisions)
636 636
637 637 (use "hg help" for the full list of commands or "hg -v" for details)
638 638 [255]
639 639
640 640
641 641 Make sure that we don't run afoul of the help system thinking that
642 642 this is a section and erroring out weirdly.
643 643
644 644 $ hg .log
645 645 hg: unknown command '.log'
646 646 (did you mean log?)
647 647 [255]
648 648
649 649 $ hg log.
650 650 hg: unknown command 'log.'
651 651 (did you mean log?)
652 652 [255]
653 653 $ hg pu.lh
654 654 hg: unknown command 'pu.lh'
655 655 (did you mean one of pull, push?)
656 656 [255]
657 657
658 658 $ cat > helpext.py <<EOF
659 659 > import os
660 660 > from mercurial import cmdutil, commands
661 661 >
662 662 > cmdtable = {}
663 663 > command = cmdutil.command(cmdtable)
664 664 >
665 665 > @command('nohelp',
666 666 > [('', 'longdesc', 3, 'x'*90),
667 667 > ('n', '', None, 'normal desc'),
668 668 > ('', 'newline', '', 'line1\nline2')],
669 669 > 'hg nohelp',
670 670 > norepo=True)
671 671 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
672 672 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
673 673 > def nohelp(ui, *args, **kwargs):
674 674 > pass
675 675 >
676 676 > def uisetup(ui):
677 677 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
678 678 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
679 679 >
680 680 > EOF
681 681 $ echo '[extensions]' >> $HGRCPATH
682 682 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
683 683
684 684 Test for aliases
685 685
686 686 $ hg help hgalias
687 687 hg hgalias [--remote]
688 688
689 689 alias for: hg summary
690 690
691 691 summarize working directory state
692 692
693 693 This generates a brief summary of the working directory state, including
694 694 parents, branch, commit status, phase and available updates.
695 695
696 696 With the --remote option, this will check the default paths for incoming
697 697 and outgoing changes. This can be time-consuming.
698 698
699 699 Returns 0 on success.
700 700
701 701 defined by: helpext
702 702
703 703 options:
704 704
705 705 --remote check for push and pull
706 706
707 707 (some details hidden, use --verbose to show complete help)
708 708
709 709 $ hg help shellalias
710 710 hg shellalias
711 711
712 712 shell alias for:
713 713
714 714 echo hi
715 715
716 716 defined by: helpext
717 717
718 718 (some details hidden, use --verbose to show complete help)
719 719
720 720 Test command with no help text
721 721
722 722 $ hg help nohelp
723 723 hg nohelp
724 724
725 725 (no help text available)
726 726
727 727 options:
728 728
729 729 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
730 730 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
731 731 -n -- normal desc
732 732 --newline VALUE line1 line2
733 733
734 734 (some details hidden, use --verbose to show complete help)
735 735
736 736 $ hg help -k nohelp
737 737 Commands:
738 738
739 739 nohelp hg nohelp
740 740
741 741 Extension Commands:
742 742
743 743 nohelp (no help text available)
744 744
745 745 Test that default list of commands omits extension commands
746 746
747 747 $ hg help
748 748 Mercurial Distributed SCM
749 749
750 750 list of commands:
751 751
752 752 add add the specified files on the next commit
753 753 addremove add all new files, delete all missing files
754 754 annotate show changeset information by line for each file
755 755 archive create an unversioned archive of a repository revision
756 756 backout reverse effect of earlier changeset
757 757 bisect subdivision search of changesets
758 758 bookmarks create a new bookmark or list existing bookmarks
759 759 branch set or show the current branch name
760 760 branches list repository named branches
761 761 bundle create a changegroup file
762 762 cat output the current or given revision of files
763 763 clone make a copy of an existing repository
764 764 commit commit the specified files or all outstanding changes
765 765 config show combined config settings from all hgrc files
766 766 copy mark files as copied for the next commit
767 767 diff diff repository (or selected files)
768 768 export dump the header and diffs for one or more changesets
769 769 files list tracked files
770 770 forget forget the specified files on the next commit
771 771 graft copy changes from other branches onto the current branch
772 772 grep search for a pattern in specified files and revisions
773 773 heads show branch heads
774 774 help show help for a given topic or a help overview
775 775 identify identify the working directory or specified revision
776 776 import import an ordered set of patches
777 777 incoming show new changesets found in source
778 778 init create a new repository in the given directory
779 779 log show revision history of entire repository or files
780 780 manifest output the current or given revision of the project manifest
781 781 merge merge another revision into working directory
782 782 outgoing show changesets not found in the destination
783 783 paths show aliases for remote repositories
784 784 phase set or show the current phase name
785 785 pull pull changes from the specified source
786 786 push push changes to the specified destination
787 787 recover roll back an interrupted transaction
788 788 remove remove the specified files on the next commit
789 789 rename rename files; equivalent of copy + remove
790 790 resolve redo merges or set/view the merge status of files
791 791 revert restore files to their checkout state
792 792 root print the root (top) of the current working directory
793 793 serve start stand-alone webserver
794 794 status show changed files in the working directory
795 795 summary summarize working directory state
796 796 tag add one or more tags for the current or given revision
797 797 tags list repository tags
798 798 unbundle apply one or more changegroup files
799 799 update update working directory (or switch revisions)
800 800 verify verify the integrity of the repository
801 801 version output version and copyright information
802 802
803 803 enabled extensions:
804 804
805 805 helpext (no help text available)
806 806
807 807 additional help topics:
808 808
809 809 config Configuration Files
810 810 dates Date Formats
811 811 diffs Diff Formats
812 812 environment Environment Variables
813 813 extensions Using Additional Features
814 814 filesets Specifying File Sets
815 815 glossary Glossary
816 816 hgignore Syntax for Mercurial Ignore Files
817 817 hgweb Configuring hgweb
818 818 internals Technical implementation topics
819 819 merge-tools Merge Tools
820 820 multirevs Specifying Multiple Revisions
821 821 patterns File Name Patterns
822 822 phases Working with Phases
823 823 revisions Specifying Single Revisions
824 824 revsets Specifying Revision Sets
825 825 scripting Using Mercurial from scripts and automation
826 826 subrepos Subrepositories
827 827 templating Template Usage
828 828 urls URL Paths
829 829
830 830 (use "hg help -v" to show built-in aliases and global options)
831 831
832 832
833 833 Test list of internal help commands
834 834
835 835 $ hg help debug
836 836 debug commands (internal and unsupported):
837 837
838 838 debugancestor
839 839 find the ancestor revision of two revisions in a given index
840 840 debugapplystreamclonebundle
841 841 apply a stream clone bundle file
842 842 debugbuilddag
843 843 builds a repo with a given DAG from scratch in the current
844 844 empty repo
845 845 debugbundle lists the contents of a bundle
846 846 debugcheckstate
847 847 validate the correctness of the current dirstate
848 848 debugcommands
849 849 list all available commands and options
850 850 debugcomplete
851 851 returns the completion list associated with the given command
852 852 debugcreatestreamclonebundle
853 853 create a stream clone bundle file
854 854 debugdag format the changelog or an index DAG as a concise textual
855 855 description
856 856 debugdata dump the contents of a data file revision
857 857 debugdate parse and display a date
858 858 debugdeltachain
859 859 dump information about delta chains in a revlog
860 860 debugdirstate
861 861 show the contents of the current dirstate
862 862 debugdiscovery
863 863 runs the changeset discovery protocol in isolation
864 864 debugextensions
865 865 show information about active extensions
866 866 debugfileset parse and apply a fileset specification
867 867 debugfsinfo show information detected about current filesystem
868 868 debuggetbundle
869 869 retrieves a bundle from a repo
870 870 debugignore display the combined ignore pattern and information about
871 871 ignored files
872 872 debugindex dump the contents of an index file
873 873 debugindexdot
874 874 dump an index DAG as a graphviz dot file
875 875 debuginstall test Mercurial installation
876 876 debugknown test whether node ids are known to a repo
877 877 debuglocks show or modify state of locks
878 878 debugmergestate
879 879 print merge state
880 880 debugnamecomplete
881 881 complete "names" - tags, open branch names, bookmark names
882 882 debugobsolete
883 883 create arbitrary obsolete marker
884 884 debugoptDEP (no help text available)
885 885 debugoptEXP (no help text available)
886 886 debugpathcomplete
887 887 complete part or all of a tracked path
888 888 debugpushkey access the pushkey key/value protocol
889 889 debugpvec (no help text available)
890 890 debugrebuilddirstate
891 891 rebuild the dirstate as it would look like for the given
892 892 revision
893 893 debugrebuildfncache
894 894 rebuild the fncache file
895 895 debugrename dump rename information
896 896 debugrevlog show data and statistics about a revlog
897 897 debugrevspec parse and apply a revision specification
898 898 debugsetparents
899 899 manually set the parents of the current working directory
900 900 debugsub (no help text available)
901 901 debugsuccessorssets
902 902 show set of successors for revision
903 903 debugtemplate
904 904 parse and apply a template
905 905 debugwalk show how files match on given patterns
906 906 debugwireargs
907 907 (no help text available)
908 908
909 909 (use "hg help -v debug" to show built-in aliases and global options)
910 910
911 911 internals topic renders index of available sub-topics
912 912
913 913 $ hg help internals
914 914 Technical implementation topics
915 915 """""""""""""""""""""""""""""""
916 916
917 917 bundles container for exchange of repository data
918 918 changegroups representation of revlog data
919 919 requirements repository requirements
920 920 revlogs revision storage mechanism
921 921
922 922 sub-topics can be accessed
923 923
924 924 $ hg help internals.changegroups
925 925 Changegroups
926 926 ============
927 927
928 928 Changegroups are representations of repository revlog data, specifically
929 929 the changelog, manifest, and filelogs.
930 930
931 931 There are 3 versions of changegroups: "1", "2", and "3". From a high-
932 932 level, versions "1" and "2" are almost exactly the same, with the only
933 933 difference being a header on entries in the changeset segment. Version "3"
934 934 adds support for exchanging treemanifests and includes revlog flags in the
935 935 delta header.
936 936
937 937 Changegroups consists of 3 logical segments:
938 938
939 939 +---------------------------------+
940 940 | | | |
941 941 | changeset | manifest | filelogs |
942 942 | | | |
943 943 +---------------------------------+
944 944
945 945 The principle building block of each segment is a *chunk*. A *chunk* is a
946 946 framed piece of data:
947 947
948 948 +---------------------------------------+
949 949 | | |
950 950 | length | data |
951 951 | (32 bits) | <length> bytes |
952 952 | | |
953 953 +---------------------------------------+
954 954
955 955 Each chunk starts with a 32-bit big-endian signed integer indicating the
956 956 length of the raw data that follows.
957 957
958 958 There is a special case chunk that has 0 length ("0x00000000"). We call
959 959 this an *empty chunk*.
960 960
961 961 Delta Groups
962 962 ------------
963 963
964 964 A *delta group* expresses the content of a revlog as a series of deltas,
965 965 or patches against previous revisions.
966 966
967 967 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
968 968 to signal the end of the delta group:
969 969
970 970 +------------------------------------------------------------------------+
971 971 | | | | | |
972 972 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
973 973 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
974 974 | | | | | |
975 975 +------------------------------------------------------------+-----------+
976 976
977 977 Each *chunk*'s data consists of the following:
978 978
979 979 +-----------------------------------------+
980 980 | | | |
981 981 | delta header | mdiff header | delta |
982 982 | (various) | (12 bytes) | (various) |
983 983 | | | |
984 984 +-----------------------------------------+
985 985
986 986 The *length* field is the byte length of the remaining 3 logical pieces of
987 987 data. The *delta* is a diff from an existing entry in the changelog.
988 988
989 989 The *delta header* is different between versions "1", "2", and "3" of the
990 990 changegroup format.
991 991
992 992 Version 1:
993 993
994 994 +------------------------------------------------------+
995 995 | | | | |
996 996 | node | p1 node | p2 node | link node |
997 997 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
998 998 | | | | |
999 999 +------------------------------------------------------+
1000 1000
1001 1001 Version 2:
1002 1002
1003 1003 +------------------------------------------------------------------+
1004 1004 | | | | | |
1005 1005 | node | p1 node | p2 node | base node | link node |
1006 1006 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1007 1007 | | | | | |
1008 1008 +------------------------------------------------------------------+
1009 1009
1010 1010 Version 3:
1011 1011
1012 1012 +------------------------------------------------------------------------------+
1013 1013 | | | | | | |
1014 1014 | node | p1 node | p2 node | base node | link node | flags |
1015 1015 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1016 1016 | | | | | | |
1017 1017 +------------------------------------------------------------------------------+
1018 1018
1019 1019 The *mdiff header* consists of 3 32-bit big-endian signed integers
1020 1020 describing offsets at which to apply the following delta content:
1021 1021
1022 1022 +-------------------------------------+
1023 1023 | | | |
1024 1024 | offset | old length | new length |
1025 1025 | (32 bits) | (32 bits) | (32 bits) |
1026 1026 | | | |
1027 1027 +-------------------------------------+
1028 1028
1029 1029 In version 1, the delta is always applied against the previous node from
1030 1030 the changegroup or the first parent if this is the first entry in the
1031 1031 changegroup.
1032 1032
1033 1033 In version 2, the delta base node is encoded in the entry in the
1034 1034 changegroup. This allows the delta to be expressed against any parent,
1035 1035 which can result in smaller deltas and more efficient encoding of data.
1036 1036
1037 1037 Changeset Segment
1038 1038 -----------------
1039 1039
1040 1040 The *changeset segment* consists of a single *delta group* holding
1041 1041 changelog data. It is followed by an *empty chunk* to denote the boundary
1042 1042 to the *manifests segment*.
1043 1043
1044 1044 Manifest Segment
1045 1045 ----------------
1046 1046
1047 1047 The *manifest segment* consists of a single *delta group* holding manifest
1048 1048 data. It is followed by an *empty chunk* to denote the boundary to the
1049 1049 *filelogs segment*.
1050 1050
1051 1051 Filelogs Segment
1052 1052 ----------------
1053 1053
1054 1054 The *filelogs* segment consists of multiple sub-segments, each
1055 1055 corresponding to an individual file whose data is being described:
1056 1056
1057 1057 +--------------------------------------+
1058 1058 | | | | |
1059 1059 | filelog0 | filelog1 | filelog2 | ... |
1060 1060 | | | | |
1061 1061 +--------------------------------------+
1062 1062
1063 1063 In version "3" of the changegroup format, filelogs may include directory
1064 1064 logs when treemanifests are in use. directory logs are identified by
1065 1065 having a trailing '/' on their filename (see below).
1066 1066
1067 1067 The final filelog sub-segment is followed by an *empty chunk* to denote
1068 1068 the end of the segment and the overall changegroup.
1069 1069
1070 1070 Each filelog sub-segment consists of the following:
1071 1071
1072 1072 +------------------------------------------+
1073 1073 | | | |
1074 1074 | filename size | filename | delta group |
1075 1075 | (32 bits) | (various) | (various) |
1076 1076 | | | |
1077 1077 +------------------------------------------+
1078 1078
1079 1079 That is, a *chunk* consisting of the filename (not terminated or padded)
1080 1080 followed by N chunks constituting the *delta group* for this file.
1081 1081
1082 1082 Test list of commands with command with no help text
1083 1083
1084 1084 $ hg help helpext
1085 1085 helpext extension - no help text available
1086 1086
1087 1087 list of commands:
1088 1088
1089 1089 nohelp (no help text available)
1090 1090
1091 1091 (use "hg help -v helpext" to show built-in aliases and global options)
1092 1092
1093 1093
1094 1094 test deprecated and experimental options are hidden in command help
1095 1095 $ hg help debugoptDEP
1096 1096 hg debugoptDEP
1097 1097
1098 1098 (no help text available)
1099 1099
1100 1100 options:
1101 1101
1102 1102 (some details hidden, use --verbose to show complete help)
1103 1103
1104 1104 $ hg help debugoptEXP
1105 1105 hg debugoptEXP
1106 1106
1107 1107 (no help text available)
1108 1108
1109 1109 options:
1110 1110
1111 1111 (some details hidden, use --verbose to show complete help)
1112 1112
1113 1113 test deprecated and experimental options is shown with -v
1114 1114 $ hg help -v debugoptDEP | grep dopt
1115 1115 --dopt option is (DEPRECATED)
1116 1116 $ hg help -v debugoptEXP | grep eopt
1117 1117 --eopt option is (EXPERIMENTAL)
1118 1118
1119 1119 #if gettext
1120 1120 test deprecated option is hidden with translation with untranslated description
1121 1121 (use many globy for not failing on changed transaction)
1122 1122 $ LANGUAGE=sv hg help debugoptDEP
1123 1123 hg debugoptDEP
1124 1124
1125 1125 (*) (glob)
1126 1126
1127 1127 options:
1128 1128
1129 1129 (some details hidden, use --verbose to show complete help)
1130 1130 #endif
1131 1131
1132 1132 Test commands that collide with topics (issue4240)
1133 1133
1134 1134 $ hg config -hq
1135 1135 hg config [-u] [NAME]...
1136 1136
1137 1137 show combined config settings from all hgrc files
1138 1138 $ hg showconfig -hq
1139 1139 hg config [-u] [NAME]...
1140 1140
1141 1141 show combined config settings from all hgrc files
1142 1142
1143 1143 Test a help topic
1144 1144
1145 1145 $ hg help revs
1146 1146 Specifying Single Revisions
1147 1147 """""""""""""""""""""""""""
1148 1148
1149 1149 Mercurial supports several ways to specify individual revisions.
1150 1150
1151 1151 A plain integer is treated as a revision number. Negative integers are
1152 1152 treated as sequential offsets from the tip, with -1 denoting the tip, -2
1153 1153 denoting the revision prior to the tip, and so forth.
1154 1154
1155 1155 A 40-digit hexadecimal string is treated as a unique revision identifier.
1156 1156
1157 1157 A hexadecimal string less than 40 characters long is treated as a unique
1158 1158 revision identifier and is referred to as a short-form identifier. A
1159 1159 short-form identifier is only valid if it is the prefix of exactly one
1160 1160 full-length identifier.
1161 1161
1162 1162 Any other string is treated as a bookmark, tag, or branch name. A bookmark
1163 1163 is a movable pointer to a revision. A tag is a permanent name associated
1164 1164 with a revision. A branch name denotes the tipmost open branch head of
1165 1165 that branch - or if they are all closed, the tipmost closed head of the
1166 1166 branch. Bookmark, tag, and branch names must not contain the ":"
1167 1167 character.
1168 1168
1169 1169 The reserved name "tip" always identifies the most recent revision.
1170 1170
1171 1171 The reserved name "null" indicates the null revision. This is the revision
1172 1172 of an empty repository, and the parent of revision 0.
1173 1173
1174 1174 The reserved name "." indicates the working directory parent. If no
1175 1175 working directory is checked out, it is equivalent to null. If an
1176 1176 uncommitted merge is in progress, "." is the revision of the first parent.
1177 1177
1178 1178 Test repeated config section name
1179 1179
1180 1180 $ hg help config.host
1181 1181 "http_proxy.host"
1182 1182 Host name and (optional) port of the proxy server, for example
1183 1183 "myproxy:8000".
1184 1184
1185 1185 "smtp.host"
1186 1186 Host name of mail server, e.g. "mail.example.com".
1187 1187
1188 1188 Unrelated trailing paragraphs shouldn't be included
1189 1189
1190 1190 $ hg help config.extramsg | grep '^$'
1191 1191
1192 1192
1193 1193 Test capitalized section name
1194 1194
1195 1195 $ hg help scripting.HGPLAIN > /dev/null
1196 1196
1197 1197 Help subsection:
1198 1198
1199 1199 $ hg help config.charsets |grep "Email example:" > /dev/null
1200 1200 [1]
1201 1201
1202 1202 Show nested definitions
1203 1203 ("profiling.type"[break]"ls"[break]"stat"[break])
1204 1204
1205 1205 $ hg help config.type | egrep '^$'|wc -l
1206 1206 \s*3 (re)
1207 1207
1208 1208 Separate sections from subsections
1209 1209
1210 1210 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1211 1211 "format"
1212 1212 --------
1213 1213
1214 1214 "usegeneraldelta"
1215 1215
1216 1216 "dotencode"
1217 1217
1218 1218 "usefncache"
1219 1219
1220 1220 "usestore"
1221 1221
1222 1222 "profiling"
1223 1223 -----------
1224 1224
1225 1225 "format"
1226 1226
1227 1227 "progress"
1228 1228 ----------
1229 1229
1230 1230 "format"
1231 1231
1232 1232
1233 1233 Last item in help config.*:
1234 1234
1235 1235 $ hg help config.`hg help config|grep '^ "'| \
1236 1236 > tail -1|sed 's![ "]*!!g'`| \
1237 1237 > grep "hg help -c config" > /dev/null
1238 1238 [1]
1239 1239
1240 1240 note to use help -c for general hg help config:
1241 1241
1242 1242 $ hg help config |grep "hg help -c config" > /dev/null
1243 1243
1244 1244 Test templating help
1245 1245
1246 1246 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1247 1247 desc String. The text of the changeset description.
1248 1248 diffstat String. Statistics of changes with the following format:
1249 1249 firstline Any text. Returns the first line of text.
1250 1250 nonempty Any text. Returns '(none)' if the string is empty.
1251 1251
1252 1252 Test deprecated items
1253 1253
1254 1254 $ hg help -v templating | grep currentbookmark
1255 1255 currentbookmark
1256 1256 $ hg help templating | (grep currentbookmark || true)
1257 1257
1258 1258 Test help hooks
1259 1259
1260 1260 $ cat > helphook1.py <<EOF
1261 1261 > from mercurial import help
1262 1262 >
1263 1263 > def rewrite(ui, topic, doc):
1264 1264 > return doc + '\nhelphook1\n'
1265 1265 >
1266 1266 > def extsetup(ui):
1267 1267 > help.addtopichook('revsets', rewrite)
1268 1268 > EOF
1269 1269 $ cat > helphook2.py <<EOF
1270 1270 > from mercurial import help
1271 1271 >
1272 1272 > def rewrite(ui, topic, doc):
1273 1273 > return doc + '\nhelphook2\n'
1274 1274 >
1275 1275 > def extsetup(ui):
1276 1276 > help.addtopichook('revsets', rewrite)
1277 1277 > EOF
1278 1278 $ echo '[extensions]' >> $HGRCPATH
1279 1279 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1280 1280 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1281 1281 $ hg help revsets | grep helphook
1282 1282 helphook1
1283 1283 helphook2
1284 1284
1285 1285 help -c should only show debug --debug
1286 1286
1287 1287 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1288 1288 [1]
1289 1289
1290 1290 help -c should only show deprecated for -v
1291 1291
1292 1292 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1293 1293 [1]
1294 1294
1295 1295 Test -s / --system
1296 1296
1297 1297 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1298 1298 > wc -l | sed -e 's/ //g'
1299 1299 0
1300 1300 $ hg help config.files --system unix | grep 'USER' | \
1301 1301 > wc -l | sed -e 's/ //g'
1302 1302 0
1303 1303
1304 1304 Test -e / -c / -k combinations
1305 1305
1306 1306 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1307 1307 Commands:
1308 1308 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1309 1309 Extensions:
1310 1310 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1311 1311 Topics:
1312 1312 Commands:
1313 1313 Extensions:
1314 1314 Extension Commands:
1315 1315 $ hg help -c schemes
1316 1316 abort: no such help topic: schemes
1317 1317 (try "hg help --keyword schemes")
1318 1318 [255]
1319 1319 $ hg help -e schemes |head -1
1320 1320 schemes extension - extend schemes with shortcuts to repository swarms
1321 1321 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1322 1322 Commands:
1323 1323 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1324 1324 Extensions:
1325 1325 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1326 1326 Extensions:
1327 1327 Commands:
1328 1328 $ hg help -c commit > /dev/null
1329 1329 $ hg help -e -c commit > /dev/null
1330 1330 $ hg help -e commit > /dev/null
1331 1331 abort: no such help topic: commit
1332 1332 (try "hg help --keyword commit")
1333 1333 [255]
1334 1334
1335 1335 Test keyword search help
1336 1336
1337 1337 $ cat > prefixedname.py <<EOF
1338 1338 > '''matched against word "clone"
1339 1339 > '''
1340 1340 > EOF
1341 1341 $ echo '[extensions]' >> $HGRCPATH
1342 1342 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1343 1343 $ hg help -k clone
1344 1344 Topics:
1345 1345
1346 1346 config Configuration Files
1347 1347 extensions Using Additional Features
1348 1348 glossary Glossary
1349 1349 phases Working with Phases
1350 1350 subrepos Subrepositories
1351 1351 urls URL Paths
1352 1352
1353 1353 Commands:
1354 1354
1355 1355 bookmarks create a new bookmark or list existing bookmarks
1356 1356 clone make a copy of an existing repository
1357 1357 paths show aliases for remote repositories
1358 1358 update update working directory (or switch revisions)
1359 1359
1360 1360 Extensions:
1361 1361
1362 1362 clonebundles advertise pre-generated bundles to seed clones
1363 1363 prefixedname matched against word "clone"
1364 1364 relink recreates hardlinks between repository clones
1365 1365
1366 1366 Extension Commands:
1367 1367
1368 1368 qclone clone main and patch repository at same time
1369 1369
1370 1370 Test unfound topic
1371 1371
1372 1372 $ hg help nonexistingtopicthatwillneverexisteverever
1373 1373 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1374 1374 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1375 1375 [255]
1376 1376
1377 1377 Test unfound keyword
1378 1378
1379 1379 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1380 1380 abort: no matches
1381 1381 (try "hg help" for a list of topics)
1382 1382 [255]
1383 1383
1384 1384 Test omit indicating for help
1385 1385
1386 1386 $ cat > addverboseitems.py <<EOF
1387 1387 > '''extension to test omit indicating.
1388 1388 >
1389 1389 > This paragraph is never omitted (for extension)
1390 1390 >
1391 1391 > .. container:: verbose
1392 1392 >
1393 1393 > This paragraph is omitted,
1394 1394 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1395 1395 >
1396 1396 > This paragraph is never omitted, too (for extension)
1397 1397 > '''
1398 1398 >
1399 1399 > from mercurial import help, commands
1400 1400 > testtopic = """This paragraph is never omitted (for topic).
1401 1401 >
1402 1402 > .. container:: verbose
1403 1403 >
1404 1404 > This paragraph is omitted,
1405 1405 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1406 1406 >
1407 1407 > This paragraph is never omitted, too (for topic)
1408 1408 > """
1409 1409 > def extsetup(ui):
1410 1410 > help.helptable.append((["topic-containing-verbose"],
1411 1411 > "This is the topic to test omit indicating.",
1412 1412 > lambda ui: testtopic))
1413 1413 > EOF
1414 1414 $ echo '[extensions]' >> $HGRCPATH
1415 1415 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1416 1416 $ hg help addverboseitems
1417 1417 addverboseitems extension - extension to test omit indicating.
1418 1418
1419 1419 This paragraph is never omitted (for extension)
1420 1420
1421 1421 This paragraph is never omitted, too (for extension)
1422 1422
1423 1423 (some details hidden, use --verbose to show complete help)
1424 1424
1425 1425 no commands defined
1426 1426 $ hg help -v addverboseitems
1427 1427 addverboseitems extension - extension to test omit indicating.
1428 1428
1429 1429 This paragraph is never omitted (for extension)
1430 1430
1431 1431 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1432 1432 extension)
1433 1433
1434 1434 This paragraph is never omitted, too (for extension)
1435 1435
1436 1436 no commands defined
1437 1437 $ hg help topic-containing-verbose
1438 1438 This is the topic to test omit indicating.
1439 1439 """"""""""""""""""""""""""""""""""""""""""
1440 1440
1441 1441 This paragraph is never omitted (for topic).
1442 1442
1443 1443 This paragraph is never omitted, too (for topic)
1444 1444
1445 1445 (some details hidden, use --verbose to show complete help)
1446 1446 $ hg help -v topic-containing-verbose
1447 1447 This is the topic to test omit indicating.
1448 1448 """"""""""""""""""""""""""""""""""""""""""
1449 1449
1450 1450 This paragraph is never omitted (for topic).
1451 1451
1452 1452 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1453 1453 topic)
1454 1454
1455 1455 This paragraph is never omitted, too (for topic)
1456 1456
1457 1457 Test section lookup
1458 1458
1459 1459 $ hg help revset.merge
1460 1460 "merge()"
1461 1461 Changeset is a merge changeset.
1462 1462
1463 1463 $ hg help glossary.dag
1464 1464 DAG
1465 1465 The repository of changesets of a distributed version control system
1466 1466 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1467 1467 of nodes and edges, where nodes correspond to changesets and edges
1468 1468 imply a parent -> child relation. This graph can be visualized by
1469 1469 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1470 1470 limited by the requirement for children to have at most two parents.
1471 1471
1472 1472
1473 1473 $ hg help hgrc.paths
1474 1474 "paths"
1475 1475 -------
1476 1476
1477 1477 Assigns symbolic names and behavior to repositories.
1478 1478
1479 1479 Options are symbolic names defining the URL or directory that is the
1480 1480 location of the repository. Example:
1481 1481
1482 1482 [paths]
1483 1483 my_server = https://example.com/my_repo
1484 1484 local_path = /home/me/repo
1485 1485
1486 1486 These symbolic names can be used from the command line. To pull from
1487 1487 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1488 1488 local_path'.
1489 1489
1490 1490 Options containing colons (":") denote sub-options that can influence
1491 1491 behavior for that specific path. Example:
1492 1492
1493 1493 [paths]
1494 1494 my_server = https://example.com/my_path
1495 1495 my_server:pushurl = ssh://example.com/my_path
1496 1496
1497 1497 The following sub-options can be defined:
1498 1498
1499 1499 "pushurl"
1500 1500 The URL to use for push operations. If not defined, the location
1501 1501 defined by the path's main entry is used.
1502 1502
1503 1503 The following special named paths exist:
1504 1504
1505 1505 "default"
1506 1506 The URL or directory to use when no source or remote is specified.
1507 1507
1508 1508 'hg clone' will automatically define this path to the location the
1509 1509 repository was cloned from.
1510 1510
1511 1511 "default-push"
1512 1512 (deprecated) The URL or directory for the default 'hg push' location.
1513 1513 "default:pushurl" should be used instead.
1514 1514
1515 1515 $ hg help glossary.mcguffin
1516 1516 abort: help section not found
1517 1517 [255]
1518 1518
1519 1519 $ hg help glossary.mc.guffin
1520 1520 abort: help section not found
1521 1521 [255]
1522 1522
1523 1523 $ hg help template.files
1524 1524 files List of strings. All files modified, added, or removed by
1525 1525 this changeset.
1526 1526
1527 1527 Test dynamic list of merge tools only shows up once
1528 1528 $ hg help merge-tools
1529 1529 Merge Tools
1530 1530 """""""""""
1531 1531
1532 1532 To merge files Mercurial uses merge tools.
1533 1533
1534 1534 A merge tool combines two different versions of a file into a merged file.
1535 1535 Merge tools are given the two files and the greatest common ancestor of
1536 1536 the two file versions, so they can determine the changes made on both
1537 1537 branches.
1538 1538
1539 1539 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1540 1540 backout' and in several extensions.
1541 1541
1542 1542 Usually, the merge tool tries to automatically reconcile the files by
1543 1543 combining all non-overlapping changes that occurred separately in the two
1544 1544 different evolutions of the same initial base file. Furthermore, some
1545 1545 interactive merge programs make it easier to manually resolve conflicting
1546 1546 merges, either in a graphical way, or by inserting some conflict markers.
1547 1547 Mercurial does not include any interactive merge programs but relies on
1548 1548 external tools for that.
1549 1549
1550 1550 Available merge tools
1551 1551 =====================
1552 1552
1553 1553 External merge tools and their properties are configured in the merge-
1554 1554 tools configuration section - see hgrc(5) - but they can often just be
1555 1555 named by their executable.
1556 1556
1557 1557 A merge tool is generally usable if its executable can be found on the
1558 1558 system and if it can handle the merge. The executable is found if it is an
1559 1559 absolute or relative executable path or the name of an application in the
1560 1560 executable search path. The tool is assumed to be able to handle the merge
1561 1561 if it can handle symlinks if the file is a symlink, if it can handle
1562 1562 binary files if the file is binary, and if a GUI is available if the tool
1563 1563 requires a GUI.
1564 1564
1565 1565 There are some internal merge tools which can be used. The internal merge
1566 1566 tools are:
1567 1567
1568 1568 ":dump"
1569 1569 Creates three versions of the files to merge, containing the contents of
1570 1570 local, other and base. These files can then be used to perform a merge
1571 1571 manually. If the file to be merged is named "a.txt", these files will
1572 1572 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1573 1573 they will be placed in the same directory as "a.txt".
1574 1574
1575 1575 ":fail"
1576 1576 Rather than attempting to merge files that were modified on both
1577 1577 branches, it marks them as unresolved. The resolve command must be used
1578 1578 to resolve these conflicts.
1579 1579
1580 1580 ":local"
1581 1581 Uses the local 'p1()' version of files as the merged version.
1582 1582
1583 1583 ":merge"
1584 1584 Uses the internal non-interactive simple merge algorithm for merging
1585 1585 files. It will fail if there are any conflicts and leave markers in the
1586 1586 partially merged file. Markers will have two sections, one for each side
1587 1587 of merge.
1588 1588
1589 1589 ":merge-local"
1590 1590 Like :merge, but resolve all conflicts non-interactively in favor of the
1591 1591 local 'p1()' changes.
1592 1592
1593 1593 ":merge-other"
1594 1594 Like :merge, but resolve all conflicts non-interactively in favor of the
1595 1595 other 'p2()' changes.
1596 1596
1597 1597 ":merge3"
1598 1598 Uses the internal non-interactive simple merge algorithm for merging
1599 1599 files. It will fail if there are any conflicts and leave markers in the
1600 1600 partially merged file. Marker will have three sections, one from each
1601 1601 side of the merge and one for the base content.
1602 1602
1603 1603 ":other"
1604 1604 Uses the other 'p2()' version of files as the merged version.
1605 1605
1606 1606 ":prompt"
1607 1607 Asks the user which of the local 'p1()' or the other 'p2()' version to
1608 1608 keep as the merged version.
1609 1609
1610 1610 ":tagmerge"
1611 1611 Uses the internal tag merge algorithm (experimental).
1612 1612
1613 1613 ":union"
1614 1614 Uses the internal non-interactive simple merge algorithm for merging
1615 1615 files. It will use both left and right sides for conflict regions. No
1616 1616 markers are inserted.
1617 1617
1618 1618 Internal tools are always available and do not require a GUI but will by
1619 1619 default not handle symlinks or binary files.
1620 1620
1621 1621 Choosing a merge tool
1622 1622 =====================
1623 1623
1624 1624 Mercurial uses these rules when deciding which merge tool to use:
1625 1625
1626 1626 1. If a tool has been specified with the --tool option to merge or
1627 1627 resolve, it is used. If it is the name of a tool in the merge-tools
1628 1628 configuration, its configuration is used. Otherwise the specified tool
1629 1629 must be executable by the shell.
1630 1630 2. If the "HGMERGE" environment variable is present, its value is used and
1631 1631 must be executable by the shell.
1632 1632 3. If the filename of the file to be merged matches any of the patterns in
1633 1633 the merge-patterns configuration section, the first usable merge tool
1634 1634 corresponding to a matching pattern is used. Here, binary capabilities
1635 1635 of the merge tool are not considered.
1636 1636 4. If ui.merge is set it will be considered next. If the value is not the
1637 1637 name of a configured tool, the specified value is used and must be
1638 1638 executable by the shell. Otherwise the named tool is used if it is
1639 1639 usable.
1640 1640 5. If any usable merge tools are present in the merge-tools configuration
1641 1641 section, the one with the highest priority is used.
1642 1642 6. If a program named "hgmerge" can be found on the system, it is used -
1643 1643 but it will by default not be used for symlinks and binary files.
1644 1644 7. If the file to be merged is not binary and is not a symlink, then
1645 1645 internal ":merge" is used.
1646 1646 8. The merge of the file fails and must be resolved before commit.
1647 1647
1648 1648 Note:
1649 1649 After selecting a merge program, Mercurial will by default attempt to
1650 1650 merge the files using a simple merge algorithm first. Only if it
1651 1651 doesn't succeed because of conflicting changes Mercurial will actually
1652 1652 execute the merge program. Whether to use the simple merge algorithm
1653 1653 first can be controlled by the premerge setting of the merge tool.
1654 1654 Premerge is enabled by default unless the file is binary or a symlink.
1655 1655
1656 1656 See the merge-tools and ui sections of hgrc(5) for details on the
1657 1657 configuration of merge tools.
1658 1658
1659 1659 Test usage of section marks in help documents
1660 1660
1661 1661 $ cd "$TESTDIR"/../doc
1662 1662 $ python check-seclevel.py
1663 1663 $ cd $TESTTMP
1664 1664
1665 1665 #if serve
1666 1666
1667 1667 Test the help pages in hgweb.
1668 1668
1669 1669 Dish up an empty repo; serve it cold.
1670 1670
1671 1671 $ hg init "$TESTTMP/test"
1672 1672 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1673 1673 $ cat hg.pid >> $DAEMON_PIDS
1674 1674
1675 1675 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1676 1676 200 Script output follows
1677 1677
1678 1678 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1679 1679 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1680 1680 <head>
1681 1681 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1682 1682 <meta name="robots" content="index, nofollow" />
1683 1683 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1684 1684 <script type="text/javascript" src="/static/mercurial.js"></script>
1685 1685
1686 1686 <title>Help: Index</title>
1687 1687 </head>
1688 1688 <body>
1689 1689
1690 1690 <div class="container">
1691 1691 <div class="menu">
1692 1692 <div class="logo">
1693 1693 <a href="https://mercurial-scm.org/">
1694 1694 <img src="/static/hglogo.png" alt="mercurial" /></a>
1695 1695 </div>
1696 1696 <ul>
1697 1697 <li><a href="/shortlog">log</a></li>
1698 1698 <li><a href="/graph">graph</a></li>
1699 1699 <li><a href="/tags">tags</a></li>
1700 1700 <li><a href="/bookmarks">bookmarks</a></li>
1701 1701 <li><a href="/branches">branches</a></li>
1702 1702 </ul>
1703 1703 <ul>
1704 1704 <li class="active">help</li>
1705 1705 </ul>
1706 1706 </div>
1707 1707
1708 1708 <div class="main">
1709 1709 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1710 1710 <form class="search" action="/log">
1711 1711
1712 1712 <p><input name="rev" id="search1" type="text" size="30" /></p>
1713 1713 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1714 1714 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1715 1715 </form>
1716 1716 <table class="bigtable">
1717 1717 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1718 1718
1719 1719 <tr><td>
1720 1720 <a href="/help/config">
1721 1721 config
1722 1722 </a>
1723 1723 </td><td>
1724 1724 Configuration Files
1725 1725 </td></tr>
1726 1726 <tr><td>
1727 1727 <a href="/help/dates">
1728 1728 dates
1729 1729 </a>
1730 1730 </td><td>
1731 1731 Date Formats
1732 1732 </td></tr>
1733 1733 <tr><td>
1734 1734 <a href="/help/diffs">
1735 1735 diffs
1736 1736 </a>
1737 1737 </td><td>
1738 1738 Diff Formats
1739 1739 </td></tr>
1740 1740 <tr><td>
1741 1741 <a href="/help/environment">
1742 1742 environment
1743 1743 </a>
1744 1744 </td><td>
1745 1745 Environment Variables
1746 1746 </td></tr>
1747 1747 <tr><td>
1748 1748 <a href="/help/extensions">
1749 1749 extensions
1750 1750 </a>
1751 1751 </td><td>
1752 1752 Using Additional Features
1753 1753 </td></tr>
1754 1754 <tr><td>
1755 1755 <a href="/help/filesets">
1756 1756 filesets
1757 1757 </a>
1758 1758 </td><td>
1759 1759 Specifying File Sets
1760 1760 </td></tr>
1761 1761 <tr><td>
1762 1762 <a href="/help/glossary">
1763 1763 glossary
1764 1764 </a>
1765 1765 </td><td>
1766 1766 Glossary
1767 1767 </td></tr>
1768 1768 <tr><td>
1769 1769 <a href="/help/hgignore">
1770 1770 hgignore
1771 1771 </a>
1772 1772 </td><td>
1773 1773 Syntax for Mercurial Ignore Files
1774 1774 </td></tr>
1775 1775 <tr><td>
1776 1776 <a href="/help/hgweb">
1777 1777 hgweb
1778 1778 </a>
1779 1779 </td><td>
1780 1780 Configuring hgweb
1781 1781 </td></tr>
1782 1782 <tr><td>
1783 1783 <a href="/help/internals">
1784 1784 internals
1785 1785 </a>
1786 1786 </td><td>
1787 1787 Technical implementation topics
1788 1788 </td></tr>
1789 1789 <tr><td>
1790 1790 <a href="/help/merge-tools">
1791 1791 merge-tools
1792 1792 </a>
1793 1793 </td><td>
1794 1794 Merge Tools
1795 1795 </td></tr>
1796 1796 <tr><td>
1797 1797 <a href="/help/multirevs">
1798 1798 multirevs
1799 1799 </a>
1800 1800 </td><td>
1801 1801 Specifying Multiple Revisions
1802 1802 </td></tr>
1803 1803 <tr><td>
1804 1804 <a href="/help/patterns">
1805 1805 patterns
1806 1806 </a>
1807 1807 </td><td>
1808 1808 File Name Patterns
1809 1809 </td></tr>
1810 1810 <tr><td>
1811 1811 <a href="/help/phases">
1812 1812 phases
1813 1813 </a>
1814 1814 </td><td>
1815 1815 Working with Phases
1816 1816 </td></tr>
1817 1817 <tr><td>
1818 1818 <a href="/help/revisions">
1819 1819 revisions
1820 1820 </a>
1821 1821 </td><td>
1822 1822 Specifying Single Revisions
1823 1823 </td></tr>
1824 1824 <tr><td>
1825 1825 <a href="/help/revsets">
1826 1826 revsets
1827 1827 </a>
1828 1828 </td><td>
1829 1829 Specifying Revision Sets
1830 1830 </td></tr>
1831 1831 <tr><td>
1832 1832 <a href="/help/scripting">
1833 1833 scripting
1834 1834 </a>
1835 1835 </td><td>
1836 1836 Using Mercurial from scripts and automation
1837 1837 </td></tr>
1838 1838 <tr><td>
1839 1839 <a href="/help/subrepos">
1840 1840 subrepos
1841 1841 </a>
1842 1842 </td><td>
1843 1843 Subrepositories
1844 1844 </td></tr>
1845 1845 <tr><td>
1846 1846 <a href="/help/templating">
1847 1847 templating
1848 1848 </a>
1849 1849 </td><td>
1850 1850 Template Usage
1851 1851 </td></tr>
1852 1852 <tr><td>
1853 1853 <a href="/help/urls">
1854 1854 urls
1855 1855 </a>
1856 1856 </td><td>
1857 1857 URL Paths
1858 1858 </td></tr>
1859 1859 <tr><td>
1860 1860 <a href="/help/topic-containing-verbose">
1861 1861 topic-containing-verbose
1862 1862 </a>
1863 1863 </td><td>
1864 1864 This is the topic to test omit indicating.
1865 1865 </td></tr>
1866 1866
1867 1867
1868 1868 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1869 1869
1870 1870 <tr><td>
1871 1871 <a href="/help/add">
1872 1872 add
1873 1873 </a>
1874 1874 </td><td>
1875 1875 add the specified files on the next commit
1876 1876 </td></tr>
1877 1877 <tr><td>
1878 1878 <a href="/help/annotate">
1879 1879 annotate
1880 1880 </a>
1881 1881 </td><td>
1882 1882 show changeset information by line for each file
1883 1883 </td></tr>
1884 1884 <tr><td>
1885 1885 <a href="/help/clone">
1886 1886 clone
1887 1887 </a>
1888 1888 </td><td>
1889 1889 make a copy of an existing repository
1890 1890 </td></tr>
1891 1891 <tr><td>
1892 1892 <a href="/help/commit">
1893 1893 commit
1894 1894 </a>
1895 1895 </td><td>
1896 1896 commit the specified files or all outstanding changes
1897 1897 </td></tr>
1898 1898 <tr><td>
1899 1899 <a href="/help/diff">
1900 1900 diff
1901 1901 </a>
1902 1902 </td><td>
1903 1903 diff repository (or selected files)
1904 1904 </td></tr>
1905 1905 <tr><td>
1906 1906 <a href="/help/export">
1907 1907 export
1908 1908 </a>
1909 1909 </td><td>
1910 1910 dump the header and diffs for one or more changesets
1911 1911 </td></tr>
1912 1912 <tr><td>
1913 1913 <a href="/help/forget">
1914 1914 forget
1915 1915 </a>
1916 1916 </td><td>
1917 1917 forget the specified files on the next commit
1918 1918 </td></tr>
1919 1919 <tr><td>
1920 1920 <a href="/help/init">
1921 1921 init
1922 1922 </a>
1923 1923 </td><td>
1924 1924 create a new repository in the given directory
1925 1925 </td></tr>
1926 1926 <tr><td>
1927 1927 <a href="/help/log">
1928 1928 log
1929 1929 </a>
1930 1930 </td><td>
1931 1931 show revision history of entire repository or files
1932 1932 </td></tr>
1933 1933 <tr><td>
1934 1934 <a href="/help/merge">
1935 1935 merge
1936 1936 </a>
1937 1937 </td><td>
1938 1938 merge another revision into working directory
1939 1939 </td></tr>
1940 1940 <tr><td>
1941 1941 <a href="/help/pull">
1942 1942 pull
1943 1943 </a>
1944 1944 </td><td>
1945 1945 pull changes from the specified source
1946 1946 </td></tr>
1947 1947 <tr><td>
1948 1948 <a href="/help/push">
1949 1949 push
1950 1950 </a>
1951 1951 </td><td>
1952 1952 push changes to the specified destination
1953 1953 </td></tr>
1954 1954 <tr><td>
1955 1955 <a href="/help/remove">
1956 1956 remove
1957 1957 </a>
1958 1958 </td><td>
1959 1959 remove the specified files on the next commit
1960 1960 </td></tr>
1961 1961 <tr><td>
1962 1962 <a href="/help/serve">
1963 1963 serve
1964 1964 </a>
1965 1965 </td><td>
1966 1966 start stand-alone webserver
1967 1967 </td></tr>
1968 1968 <tr><td>
1969 1969 <a href="/help/status">
1970 1970 status
1971 1971 </a>
1972 1972 </td><td>
1973 1973 show changed files in the working directory
1974 1974 </td></tr>
1975 1975 <tr><td>
1976 1976 <a href="/help/summary">
1977 1977 summary
1978 1978 </a>
1979 1979 </td><td>
1980 1980 summarize working directory state
1981 1981 </td></tr>
1982 1982 <tr><td>
1983 1983 <a href="/help/update">
1984 1984 update
1985 1985 </a>
1986 1986 </td><td>
1987 1987 update working directory (or switch revisions)
1988 1988 </td></tr>
1989 1989
1990 1990
1991 1991
1992 1992 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
1993 1993
1994 1994 <tr><td>
1995 1995 <a href="/help/addremove">
1996 1996 addremove
1997 1997 </a>
1998 1998 </td><td>
1999 1999 add all new files, delete all missing files
2000 2000 </td></tr>
2001 2001 <tr><td>
2002 2002 <a href="/help/archive">
2003 2003 archive
2004 2004 </a>
2005 2005 </td><td>
2006 2006 create an unversioned archive of a repository revision
2007 2007 </td></tr>
2008 2008 <tr><td>
2009 2009 <a href="/help/backout">
2010 2010 backout
2011 2011 </a>
2012 2012 </td><td>
2013 2013 reverse effect of earlier changeset
2014 2014 </td></tr>
2015 2015 <tr><td>
2016 2016 <a href="/help/bisect">
2017 2017 bisect
2018 2018 </a>
2019 2019 </td><td>
2020 2020 subdivision search of changesets
2021 2021 </td></tr>
2022 2022 <tr><td>
2023 2023 <a href="/help/bookmarks">
2024 2024 bookmarks
2025 2025 </a>
2026 2026 </td><td>
2027 2027 create a new bookmark or list existing bookmarks
2028 2028 </td></tr>
2029 2029 <tr><td>
2030 2030 <a href="/help/branch">
2031 2031 branch
2032 2032 </a>
2033 2033 </td><td>
2034 2034 set or show the current branch name
2035 2035 </td></tr>
2036 2036 <tr><td>
2037 2037 <a href="/help/branches">
2038 2038 branches
2039 2039 </a>
2040 2040 </td><td>
2041 2041 list repository named branches
2042 2042 </td></tr>
2043 2043 <tr><td>
2044 2044 <a href="/help/bundle">
2045 2045 bundle
2046 2046 </a>
2047 2047 </td><td>
2048 2048 create a changegroup file
2049 2049 </td></tr>
2050 2050 <tr><td>
2051 2051 <a href="/help/cat">
2052 2052 cat
2053 2053 </a>
2054 2054 </td><td>
2055 2055 output the current or given revision of files
2056 2056 </td></tr>
2057 2057 <tr><td>
2058 2058 <a href="/help/config">
2059 2059 config
2060 2060 </a>
2061 2061 </td><td>
2062 2062 show combined config settings from all hgrc files
2063 2063 </td></tr>
2064 2064 <tr><td>
2065 2065 <a href="/help/copy">
2066 2066 copy
2067 2067 </a>
2068 2068 </td><td>
2069 2069 mark files as copied for the next commit
2070 2070 </td></tr>
2071 2071 <tr><td>
2072 2072 <a href="/help/files">
2073 2073 files
2074 2074 </a>
2075 2075 </td><td>
2076 2076 list tracked files
2077 2077 </td></tr>
2078 2078 <tr><td>
2079 2079 <a href="/help/graft">
2080 2080 graft
2081 2081 </a>
2082 2082 </td><td>
2083 2083 copy changes from other branches onto the current branch
2084 2084 </td></tr>
2085 2085 <tr><td>
2086 2086 <a href="/help/grep">
2087 2087 grep
2088 2088 </a>
2089 2089 </td><td>
2090 2090 search for a pattern in specified files and revisions
2091 2091 </td></tr>
2092 2092 <tr><td>
2093 2093 <a href="/help/heads">
2094 2094 heads
2095 2095 </a>
2096 2096 </td><td>
2097 2097 show branch heads
2098 2098 </td></tr>
2099 2099 <tr><td>
2100 2100 <a href="/help/help">
2101 2101 help
2102 2102 </a>
2103 2103 </td><td>
2104 2104 show help for a given topic or a help overview
2105 2105 </td></tr>
2106 2106 <tr><td>
2107 2107 <a href="/help/hgalias">
2108 2108 hgalias
2109 2109 </a>
2110 2110 </td><td>
2111 2111 summarize working directory state
2112 2112 </td></tr>
2113 2113 <tr><td>
2114 2114 <a href="/help/identify">
2115 2115 identify
2116 2116 </a>
2117 2117 </td><td>
2118 2118 identify the working directory or specified revision
2119 2119 </td></tr>
2120 2120 <tr><td>
2121 2121 <a href="/help/import">
2122 2122 import
2123 2123 </a>
2124 2124 </td><td>
2125 2125 import an ordered set of patches
2126 2126 </td></tr>
2127 2127 <tr><td>
2128 2128 <a href="/help/incoming">
2129 2129 incoming
2130 2130 </a>
2131 2131 </td><td>
2132 2132 show new changesets found in source
2133 2133 </td></tr>
2134 2134 <tr><td>
2135 2135 <a href="/help/manifest">
2136 2136 manifest
2137 2137 </a>
2138 2138 </td><td>
2139 2139 output the current or given revision of the project manifest
2140 2140 </td></tr>
2141 2141 <tr><td>
2142 2142 <a href="/help/nohelp">
2143 2143 nohelp
2144 2144 </a>
2145 2145 </td><td>
2146 2146 (no help text available)
2147 2147 </td></tr>
2148 2148 <tr><td>
2149 2149 <a href="/help/outgoing">
2150 2150 outgoing
2151 2151 </a>
2152 2152 </td><td>
2153 2153 show changesets not found in the destination
2154 2154 </td></tr>
2155 2155 <tr><td>
2156 2156 <a href="/help/paths">
2157 2157 paths
2158 2158 </a>
2159 2159 </td><td>
2160 2160 show aliases for remote repositories
2161 2161 </td></tr>
2162 2162 <tr><td>
2163 2163 <a href="/help/phase">
2164 2164 phase
2165 2165 </a>
2166 2166 </td><td>
2167 2167 set or show the current phase name
2168 2168 </td></tr>
2169 2169 <tr><td>
2170 2170 <a href="/help/recover">
2171 2171 recover
2172 2172 </a>
2173 2173 </td><td>
2174 2174 roll back an interrupted transaction
2175 2175 </td></tr>
2176 2176 <tr><td>
2177 2177 <a href="/help/rename">
2178 2178 rename
2179 2179 </a>
2180 2180 </td><td>
2181 2181 rename files; equivalent of copy + remove
2182 2182 </td></tr>
2183 2183 <tr><td>
2184 2184 <a href="/help/resolve">
2185 2185 resolve
2186 2186 </a>
2187 2187 </td><td>
2188 2188 redo merges or set/view the merge status of files
2189 2189 </td></tr>
2190 2190 <tr><td>
2191 2191 <a href="/help/revert">
2192 2192 revert
2193 2193 </a>
2194 2194 </td><td>
2195 2195 restore files to their checkout state
2196 2196 </td></tr>
2197 2197 <tr><td>
2198 2198 <a href="/help/root">
2199 2199 root
2200 2200 </a>
2201 2201 </td><td>
2202 2202 print the root (top) of the current working directory
2203 2203 </td></tr>
2204 2204 <tr><td>
2205 2205 <a href="/help/shellalias">
2206 2206 shellalias
2207 2207 </a>
2208 2208 </td><td>
2209 2209 (no help text available)
2210 2210 </td></tr>
2211 2211 <tr><td>
2212 2212 <a href="/help/tag">
2213 2213 tag
2214 2214 </a>
2215 2215 </td><td>
2216 2216 add one or more tags for the current or given revision
2217 2217 </td></tr>
2218 2218 <tr><td>
2219 2219 <a href="/help/tags">
2220 2220 tags
2221 2221 </a>
2222 2222 </td><td>
2223 2223 list repository tags
2224 2224 </td></tr>
2225 2225 <tr><td>
2226 2226 <a href="/help/unbundle">
2227 2227 unbundle
2228 2228 </a>
2229 2229 </td><td>
2230 2230 apply one or more changegroup files
2231 2231 </td></tr>
2232 2232 <tr><td>
2233 2233 <a href="/help/verify">
2234 2234 verify
2235 2235 </a>
2236 2236 </td><td>
2237 2237 verify the integrity of the repository
2238 2238 </td></tr>
2239 2239 <tr><td>
2240 2240 <a href="/help/version">
2241 2241 version
2242 2242 </a>
2243 2243 </td><td>
2244 2244 output version and copyright information
2245 2245 </td></tr>
2246 2246
2247 2247
2248 2248 </table>
2249 2249 </div>
2250 2250 </div>
2251 2251
2252 2252 <script type="text/javascript">process_dates()</script>
2253 2253
2254 2254
2255 2255 </body>
2256 2256 </html>
2257 2257
2258 2258
2259 2259 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2260 2260 200 Script output follows
2261 2261
2262 2262 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2263 2263 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2264 2264 <head>
2265 2265 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2266 2266 <meta name="robots" content="index, nofollow" />
2267 2267 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2268 2268 <script type="text/javascript" src="/static/mercurial.js"></script>
2269 2269
2270 2270 <title>Help: add</title>
2271 2271 </head>
2272 2272 <body>
2273 2273
2274 2274 <div class="container">
2275 2275 <div class="menu">
2276 2276 <div class="logo">
2277 2277 <a href="https://mercurial-scm.org/">
2278 2278 <img src="/static/hglogo.png" alt="mercurial" /></a>
2279 2279 </div>
2280 2280 <ul>
2281 2281 <li><a href="/shortlog">log</a></li>
2282 2282 <li><a href="/graph">graph</a></li>
2283 2283 <li><a href="/tags">tags</a></li>
2284 2284 <li><a href="/bookmarks">bookmarks</a></li>
2285 2285 <li><a href="/branches">branches</a></li>
2286 2286 </ul>
2287 2287 <ul>
2288 2288 <li class="active"><a href="/help">help</a></li>
2289 2289 </ul>
2290 2290 </div>
2291 2291
2292 2292 <div class="main">
2293 2293 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2294 2294 <h3>Help: add</h3>
2295 2295
2296 2296 <form class="search" action="/log">
2297 2297
2298 2298 <p><input name="rev" id="search1" type="text" size="30" /></p>
2299 2299 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2300 2300 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2301 2301 </form>
2302 2302 <div id="doc">
2303 2303 <p>
2304 2304 hg add [OPTION]... [FILE]...
2305 2305 </p>
2306 2306 <p>
2307 2307 add the specified files on the next commit
2308 2308 </p>
2309 2309 <p>
2310 2310 Schedule files to be version controlled and added to the
2311 2311 repository.
2312 2312 </p>
2313 2313 <p>
2314 2314 The files will be added to the repository at the next commit. To
2315 2315 undo an add before that, see 'hg forget'.
2316 2316 </p>
2317 2317 <p>
2318 2318 If no names are given, add all files to the repository (except
2319 2319 files matching &quot;.hgignore&quot;).
2320 2320 </p>
2321 2321 <p>
2322 2322 Examples:
2323 2323 </p>
2324 2324 <ul>
2325 2325 <li> New (unknown) files are added automatically by 'hg add':
2326 2326 <pre>
2327 2327 \$ ls (re)
2328 2328 foo.c
2329 2329 \$ hg status (re)
2330 2330 ? foo.c
2331 2331 \$ hg add (re)
2332 2332 adding foo.c
2333 2333 \$ hg status (re)
2334 2334 A foo.c
2335 2335 </pre>
2336 2336 <li> Specific files to be added can be specified:
2337 2337 <pre>
2338 2338 \$ ls (re)
2339 2339 bar.c foo.c
2340 2340 \$ hg status (re)
2341 2341 ? bar.c
2342 2342 ? foo.c
2343 2343 \$ hg add bar.c (re)
2344 2344 \$ hg status (re)
2345 2345 A bar.c
2346 2346 ? foo.c
2347 2347 </pre>
2348 2348 </ul>
2349 2349 <p>
2350 2350 Returns 0 if all files are successfully added.
2351 2351 </p>
2352 2352 <p>
2353 2353 options ([+] can be repeated):
2354 2354 </p>
2355 2355 <table>
2356 2356 <tr><td>-I</td>
2357 2357 <td>--include PATTERN [+]</td>
2358 2358 <td>include names matching the given patterns</td></tr>
2359 2359 <tr><td>-X</td>
2360 2360 <td>--exclude PATTERN [+]</td>
2361 2361 <td>exclude names matching the given patterns</td></tr>
2362 2362 <tr><td>-S</td>
2363 2363 <td>--subrepos</td>
2364 2364 <td>recurse into subrepositories</td></tr>
2365 2365 <tr><td>-n</td>
2366 2366 <td>--dry-run</td>
2367 2367 <td>do not perform actions, just print output</td></tr>
2368 2368 </table>
2369 2369 <p>
2370 2370 global options ([+] can be repeated):
2371 2371 </p>
2372 2372 <table>
2373 2373 <tr><td>-R</td>
2374 2374 <td>--repository REPO</td>
2375 2375 <td>repository root directory or name of overlay bundle file</td></tr>
2376 2376 <tr><td></td>
2377 2377 <td>--cwd DIR</td>
2378 2378 <td>change working directory</td></tr>
2379 2379 <tr><td>-y</td>
2380 2380 <td>--noninteractive</td>
2381 2381 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2382 2382 <tr><td>-q</td>
2383 2383 <td>--quiet</td>
2384 2384 <td>suppress output</td></tr>
2385 2385 <tr><td>-v</td>
2386 2386 <td>--verbose</td>
2387 2387 <td>enable additional output</td></tr>
2388 2388 <tr><td></td>
2389 2389 <td>--config CONFIG [+]</td>
2390 2390 <td>set/override config option (use 'section.name=value')</td></tr>
2391 2391 <tr><td></td>
2392 2392 <td>--debug</td>
2393 2393 <td>enable debugging output</td></tr>
2394 2394 <tr><td></td>
2395 2395 <td>--debugger</td>
2396 2396 <td>start debugger</td></tr>
2397 2397 <tr><td></td>
2398 2398 <td>--encoding ENCODE</td>
2399 2399 <td>set the charset encoding (default: ascii)</td></tr>
2400 2400 <tr><td></td>
2401 2401 <td>--encodingmode MODE</td>
2402 2402 <td>set the charset encoding mode (default: strict)</td></tr>
2403 2403 <tr><td></td>
2404 2404 <td>--traceback</td>
2405 2405 <td>always print a traceback on exception</td></tr>
2406 2406 <tr><td></td>
2407 2407 <td>--time</td>
2408 2408 <td>time how long the command takes</td></tr>
2409 2409 <tr><td></td>
2410 2410 <td>--profile</td>
2411 2411 <td>print command execution profile</td></tr>
2412 2412 <tr><td></td>
2413 2413 <td>--version</td>
2414 2414 <td>output version information and exit</td></tr>
2415 2415 <tr><td>-h</td>
2416 2416 <td>--help</td>
2417 2417 <td>display help and exit</td></tr>
2418 2418 <tr><td></td>
2419 2419 <td>--hidden</td>
2420 2420 <td>consider hidden changesets</td></tr>
2421 2421 </table>
2422 2422
2423 2423 </div>
2424 2424 </div>
2425 2425 </div>
2426 2426
2427 2427 <script type="text/javascript">process_dates()</script>
2428 2428
2429 2429
2430 2430 </body>
2431 2431 </html>
2432 2432
2433 2433
2434 2434 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2435 2435 200 Script output follows
2436 2436
2437 2437 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2438 2438 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2439 2439 <head>
2440 2440 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2441 2441 <meta name="robots" content="index, nofollow" />
2442 2442 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2443 2443 <script type="text/javascript" src="/static/mercurial.js"></script>
2444 2444
2445 2445 <title>Help: remove</title>
2446 2446 </head>
2447 2447 <body>
2448 2448
2449 2449 <div class="container">
2450 2450 <div class="menu">
2451 2451 <div class="logo">
2452 2452 <a href="https://mercurial-scm.org/">
2453 2453 <img src="/static/hglogo.png" alt="mercurial" /></a>
2454 2454 </div>
2455 2455 <ul>
2456 2456 <li><a href="/shortlog">log</a></li>
2457 2457 <li><a href="/graph">graph</a></li>
2458 2458 <li><a href="/tags">tags</a></li>
2459 2459 <li><a href="/bookmarks">bookmarks</a></li>
2460 2460 <li><a href="/branches">branches</a></li>
2461 2461 </ul>
2462 2462 <ul>
2463 2463 <li class="active"><a href="/help">help</a></li>
2464 2464 </ul>
2465 2465 </div>
2466 2466
2467 2467 <div class="main">
2468 2468 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2469 2469 <h3>Help: remove</h3>
2470 2470
2471 2471 <form class="search" action="/log">
2472 2472
2473 2473 <p><input name="rev" id="search1" type="text" size="30" /></p>
2474 2474 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2475 2475 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2476 2476 </form>
2477 2477 <div id="doc">
2478 2478 <p>
2479 2479 hg remove [OPTION]... FILE...
2480 2480 </p>
2481 2481 <p>
2482 2482 aliases: rm
2483 2483 </p>
2484 2484 <p>
2485 2485 remove the specified files on the next commit
2486 2486 </p>
2487 2487 <p>
2488 2488 Schedule the indicated files for removal from the current branch.
2489 2489 </p>
2490 2490 <p>
2491 2491 This command schedules the files to be removed at the next commit.
2492 2492 To undo a remove before that, see 'hg revert'. To undo added
2493 2493 files, see 'hg forget'.
2494 2494 </p>
2495 2495 <p>
2496 2496 -A/--after can be used to remove only files that have already
2497 2497 been deleted, -f/--force can be used to force deletion, and -Af
2498 2498 can be used to remove files from the next revision without
2499 2499 deleting them from the working directory.
2500 2500 </p>
2501 2501 <p>
2502 2502 The following table details the behavior of remove for different
2503 2503 file states (columns) and option combinations (rows). The file
2504 2504 states are Added [A], Clean [C], Modified [M] and Missing [!]
2505 2505 (as reported by 'hg status'). The actions are Warn, Remove
2506 2506 (from branch) and Delete (from disk):
2507 2507 </p>
2508 2508 <table>
2509 2509 <tr><td>opt/state</td>
2510 2510 <td>A</td>
2511 2511 <td>C</td>
2512 2512 <td>M</td>
2513 2513 <td>!</td></tr>
2514 2514 <tr><td>none</td>
2515 2515 <td>W</td>
2516 2516 <td>RD</td>
2517 2517 <td>W</td>
2518 2518 <td>R</td></tr>
2519 2519 <tr><td>-f</td>
2520 2520 <td>R</td>
2521 2521 <td>RD</td>
2522 2522 <td>RD</td>
2523 2523 <td>R</td></tr>
2524 2524 <tr><td>-A</td>
2525 2525 <td>W</td>
2526 2526 <td>W</td>
2527 2527 <td>W</td>
2528 2528 <td>R</td></tr>
2529 2529 <tr><td>-Af</td>
2530 2530 <td>R</td>
2531 2531 <td>R</td>
2532 2532 <td>R</td>
2533 2533 <td>R</td></tr>
2534 2534 </table>
2535 2535 <p>
2536 2536 <b>Note:</b>
2537 2537 </p>
2538 2538 <p>
2539 2539 'hg remove' never deletes files in Added [A] state from the
2540 2540 working directory, not even if &quot;--force&quot; is specified.
2541 2541 </p>
2542 2542 <p>
2543 2543 Returns 0 on success, 1 if any warnings encountered.
2544 2544 </p>
2545 2545 <p>
2546 2546 options ([+] can be repeated):
2547 2547 </p>
2548 2548 <table>
2549 2549 <tr><td>-A</td>
2550 2550 <td>--after</td>
2551 2551 <td>record delete for missing files</td></tr>
2552 2552 <tr><td>-f</td>
2553 2553 <td>--force</td>
2554 <td>remove (and delete) file even if added or modified</td></tr>
2554 <td>forget added files, delete modified files</td></tr>
2555 2555 <tr><td>-S</td>
2556 2556 <td>--subrepos</td>
2557 2557 <td>recurse into subrepositories</td></tr>
2558 2558 <tr><td>-I</td>
2559 2559 <td>--include PATTERN [+]</td>
2560 2560 <td>include names matching the given patterns</td></tr>
2561 2561 <tr><td>-X</td>
2562 2562 <td>--exclude PATTERN [+]</td>
2563 2563 <td>exclude names matching the given patterns</td></tr>
2564 2564 </table>
2565 2565 <p>
2566 2566 global options ([+] can be repeated):
2567 2567 </p>
2568 2568 <table>
2569 2569 <tr><td>-R</td>
2570 2570 <td>--repository REPO</td>
2571 2571 <td>repository root directory or name of overlay bundle file</td></tr>
2572 2572 <tr><td></td>
2573 2573 <td>--cwd DIR</td>
2574 2574 <td>change working directory</td></tr>
2575 2575 <tr><td>-y</td>
2576 2576 <td>--noninteractive</td>
2577 2577 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2578 2578 <tr><td>-q</td>
2579 2579 <td>--quiet</td>
2580 2580 <td>suppress output</td></tr>
2581 2581 <tr><td>-v</td>
2582 2582 <td>--verbose</td>
2583 2583 <td>enable additional output</td></tr>
2584 2584 <tr><td></td>
2585 2585 <td>--config CONFIG [+]</td>
2586 2586 <td>set/override config option (use 'section.name=value')</td></tr>
2587 2587 <tr><td></td>
2588 2588 <td>--debug</td>
2589 2589 <td>enable debugging output</td></tr>
2590 2590 <tr><td></td>
2591 2591 <td>--debugger</td>
2592 2592 <td>start debugger</td></tr>
2593 2593 <tr><td></td>
2594 2594 <td>--encoding ENCODE</td>
2595 2595 <td>set the charset encoding (default: ascii)</td></tr>
2596 2596 <tr><td></td>
2597 2597 <td>--encodingmode MODE</td>
2598 2598 <td>set the charset encoding mode (default: strict)</td></tr>
2599 2599 <tr><td></td>
2600 2600 <td>--traceback</td>
2601 2601 <td>always print a traceback on exception</td></tr>
2602 2602 <tr><td></td>
2603 2603 <td>--time</td>
2604 2604 <td>time how long the command takes</td></tr>
2605 2605 <tr><td></td>
2606 2606 <td>--profile</td>
2607 2607 <td>print command execution profile</td></tr>
2608 2608 <tr><td></td>
2609 2609 <td>--version</td>
2610 2610 <td>output version information and exit</td></tr>
2611 2611 <tr><td>-h</td>
2612 2612 <td>--help</td>
2613 2613 <td>display help and exit</td></tr>
2614 2614 <tr><td></td>
2615 2615 <td>--hidden</td>
2616 2616 <td>consider hidden changesets</td></tr>
2617 2617 </table>
2618 2618
2619 2619 </div>
2620 2620 </div>
2621 2621 </div>
2622 2622
2623 2623 <script type="text/javascript">process_dates()</script>
2624 2624
2625 2625
2626 2626 </body>
2627 2627 </html>
2628 2628
2629 2629
2630 2630 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2631 2631 200 Script output follows
2632 2632
2633 2633 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2634 2634 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2635 2635 <head>
2636 2636 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2637 2637 <meta name="robots" content="index, nofollow" />
2638 2638 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2639 2639 <script type="text/javascript" src="/static/mercurial.js"></script>
2640 2640
2641 2641 <title>Help: revisions</title>
2642 2642 </head>
2643 2643 <body>
2644 2644
2645 2645 <div class="container">
2646 2646 <div class="menu">
2647 2647 <div class="logo">
2648 2648 <a href="https://mercurial-scm.org/">
2649 2649 <img src="/static/hglogo.png" alt="mercurial" /></a>
2650 2650 </div>
2651 2651 <ul>
2652 2652 <li><a href="/shortlog">log</a></li>
2653 2653 <li><a href="/graph">graph</a></li>
2654 2654 <li><a href="/tags">tags</a></li>
2655 2655 <li><a href="/bookmarks">bookmarks</a></li>
2656 2656 <li><a href="/branches">branches</a></li>
2657 2657 </ul>
2658 2658 <ul>
2659 2659 <li class="active"><a href="/help">help</a></li>
2660 2660 </ul>
2661 2661 </div>
2662 2662
2663 2663 <div class="main">
2664 2664 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2665 2665 <h3>Help: revisions</h3>
2666 2666
2667 2667 <form class="search" action="/log">
2668 2668
2669 2669 <p><input name="rev" id="search1" type="text" size="30" /></p>
2670 2670 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2671 2671 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2672 2672 </form>
2673 2673 <div id="doc">
2674 2674 <h1>Specifying Single Revisions</h1>
2675 2675 <p>
2676 2676 Mercurial supports several ways to specify individual revisions.
2677 2677 </p>
2678 2678 <p>
2679 2679 A plain integer is treated as a revision number. Negative integers are
2680 2680 treated as sequential offsets from the tip, with -1 denoting the tip,
2681 2681 -2 denoting the revision prior to the tip, and so forth.
2682 2682 </p>
2683 2683 <p>
2684 2684 A 40-digit hexadecimal string is treated as a unique revision
2685 2685 identifier.
2686 2686 </p>
2687 2687 <p>
2688 2688 A hexadecimal string less than 40 characters long is treated as a
2689 2689 unique revision identifier and is referred to as a short-form
2690 2690 identifier. A short-form identifier is only valid if it is the prefix
2691 2691 of exactly one full-length identifier.
2692 2692 </p>
2693 2693 <p>
2694 2694 Any other string is treated as a bookmark, tag, or branch name. A
2695 2695 bookmark is a movable pointer to a revision. A tag is a permanent name
2696 2696 associated with a revision. A branch name denotes the tipmost open branch head
2697 2697 of that branch - or if they are all closed, the tipmost closed head of the
2698 2698 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2699 2699 </p>
2700 2700 <p>
2701 2701 The reserved name &quot;tip&quot; always identifies the most recent revision.
2702 2702 </p>
2703 2703 <p>
2704 2704 The reserved name &quot;null&quot; indicates the null revision. This is the
2705 2705 revision of an empty repository, and the parent of revision 0.
2706 2706 </p>
2707 2707 <p>
2708 2708 The reserved name &quot;.&quot; indicates the working directory parent. If no
2709 2709 working directory is checked out, it is equivalent to null. If an
2710 2710 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2711 2711 parent.
2712 2712 </p>
2713 2713
2714 2714 </div>
2715 2715 </div>
2716 2716 </div>
2717 2717
2718 2718 <script type="text/javascript">process_dates()</script>
2719 2719
2720 2720
2721 2721 </body>
2722 2722 </html>
2723 2723
2724 2724
2725 2725 Sub-topic indexes rendered properly
2726 2726
2727 2727 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2728 2728 200 Script output follows
2729 2729
2730 2730 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2731 2731 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2732 2732 <head>
2733 2733 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2734 2734 <meta name="robots" content="index, nofollow" />
2735 2735 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2736 2736 <script type="text/javascript" src="/static/mercurial.js"></script>
2737 2737
2738 2738 <title>Help: internals</title>
2739 2739 </head>
2740 2740 <body>
2741 2741
2742 2742 <div class="container">
2743 2743 <div class="menu">
2744 2744 <div class="logo">
2745 2745 <a href="https://mercurial-scm.org/">
2746 2746 <img src="/static/hglogo.png" alt="mercurial" /></a>
2747 2747 </div>
2748 2748 <ul>
2749 2749 <li><a href="/shortlog">log</a></li>
2750 2750 <li><a href="/graph">graph</a></li>
2751 2751 <li><a href="/tags">tags</a></li>
2752 2752 <li><a href="/bookmarks">bookmarks</a></li>
2753 2753 <li><a href="/branches">branches</a></li>
2754 2754 </ul>
2755 2755 <ul>
2756 2756 <li><a href="/help">help</a></li>
2757 2757 </ul>
2758 2758 </div>
2759 2759
2760 2760 <div class="main">
2761 2761 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2762 2762 <form class="search" action="/log">
2763 2763
2764 2764 <p><input name="rev" id="search1" type="text" size="30" /></p>
2765 2765 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2766 2766 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2767 2767 </form>
2768 2768 <table class="bigtable">
2769 2769 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
2770 2770
2771 2771 <tr><td>
2772 2772 <a href="/help/internals.bundles">
2773 2773 bundles
2774 2774 </a>
2775 2775 </td><td>
2776 2776 container for exchange of repository data
2777 2777 </td></tr>
2778 2778 <tr><td>
2779 2779 <a href="/help/internals.changegroups">
2780 2780 changegroups
2781 2781 </a>
2782 2782 </td><td>
2783 2783 representation of revlog data
2784 2784 </td></tr>
2785 2785 <tr><td>
2786 2786 <a href="/help/internals.requirements">
2787 2787 requirements
2788 2788 </a>
2789 2789 </td><td>
2790 2790 repository requirements
2791 2791 </td></tr>
2792 2792 <tr><td>
2793 2793 <a href="/help/internals.revlogs">
2794 2794 revlogs
2795 2795 </a>
2796 2796 </td><td>
2797 2797 revision storage mechanism
2798 2798 </td></tr>
2799 2799
2800 2800
2801 2801
2802 2802
2803 2803
2804 2804 </table>
2805 2805 </div>
2806 2806 </div>
2807 2807
2808 2808 <script type="text/javascript">process_dates()</script>
2809 2809
2810 2810
2811 2811 </body>
2812 2812 </html>
2813 2813
2814 2814
2815 2815 Sub-topic topics rendered properly
2816 2816
2817 2817 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2818 2818 200 Script output follows
2819 2819
2820 2820 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2821 2821 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2822 2822 <head>
2823 2823 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2824 2824 <meta name="robots" content="index, nofollow" />
2825 2825 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2826 2826 <script type="text/javascript" src="/static/mercurial.js"></script>
2827 2827
2828 2828 <title>Help: internals.changegroups</title>
2829 2829 </head>
2830 2830 <body>
2831 2831
2832 2832 <div class="container">
2833 2833 <div class="menu">
2834 2834 <div class="logo">
2835 2835 <a href="https://mercurial-scm.org/">
2836 2836 <img src="/static/hglogo.png" alt="mercurial" /></a>
2837 2837 </div>
2838 2838 <ul>
2839 2839 <li><a href="/shortlog">log</a></li>
2840 2840 <li><a href="/graph">graph</a></li>
2841 2841 <li><a href="/tags">tags</a></li>
2842 2842 <li><a href="/bookmarks">bookmarks</a></li>
2843 2843 <li><a href="/branches">branches</a></li>
2844 2844 </ul>
2845 2845 <ul>
2846 2846 <li class="active"><a href="/help">help</a></li>
2847 2847 </ul>
2848 2848 </div>
2849 2849
2850 2850 <div class="main">
2851 2851 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2852 2852 <h3>Help: internals.changegroups</h3>
2853 2853
2854 2854 <form class="search" action="/log">
2855 2855
2856 2856 <p><input name="rev" id="search1" type="text" size="30" /></p>
2857 2857 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2858 2858 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2859 2859 </form>
2860 2860 <div id="doc">
2861 2861 <h1>representation of revlog data</h1>
2862 2862 <h2>Changegroups</h2>
2863 2863 <p>
2864 2864 Changegroups are representations of repository revlog data, specifically
2865 2865 the changelog, manifest, and filelogs.
2866 2866 </p>
2867 2867 <p>
2868 2868 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2869 2869 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2870 2870 the only difference being a header on entries in the changeset
2871 2871 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2872 2872 includes revlog flags in the delta header.
2873 2873 </p>
2874 2874 <p>
2875 2875 Changegroups consists of 3 logical segments:
2876 2876 </p>
2877 2877 <pre>
2878 2878 +---------------------------------+
2879 2879 | | | |
2880 2880 | changeset | manifest | filelogs |
2881 2881 | | | |
2882 2882 +---------------------------------+
2883 2883 </pre>
2884 2884 <p>
2885 2885 The principle building block of each segment is a *chunk*. A *chunk*
2886 2886 is a framed piece of data:
2887 2887 </p>
2888 2888 <pre>
2889 2889 +---------------------------------------+
2890 2890 | | |
2891 2891 | length | data |
2892 2892 | (32 bits) | &lt;length&gt; bytes |
2893 2893 | | |
2894 2894 +---------------------------------------+
2895 2895 </pre>
2896 2896 <p>
2897 2897 Each chunk starts with a 32-bit big-endian signed integer indicating
2898 2898 the length of the raw data that follows.
2899 2899 </p>
2900 2900 <p>
2901 2901 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
2902 2902 call this an *empty chunk*.
2903 2903 </p>
2904 2904 <h3>Delta Groups</h3>
2905 2905 <p>
2906 2906 A *delta group* expresses the content of a revlog as a series of deltas,
2907 2907 or patches against previous revisions.
2908 2908 </p>
2909 2909 <p>
2910 2910 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
2911 2911 to signal the end of the delta group:
2912 2912 </p>
2913 2913 <pre>
2914 2914 +------------------------------------------------------------------------+
2915 2915 | | | | | |
2916 2916 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
2917 2917 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
2918 2918 | | | | | |
2919 2919 +------------------------------------------------------------+-----------+
2920 2920 </pre>
2921 2921 <p>
2922 2922 Each *chunk*'s data consists of the following:
2923 2923 </p>
2924 2924 <pre>
2925 2925 +-----------------------------------------+
2926 2926 | | | |
2927 2927 | delta header | mdiff header | delta |
2928 2928 | (various) | (12 bytes) | (various) |
2929 2929 | | | |
2930 2930 +-----------------------------------------+
2931 2931 </pre>
2932 2932 <p>
2933 2933 The *length* field is the byte length of the remaining 3 logical pieces
2934 2934 of data. The *delta* is a diff from an existing entry in the changelog.
2935 2935 </p>
2936 2936 <p>
2937 2937 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
2938 2938 &quot;3&quot; of the changegroup format.
2939 2939 </p>
2940 2940 <p>
2941 2941 Version 1:
2942 2942 </p>
2943 2943 <pre>
2944 2944 +------------------------------------------------------+
2945 2945 | | | | |
2946 2946 | node | p1 node | p2 node | link node |
2947 2947 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
2948 2948 | | | | |
2949 2949 +------------------------------------------------------+
2950 2950 </pre>
2951 2951 <p>
2952 2952 Version 2:
2953 2953 </p>
2954 2954 <pre>
2955 2955 +------------------------------------------------------------------+
2956 2956 | | | | | |
2957 2957 | node | p1 node | p2 node | base node | link node |
2958 2958 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
2959 2959 | | | | | |
2960 2960 +------------------------------------------------------------------+
2961 2961 </pre>
2962 2962 <p>
2963 2963 Version 3:
2964 2964 </p>
2965 2965 <pre>
2966 2966 +------------------------------------------------------------------------------+
2967 2967 | | | | | | |
2968 2968 | node | p1 node | p2 node | base node | link node | flags |
2969 2969 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
2970 2970 | | | | | | |
2971 2971 +------------------------------------------------------------------------------+
2972 2972 </pre>
2973 2973 <p>
2974 2974 The *mdiff header* consists of 3 32-bit big-endian signed integers
2975 2975 describing offsets at which to apply the following delta content:
2976 2976 </p>
2977 2977 <pre>
2978 2978 +-------------------------------------+
2979 2979 | | | |
2980 2980 | offset | old length | new length |
2981 2981 | (32 bits) | (32 bits) | (32 bits) |
2982 2982 | | | |
2983 2983 +-------------------------------------+
2984 2984 </pre>
2985 2985 <p>
2986 2986 In version 1, the delta is always applied against the previous node from
2987 2987 the changegroup or the first parent if this is the first entry in the
2988 2988 changegroup.
2989 2989 </p>
2990 2990 <p>
2991 2991 In version 2, the delta base node is encoded in the entry in the
2992 2992 changegroup. This allows the delta to be expressed against any parent,
2993 2993 which can result in smaller deltas and more efficient encoding of data.
2994 2994 </p>
2995 2995 <h3>Changeset Segment</h3>
2996 2996 <p>
2997 2997 The *changeset segment* consists of a single *delta group* holding
2998 2998 changelog data. It is followed by an *empty chunk* to denote the
2999 2999 boundary to the *manifests segment*.
3000 3000 </p>
3001 3001 <h3>Manifest Segment</h3>
3002 3002 <p>
3003 3003 The *manifest segment* consists of a single *delta group* holding
3004 3004 manifest data. It is followed by an *empty chunk* to denote the boundary
3005 3005 to the *filelogs segment*.
3006 3006 </p>
3007 3007 <h3>Filelogs Segment</h3>
3008 3008 <p>
3009 3009 The *filelogs* segment consists of multiple sub-segments, each
3010 3010 corresponding to an individual file whose data is being described:
3011 3011 </p>
3012 3012 <pre>
3013 3013 +--------------------------------------+
3014 3014 | | | | |
3015 3015 | filelog0 | filelog1 | filelog2 | ... |
3016 3016 | | | | |
3017 3017 +--------------------------------------+
3018 3018 </pre>
3019 3019 <p>
3020 3020 In version &quot;3&quot; of the changegroup format, filelogs may include
3021 3021 directory logs when treemanifests are in use. directory logs are
3022 3022 identified by having a trailing '/' on their filename (see below).
3023 3023 </p>
3024 3024 <p>
3025 3025 The final filelog sub-segment is followed by an *empty chunk* to denote
3026 3026 the end of the segment and the overall changegroup.
3027 3027 </p>
3028 3028 <p>
3029 3029 Each filelog sub-segment consists of the following:
3030 3030 </p>
3031 3031 <pre>
3032 3032 +------------------------------------------+
3033 3033 | | | |
3034 3034 | filename size | filename | delta group |
3035 3035 | (32 bits) | (various) | (various) |
3036 3036 | | | |
3037 3037 +------------------------------------------+
3038 3038 </pre>
3039 3039 <p>
3040 3040 That is, a *chunk* consisting of the filename (not terminated or padded)
3041 3041 followed by N chunks constituting the *delta group* for this file.
3042 3042 </p>
3043 3043
3044 3044 </div>
3045 3045 </div>
3046 3046 </div>
3047 3047
3048 3048 <script type="text/javascript">process_dates()</script>
3049 3049
3050 3050
3051 3051 </body>
3052 3052 </html>
3053 3053
3054 3054
3055 3055 $ killdaemons.py
3056 3056
3057 3057 #endif
General Comments 0
You need to be logged in to leave comments. Login now