##// END OF EJS Templates
commands: add debugdeltachain command...
Gregory Szorc -
r27263:4efb36ec default
parent child Browse files
Show More
@@ -1,6852 +1,6963 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex, bin, nullhex, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _
11 11 import os, re, difflib, time, tempfile, errno, shlex
12 12 import sys, socket
13 13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 14 import patch, help, encoding, templatekw, discovery
15 15 import archival, changegroup, cmdutil, hbisect
16 16 import sshserver, hgweb
17 17 import extensions
18 18 import merge as mergemod
19 19 import minirst, revset, fileset
20 20 import dagparser, context, simplemerge, graphmod, copies
21 21 import random, operator
22 22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 24 import ui as uimod
25 25 import streamclone
26 26
27 27 table = {}
28 28
29 29 command = cmdutil.command(table)
30 30
31 31 # Space delimited list of commands that don't require local repositories.
32 32 # This should be populated by passing norepo=True into the @command decorator.
33 33 norepo = ''
34 34 # Space delimited list of commands that optionally require local repositories.
35 35 # This should be populated by passing optionalrepo=True into the @command
36 36 # decorator.
37 37 optionalrepo = ''
38 38 # Space delimited list of commands that will examine arguments looking for
39 39 # a repository. This should be populated by passing inferrepo=True into the
40 40 # @command decorator.
41 41 inferrepo = ''
42 42
43 43 # label constants
44 44 # until 3.5, bookmarks.current was the advertised name, not
45 45 # bookmarks.active, so we must use both to avoid breaking old
46 46 # custom styles
47 47 activebookmarklabel = 'bookmarks.active bookmarks.current'
48 48
49 49 # common command options
50 50
51 51 globalopts = [
52 52 ('R', 'repository', '',
53 53 _('repository root directory or name of overlay bundle file'),
54 54 _('REPO')),
55 55 ('', 'cwd', '',
56 56 _('change working directory'), _('DIR')),
57 57 ('y', 'noninteractive', None,
58 58 _('do not prompt, automatically pick the first choice for all prompts')),
59 59 ('q', 'quiet', None, _('suppress output')),
60 60 ('v', 'verbose', None, _('enable additional output')),
61 61 ('', 'config', [],
62 62 _('set/override config option (use \'section.name=value\')'),
63 63 _('CONFIG')),
64 64 ('', 'debug', None, _('enable debugging output')),
65 65 ('', 'debugger', None, _('start debugger')),
66 66 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 67 _('ENCODE')),
68 68 ('', 'encodingmode', encoding.encodingmode,
69 69 _('set the charset encoding mode'), _('MODE')),
70 70 ('', 'traceback', None, _('always print a traceback on exception')),
71 71 ('', 'time', None, _('time how long the command takes')),
72 72 ('', 'profile', None, _('print command execution profile')),
73 73 ('', 'version', None, _('output version information and exit')),
74 74 ('h', 'help', None, _('display help and exit')),
75 75 ('', 'hidden', False, _('consider hidden changesets')),
76 76 ]
77 77
78 78 dryrunopts = [('n', 'dry-run', None,
79 79 _('do not perform actions, just print output'))]
80 80
81 81 remoteopts = [
82 82 ('e', 'ssh', '',
83 83 _('specify ssh command to use'), _('CMD')),
84 84 ('', 'remotecmd', '',
85 85 _('specify hg command to run on the remote side'), _('CMD')),
86 86 ('', 'insecure', None,
87 87 _('do not verify server certificate (ignoring web.cacerts config)')),
88 88 ]
89 89
90 90 walkopts = [
91 91 ('I', 'include', [],
92 92 _('include names matching the given patterns'), _('PATTERN')),
93 93 ('X', 'exclude', [],
94 94 _('exclude names matching the given patterns'), _('PATTERN')),
95 95 ]
96 96
97 97 commitopts = [
98 98 ('m', 'message', '',
99 99 _('use text as commit message'), _('TEXT')),
100 100 ('l', 'logfile', '',
101 101 _('read commit message from file'), _('FILE')),
102 102 ]
103 103
104 104 commitopts2 = [
105 105 ('d', 'date', '',
106 106 _('record the specified date as commit date'), _('DATE')),
107 107 ('u', 'user', '',
108 108 _('record the specified user as committer'), _('USER')),
109 109 ]
110 110
111 111 # hidden for now
112 112 formatteropts = [
113 113 ('T', 'template', '',
114 114 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 115 ]
116 116
117 117 templateopts = [
118 118 ('', 'style', '',
119 119 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 120 ('T', 'template', '',
121 121 _('display with template'), _('TEMPLATE')),
122 122 ]
123 123
124 124 logopts = [
125 125 ('p', 'patch', None, _('show patch')),
126 126 ('g', 'git', None, _('use git extended diff format')),
127 127 ('l', 'limit', '',
128 128 _('limit number of changes displayed'), _('NUM')),
129 129 ('M', 'no-merges', None, _('do not show merges')),
130 130 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 131 ('G', 'graph', None, _("show the revision DAG")),
132 132 ] + templateopts
133 133
134 134 diffopts = [
135 135 ('a', 'text', None, _('treat all files as text')),
136 136 ('g', 'git', None, _('use git extended diff format')),
137 137 ('', 'nodates', None, _('omit dates from diff headers'))
138 138 ]
139 139
140 140 diffwsopts = [
141 141 ('w', 'ignore-all-space', None,
142 142 _('ignore white space when comparing lines')),
143 143 ('b', 'ignore-space-change', None,
144 144 _('ignore changes in the amount of white space')),
145 145 ('B', 'ignore-blank-lines', None,
146 146 _('ignore changes whose lines are all blank')),
147 147 ]
148 148
149 149 diffopts2 = [
150 150 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 151 ('p', 'show-function', None, _('show which function each change is in')),
152 152 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 153 ] + diffwsopts + [
154 154 ('U', 'unified', '',
155 155 _('number of lines of context to show'), _('NUM')),
156 156 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 157 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 158 ]
159 159
160 160 mergetoolopts = [
161 161 ('t', 'tool', '', _('specify merge tool')),
162 162 ]
163 163
164 164 similarityopts = [
165 165 ('s', 'similarity', '',
166 166 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 167 ]
168 168
169 169 subrepoopts = [
170 170 ('S', 'subrepos', None,
171 171 _('recurse into subrepositories'))
172 172 ]
173 173
174 174 debugrevlogopts = [
175 175 ('c', 'changelog', False, _('open changelog')),
176 176 ('m', 'manifest', False, _('open manifest')),
177 177 ('', 'dir', False, _('open directory manifest')),
178 178 ]
179 179
180 180 # Commands start here, listed alphabetically
181 181
182 182 @command('^add',
183 183 walkopts + subrepoopts + dryrunopts,
184 184 _('[OPTION]... [FILE]...'),
185 185 inferrepo=True)
186 186 def add(ui, repo, *pats, **opts):
187 187 """add the specified files on the next commit
188 188
189 189 Schedule files to be version controlled and added to the
190 190 repository.
191 191
192 192 The files will be added to the repository at the next commit. To
193 193 undo an add before that, see :hg:`forget`.
194 194
195 195 If no names are given, add all files to the repository.
196 196
197 197 .. container:: verbose
198 198
199 199 Examples:
200 200
201 201 - New (unknown) files are added
202 202 automatically by :hg:`add`::
203 203
204 204 $ ls
205 205 foo.c
206 206 $ hg status
207 207 ? foo.c
208 208 $ hg add
209 209 adding foo.c
210 210 $ hg status
211 211 A foo.c
212 212
213 213 - Specific files to be added can be specified::
214 214
215 215 $ ls
216 216 bar.c foo.c
217 217 $ hg status
218 218 ? bar.c
219 219 ? foo.c
220 220 $ hg add bar.c
221 221 $ hg status
222 222 A bar.c
223 223 ? foo.c
224 224
225 225 Returns 0 if all files are successfully added.
226 226 """
227 227
228 228 m = scmutil.match(repo[None], pats, opts)
229 229 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
230 230 return rejected and 1 or 0
231 231
232 232 @command('addremove',
233 233 similarityopts + subrepoopts + walkopts + dryrunopts,
234 234 _('[OPTION]... [FILE]...'),
235 235 inferrepo=True)
236 236 def addremove(ui, repo, *pats, **opts):
237 237 """add all new files, delete all missing files
238 238
239 239 Add all new files and remove all missing files from the
240 240 repository.
241 241
242 242 New files are ignored if they match any of the patterns in
243 243 ``.hgignore``. As with add, these changes take effect at the next
244 244 commit.
245 245
246 246 Use the -s/--similarity option to detect renamed files. This
247 247 option takes a percentage between 0 (disabled) and 100 (files must
248 248 be identical) as its parameter. With a parameter greater than 0,
249 249 this compares every removed file with every added file and records
250 250 those similar enough as renames. Detecting renamed files this way
251 251 can be expensive. After using this option, :hg:`status -C` can be
252 252 used to check which files were identified as moved or renamed. If
253 253 not specified, -s/--similarity defaults to 100 and only renames of
254 254 identical files are detected.
255 255
256 256 .. container:: verbose
257 257
258 258 Examples:
259 259
260 260 - A number of files (bar.c and foo.c) are new,
261 261 while foobar.c has been removed (without using :hg:`remove`)
262 262 from the repository::
263 263
264 264 $ ls
265 265 bar.c foo.c
266 266 $ hg status
267 267 ! foobar.c
268 268 ? bar.c
269 269 ? foo.c
270 270 $ hg addremove
271 271 adding bar.c
272 272 adding foo.c
273 273 removing foobar.c
274 274 $ hg status
275 275 A bar.c
276 276 A foo.c
277 277 R foobar.c
278 278
279 279 - A file foobar.c was moved to foo.c without using :hg:`rename`.
280 280 Afterwards, it was edited slightly::
281 281
282 282 $ ls
283 283 foo.c
284 284 $ hg status
285 285 ! foobar.c
286 286 ? foo.c
287 287 $ hg addremove --similarity 90
288 288 removing foobar.c
289 289 adding foo.c
290 290 recording removal of foobar.c as rename to foo.c (94% similar)
291 291 $ hg status -C
292 292 A foo.c
293 293 foobar.c
294 294 R foobar.c
295 295
296 296 Returns 0 if all files are successfully added.
297 297 """
298 298 try:
299 299 sim = float(opts.get('similarity') or 100)
300 300 except ValueError:
301 301 raise error.Abort(_('similarity must be a number'))
302 302 if sim < 0 or sim > 100:
303 303 raise error.Abort(_('similarity must be between 0 and 100'))
304 304 matcher = scmutil.match(repo[None], pats, opts)
305 305 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
306 306
307 307 @command('^annotate|blame',
308 308 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
309 309 ('', 'follow', None,
310 310 _('follow copies/renames and list the filename (DEPRECATED)')),
311 311 ('', 'no-follow', None, _("don't follow copies and renames")),
312 312 ('a', 'text', None, _('treat all files as text')),
313 313 ('u', 'user', None, _('list the author (long with -v)')),
314 314 ('f', 'file', None, _('list the filename')),
315 315 ('d', 'date', None, _('list the date (short with -q)')),
316 316 ('n', 'number', None, _('list the revision number (default)')),
317 317 ('c', 'changeset', None, _('list the changeset')),
318 318 ('l', 'line-number', None, _('show line number at the first appearance'))
319 319 ] + diffwsopts + walkopts + formatteropts,
320 320 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
321 321 inferrepo=True)
322 322 def annotate(ui, repo, *pats, **opts):
323 323 """show changeset information by line for each file
324 324
325 325 List changes in files, showing the revision id responsible for
326 326 each line
327 327
328 328 This command is useful for discovering when a change was made and
329 329 by whom.
330 330
331 331 Without the -a/--text option, annotate will avoid processing files
332 332 it detects as binary. With -a, annotate will annotate the file
333 333 anyway, although the results will probably be neither useful
334 334 nor desirable.
335 335
336 336 Returns 0 on success.
337 337 """
338 338 if not pats:
339 339 raise error.Abort(_('at least one filename or pattern is required'))
340 340
341 341 if opts.get('follow'):
342 342 # --follow is deprecated and now just an alias for -f/--file
343 343 # to mimic the behavior of Mercurial before version 1.5
344 344 opts['file'] = True
345 345
346 346 ctx = scmutil.revsingle(repo, opts.get('rev'))
347 347
348 348 fm = ui.formatter('annotate', opts)
349 349 if ui.quiet:
350 350 datefunc = util.shortdate
351 351 else:
352 352 datefunc = util.datestr
353 353 if ctx.rev() is None:
354 354 def hexfn(node):
355 355 if node is None:
356 356 return None
357 357 else:
358 358 return fm.hexfunc(node)
359 359 if opts.get('changeset'):
360 360 # omit "+" suffix which is appended to node hex
361 361 def formatrev(rev):
362 362 if rev is None:
363 363 return '%d' % ctx.p1().rev()
364 364 else:
365 365 return '%d' % rev
366 366 else:
367 367 def formatrev(rev):
368 368 if rev is None:
369 369 return '%d+' % ctx.p1().rev()
370 370 else:
371 371 return '%d ' % rev
372 372 def formathex(hex):
373 373 if hex is None:
374 374 return '%s+' % fm.hexfunc(ctx.p1().node())
375 375 else:
376 376 return '%s ' % hex
377 377 else:
378 378 hexfn = fm.hexfunc
379 379 formatrev = formathex = str
380 380
381 381 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
382 382 ('number', ' ', lambda x: x[0].rev(), formatrev),
383 383 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
384 384 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
385 385 ('file', ' ', lambda x: x[0].path(), str),
386 386 ('line_number', ':', lambda x: x[1], str),
387 387 ]
388 388 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
389 389
390 390 if (not opts.get('user') and not opts.get('changeset')
391 391 and not opts.get('date') and not opts.get('file')):
392 392 opts['number'] = True
393 393
394 394 linenumber = opts.get('line_number') is not None
395 395 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
396 396 raise error.Abort(_('at least one of -n/-c is required for -l'))
397 397
398 398 if fm:
399 399 def makefunc(get, fmt):
400 400 return get
401 401 else:
402 402 def makefunc(get, fmt):
403 403 return lambda x: fmt(get(x))
404 404 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
405 405 if opts.get(op)]
406 406 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
407 407 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
408 408 if opts.get(op))
409 409
410 410 def bad(x, y):
411 411 raise error.Abort("%s: %s" % (x, y))
412 412
413 413 m = scmutil.match(ctx, pats, opts, badfn=bad)
414 414
415 415 follow = not opts.get('no_follow')
416 416 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
417 417 whitespace=True)
418 418 for abs in ctx.walk(m):
419 419 fctx = ctx[abs]
420 420 if not opts.get('text') and util.binary(fctx.data()):
421 421 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
422 422 continue
423 423
424 424 lines = fctx.annotate(follow=follow, linenumber=linenumber,
425 425 diffopts=diffopts)
426 426 formats = []
427 427 pieces = []
428 428
429 429 for f, sep in funcmap:
430 430 l = [f(n) for n, dummy in lines]
431 431 if l:
432 432 if fm:
433 433 formats.append(['%s' for x in l])
434 434 else:
435 435 sizes = [encoding.colwidth(x) for x in l]
436 436 ml = max(sizes)
437 437 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
438 438 pieces.append(l)
439 439
440 440 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
441 441 fm.startitem()
442 442 fm.write(fields, "".join(f), *p)
443 443 fm.write('line', ": %s", l[1])
444 444
445 445 if lines and not lines[-1][1].endswith('\n'):
446 446 fm.plain('\n')
447 447
448 448 fm.end()
449 449
450 450 @command('archive',
451 451 [('', 'no-decode', None, _('do not pass files through decoders')),
452 452 ('p', 'prefix', '', _('directory prefix for files in archive'),
453 453 _('PREFIX')),
454 454 ('r', 'rev', '', _('revision to distribute'), _('REV')),
455 455 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
456 456 ] + subrepoopts + walkopts,
457 457 _('[OPTION]... DEST'))
458 458 def archive(ui, repo, dest, **opts):
459 459 '''create an unversioned archive of a repository revision
460 460
461 461 By default, the revision used is the parent of the working
462 462 directory; use -r/--rev to specify a different revision.
463 463
464 464 The archive type is automatically detected based on file
465 465 extension (or override using -t/--type).
466 466
467 467 .. container:: verbose
468 468
469 469 Examples:
470 470
471 471 - create a zip file containing the 1.0 release::
472 472
473 473 hg archive -r 1.0 project-1.0.zip
474 474
475 475 - create a tarball excluding .hg files::
476 476
477 477 hg archive project.tar.gz -X ".hg*"
478 478
479 479 Valid types are:
480 480
481 481 :``files``: a directory full of files (default)
482 482 :``tar``: tar archive, uncompressed
483 483 :``tbz2``: tar archive, compressed using bzip2
484 484 :``tgz``: tar archive, compressed using gzip
485 485 :``uzip``: zip archive, uncompressed
486 486 :``zip``: zip archive, compressed using deflate
487 487
488 488 The exact name of the destination archive or directory is given
489 489 using a format string; see :hg:`help export` for details.
490 490
491 491 Each member added to an archive file has a directory prefix
492 492 prepended. Use -p/--prefix to specify a format string for the
493 493 prefix. The default is the basename of the archive, with suffixes
494 494 removed.
495 495
496 496 Returns 0 on success.
497 497 '''
498 498
499 499 ctx = scmutil.revsingle(repo, opts.get('rev'))
500 500 if not ctx:
501 501 raise error.Abort(_('no working directory: please specify a revision'))
502 502 node = ctx.node()
503 503 dest = cmdutil.makefilename(repo, dest, node)
504 504 if os.path.realpath(dest) == repo.root:
505 505 raise error.Abort(_('repository root cannot be destination'))
506 506
507 507 kind = opts.get('type') or archival.guesskind(dest) or 'files'
508 508 prefix = opts.get('prefix')
509 509
510 510 if dest == '-':
511 511 if kind == 'files':
512 512 raise error.Abort(_('cannot archive plain files to stdout'))
513 513 dest = cmdutil.makefileobj(repo, dest)
514 514 if not prefix:
515 515 prefix = os.path.basename(repo.root) + '-%h'
516 516
517 517 prefix = cmdutil.makefilename(repo, prefix, node)
518 518 matchfn = scmutil.match(ctx, [], opts)
519 519 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
520 520 matchfn, prefix, subrepos=opts.get('subrepos'))
521 521
522 522 @command('backout',
523 523 [('', 'merge', None, _('merge with old dirstate parent after backout')),
524 524 ('', 'commit', None, _('commit if no conflicts were encountered')),
525 525 ('', 'parent', '',
526 526 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
527 527 ('r', 'rev', '', _('revision to backout'), _('REV')),
528 528 ('e', 'edit', False, _('invoke editor on commit messages')),
529 529 ] + mergetoolopts + walkopts + commitopts + commitopts2,
530 530 _('[OPTION]... [-r] REV'))
531 531 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
532 532 '''reverse effect of earlier changeset
533 533
534 534 Prepare a new changeset with the effect of REV undone in the
535 535 current working directory.
536 536
537 537 If REV is the parent of the working directory, then this new changeset
538 538 is committed automatically. Otherwise, hg needs to merge the
539 539 changes and the merged result is left uncommitted.
540 540
541 541 .. note::
542 542
543 543 backout cannot be used to fix either an unwanted or
544 544 incorrect merge.
545 545
546 546 .. container:: verbose
547 547
548 548 Examples:
549 549
550 550 - Reverse the effect of the parent of the working directory.
551 551 This backout will be committed immediately::
552 552
553 553 hg backout -r .
554 554
555 555 - Reverse the effect of previous bad revision 23::
556 556
557 557 hg backout -r 23
558 558 hg commit -m "Backout revision 23"
559 559
560 560 - Reverse the effect of previous bad revision 23 and
561 561 commit the backout immediately::
562 562
563 563 hg backout -r 23 --commit
564 564
565 565 By default, the pending changeset will have one parent,
566 566 maintaining a linear history. With --merge, the pending
567 567 changeset will instead have two parents: the old parent of the
568 568 working directory and a new child of REV that simply undoes REV.
569 569
570 570 Before version 1.7, the behavior without --merge was equivalent
571 571 to specifying --merge followed by :hg:`update --clean .` to
572 572 cancel the merge and leave the child of REV as a head to be
573 573 merged separately.
574 574
575 575 See :hg:`help dates` for a list of formats valid for -d/--date.
576 576
577 577 See :hg:`help revert` for a way to restore files to the state
578 578 of another revision.
579 579
580 580 Returns 0 on success, 1 if nothing to backout or there are unresolved
581 581 files.
582 582 '''
583 583 wlock = lock = None
584 584 try:
585 585 wlock = repo.wlock()
586 586 lock = repo.lock()
587 587 return _dobackout(ui, repo, node, rev, commit, **opts)
588 588 finally:
589 589 release(lock, wlock)
590 590
591 591 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
592 592 if rev and node:
593 593 raise error.Abort(_("please specify just one revision"))
594 594
595 595 if not rev:
596 596 rev = node
597 597
598 598 if not rev:
599 599 raise error.Abort(_("please specify a revision to backout"))
600 600
601 601 date = opts.get('date')
602 602 if date:
603 603 opts['date'] = util.parsedate(date)
604 604
605 605 cmdutil.checkunfinished(repo)
606 606 cmdutil.bailifchanged(repo)
607 607 node = scmutil.revsingle(repo, rev).node()
608 608
609 609 op1, op2 = repo.dirstate.parents()
610 610 if not repo.changelog.isancestor(node, op1):
611 611 raise error.Abort(_('cannot backout change that is not an ancestor'))
612 612
613 613 p1, p2 = repo.changelog.parents(node)
614 614 if p1 == nullid:
615 615 raise error.Abort(_('cannot backout a change with no parents'))
616 616 if p2 != nullid:
617 617 if not opts.get('parent'):
618 618 raise error.Abort(_('cannot backout a merge changeset'))
619 619 p = repo.lookup(opts['parent'])
620 620 if p not in (p1, p2):
621 621 raise error.Abort(_('%s is not a parent of %s') %
622 622 (short(p), short(node)))
623 623 parent = p
624 624 else:
625 625 if opts.get('parent'):
626 626 raise error.Abort(_('cannot use --parent on non-merge changeset'))
627 627 parent = p1
628 628
629 629 # the backout should appear on the same branch
630 630 try:
631 631 branch = repo.dirstate.branch()
632 632 bheads = repo.branchheads(branch)
633 633 rctx = scmutil.revsingle(repo, hex(parent))
634 634 if not opts.get('merge') and op1 != node:
635 635 dsguard = cmdutil.dirstateguard(repo, 'backout')
636 636 try:
637 637 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
638 638 'backout')
639 639 stats = mergemod.update(repo, parent, True, True, False,
640 640 node, False)
641 641 repo.setparents(op1, op2)
642 642 dsguard.close()
643 643 hg._showstats(repo, stats)
644 644 if stats[3]:
645 645 repo.ui.status(_("use 'hg resolve' to retry unresolved "
646 646 "file merges\n"))
647 647 return 1
648 648 elif not commit:
649 649 msg = _("changeset %s backed out, "
650 650 "don't forget to commit.\n")
651 651 ui.status(msg % short(node))
652 652 return 0
653 653 finally:
654 654 ui.setconfig('ui', 'forcemerge', '', '')
655 655 lockmod.release(dsguard)
656 656 else:
657 657 hg.clean(repo, node, show_stats=False)
658 658 repo.dirstate.setbranch(branch)
659 659 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
660 660
661 661
662 662 def commitfunc(ui, repo, message, match, opts):
663 663 editform = 'backout'
664 664 e = cmdutil.getcommiteditor(editform=editform, **opts)
665 665 if not message:
666 666 # we don't translate commit messages
667 667 message = "Backed out changeset %s" % short(node)
668 668 e = cmdutil.getcommiteditor(edit=True, editform=editform)
669 669 return repo.commit(message, opts.get('user'), opts.get('date'),
670 670 match, editor=e)
671 671 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
672 672 if not newnode:
673 673 ui.status(_("nothing changed\n"))
674 674 return 1
675 675 cmdutil.commitstatus(repo, newnode, branch, bheads)
676 676
677 677 def nice(node):
678 678 return '%d:%s' % (repo.changelog.rev(node), short(node))
679 679 ui.status(_('changeset %s backs out changeset %s\n') %
680 680 (nice(repo.changelog.tip()), nice(node)))
681 681 if opts.get('merge') and op1 != node:
682 682 hg.clean(repo, op1, show_stats=False)
683 683 ui.status(_('merging with changeset %s\n')
684 684 % nice(repo.changelog.tip()))
685 685 try:
686 686 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
687 687 'backout')
688 688 return hg.merge(repo, hex(repo.changelog.tip()))
689 689 finally:
690 690 ui.setconfig('ui', 'forcemerge', '', '')
691 691 finally:
692 692 # TODO: get rid of this meaningless try/finally enclosing.
693 693 # this is kept only to reduce changes in a patch.
694 694 pass
695 695 return 0
696 696
697 697 @command('bisect',
698 698 [('r', 'reset', False, _('reset bisect state')),
699 699 ('g', 'good', False, _('mark changeset good')),
700 700 ('b', 'bad', False, _('mark changeset bad')),
701 701 ('s', 'skip', False, _('skip testing changeset')),
702 702 ('e', 'extend', False, _('extend the bisect range')),
703 703 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
704 704 ('U', 'noupdate', False, _('do not update to target'))],
705 705 _("[-gbsr] [-U] [-c CMD] [REV]"))
706 706 def bisect(ui, repo, rev=None, extra=None, command=None,
707 707 reset=None, good=None, bad=None, skip=None, extend=None,
708 708 noupdate=None):
709 709 """subdivision search of changesets
710 710
711 711 This command helps to find changesets which introduce problems. To
712 712 use, mark the earliest changeset you know exhibits the problem as
713 713 bad, then mark the latest changeset which is free from the problem
714 714 as good. Bisect will update your working directory to a revision
715 715 for testing (unless the -U/--noupdate option is specified). Once
716 716 you have performed tests, mark the working directory as good or
717 717 bad, and bisect will either update to another candidate changeset
718 718 or announce that it has found the bad revision.
719 719
720 720 As a shortcut, you can also use the revision argument to mark a
721 721 revision as good or bad without checking it out first.
722 722
723 723 If you supply a command, it will be used for automatic bisection.
724 724 The environment variable HG_NODE will contain the ID of the
725 725 changeset being tested. The exit status of the command will be
726 726 used to mark revisions as good or bad: status 0 means good, 125
727 727 means to skip the revision, 127 (command not found) will abort the
728 728 bisection, and any other non-zero exit status means the revision
729 729 is bad.
730 730
731 731 .. container:: verbose
732 732
733 733 Some examples:
734 734
735 735 - start a bisection with known bad revision 34, and good revision 12::
736 736
737 737 hg bisect --bad 34
738 738 hg bisect --good 12
739 739
740 740 - advance the current bisection by marking current revision as good or
741 741 bad::
742 742
743 743 hg bisect --good
744 744 hg bisect --bad
745 745
746 746 - mark the current revision, or a known revision, to be skipped (e.g. if
747 747 that revision is not usable because of another issue)::
748 748
749 749 hg bisect --skip
750 750 hg bisect --skip 23
751 751
752 752 - skip all revisions that do not touch directories ``foo`` or ``bar``::
753 753
754 754 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
755 755
756 756 - forget the current bisection::
757 757
758 758 hg bisect --reset
759 759
760 760 - use 'make && make tests' to automatically find the first broken
761 761 revision::
762 762
763 763 hg bisect --reset
764 764 hg bisect --bad 34
765 765 hg bisect --good 12
766 766 hg bisect --command "make && make tests"
767 767
768 768 - see all changesets whose states are already known in the current
769 769 bisection::
770 770
771 771 hg log -r "bisect(pruned)"
772 772
773 773 - see the changeset currently being bisected (especially useful
774 774 if running with -U/--noupdate)::
775 775
776 776 hg log -r "bisect(current)"
777 777
778 778 - see all changesets that took part in the current bisection::
779 779
780 780 hg log -r "bisect(range)"
781 781
782 782 - you can even get a nice graph::
783 783
784 784 hg log --graph -r "bisect(range)"
785 785
786 786 See :hg:`help revsets` for more about the `bisect()` keyword.
787 787
788 788 Returns 0 on success.
789 789 """
790 790 def extendbisectrange(nodes, good):
791 791 # bisect is incomplete when it ends on a merge node and
792 792 # one of the parent was not checked.
793 793 parents = repo[nodes[0]].parents()
794 794 if len(parents) > 1:
795 795 if good:
796 796 side = state['bad']
797 797 else:
798 798 side = state['good']
799 799 num = len(set(i.node() for i in parents) & set(side))
800 800 if num == 1:
801 801 return parents[0].ancestor(parents[1])
802 802 return None
803 803
804 804 def print_result(nodes, good):
805 805 displayer = cmdutil.show_changeset(ui, repo, {})
806 806 if len(nodes) == 1:
807 807 # narrowed it down to a single revision
808 808 if good:
809 809 ui.write(_("The first good revision is:\n"))
810 810 else:
811 811 ui.write(_("The first bad revision is:\n"))
812 812 displayer.show(repo[nodes[0]])
813 813 extendnode = extendbisectrange(nodes, good)
814 814 if extendnode is not None:
815 815 ui.write(_('Not all ancestors of this changeset have been'
816 816 ' checked.\nUse bisect --extend to continue the '
817 817 'bisection from\nthe common ancestor, %s.\n')
818 818 % extendnode)
819 819 else:
820 820 # multiple possible revisions
821 821 if good:
822 822 ui.write(_("Due to skipped revisions, the first "
823 823 "good revision could be any of:\n"))
824 824 else:
825 825 ui.write(_("Due to skipped revisions, the first "
826 826 "bad revision could be any of:\n"))
827 827 for n in nodes:
828 828 displayer.show(repo[n])
829 829 displayer.close()
830 830
831 831 def check_state(state, interactive=True):
832 832 if not state['good'] or not state['bad']:
833 833 if (good or bad or skip or reset) and interactive:
834 834 return
835 835 if not state['good']:
836 836 raise error.Abort(_('cannot bisect (no known good revisions)'))
837 837 else:
838 838 raise error.Abort(_('cannot bisect (no known bad revisions)'))
839 839 return True
840 840
841 841 # backward compatibility
842 842 if rev in "good bad reset init".split():
843 843 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
844 844 cmd, rev, extra = rev, extra, None
845 845 if cmd == "good":
846 846 good = True
847 847 elif cmd == "bad":
848 848 bad = True
849 849 else:
850 850 reset = True
851 851 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
852 852 raise error.Abort(_('incompatible arguments'))
853 853
854 854 cmdutil.checkunfinished(repo)
855 855
856 856 if reset:
857 857 p = repo.join("bisect.state")
858 858 if os.path.exists(p):
859 859 os.unlink(p)
860 860 return
861 861
862 862 state = hbisect.load_state(repo)
863 863
864 864 if command:
865 865 changesets = 1
866 866 if noupdate:
867 867 try:
868 868 node = state['current'][0]
869 869 except LookupError:
870 870 raise error.Abort(_('current bisect revision is unknown - '
871 871 'start a new bisect to fix'))
872 872 else:
873 873 node, p2 = repo.dirstate.parents()
874 874 if p2 != nullid:
875 875 raise error.Abort(_('current bisect revision is a merge'))
876 876 try:
877 877 while changesets:
878 878 # update state
879 879 state['current'] = [node]
880 880 hbisect.save_state(repo, state)
881 881 status = ui.system(command, environ={'HG_NODE': hex(node)})
882 882 if status == 125:
883 883 transition = "skip"
884 884 elif status == 0:
885 885 transition = "good"
886 886 # status < 0 means process was killed
887 887 elif status == 127:
888 888 raise error.Abort(_("failed to execute %s") % command)
889 889 elif status < 0:
890 890 raise error.Abort(_("%s killed") % command)
891 891 else:
892 892 transition = "bad"
893 893 ctx = scmutil.revsingle(repo, rev, node)
894 894 rev = None # clear for future iterations
895 895 state[transition].append(ctx.node())
896 896 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
897 897 check_state(state, interactive=False)
898 898 # bisect
899 899 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
900 900 # update to next check
901 901 node = nodes[0]
902 902 if not noupdate:
903 903 cmdutil.bailifchanged(repo)
904 904 hg.clean(repo, node, show_stats=False)
905 905 finally:
906 906 state['current'] = [node]
907 907 hbisect.save_state(repo, state)
908 908 print_result(nodes, bgood)
909 909 return
910 910
911 911 # update state
912 912
913 913 if rev:
914 914 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
915 915 else:
916 916 nodes = [repo.lookup('.')]
917 917
918 918 if good or bad or skip:
919 919 if good:
920 920 state['good'] += nodes
921 921 elif bad:
922 922 state['bad'] += nodes
923 923 elif skip:
924 924 state['skip'] += nodes
925 925 hbisect.save_state(repo, state)
926 926
927 927 if not check_state(state):
928 928 return
929 929
930 930 # actually bisect
931 931 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
932 932 if extend:
933 933 if not changesets:
934 934 extendnode = extendbisectrange(nodes, good)
935 935 if extendnode is not None:
936 936 ui.write(_("Extending search to changeset %d:%s\n")
937 937 % (extendnode.rev(), extendnode))
938 938 state['current'] = [extendnode.node()]
939 939 hbisect.save_state(repo, state)
940 940 if noupdate:
941 941 return
942 942 cmdutil.bailifchanged(repo)
943 943 return hg.clean(repo, extendnode.node())
944 944 raise error.Abort(_("nothing to extend"))
945 945
946 946 if changesets == 0:
947 947 print_result(nodes, good)
948 948 else:
949 949 assert len(nodes) == 1 # only a single node can be tested next
950 950 node = nodes[0]
951 951 # compute the approximate number of remaining tests
952 952 tests, size = 0, 2
953 953 while size <= changesets:
954 954 tests, size = tests + 1, size * 2
955 955 rev = repo.changelog.rev(node)
956 956 ui.write(_("Testing changeset %d:%s "
957 957 "(%d changesets remaining, ~%d tests)\n")
958 958 % (rev, short(node), changesets, tests))
959 959 state['current'] = [node]
960 960 hbisect.save_state(repo, state)
961 961 if not noupdate:
962 962 cmdutil.bailifchanged(repo)
963 963 return hg.clean(repo, node)
964 964
965 965 @command('bookmarks|bookmark',
966 966 [('f', 'force', False, _('force')),
967 967 ('r', 'rev', '', _('revision'), _('REV')),
968 968 ('d', 'delete', False, _('delete a given bookmark')),
969 969 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
970 970 ('i', 'inactive', False, _('mark a bookmark inactive')),
971 971 ] + formatteropts,
972 972 _('hg bookmarks [OPTIONS]... [NAME]...'))
973 973 def bookmark(ui, repo, *names, **opts):
974 974 '''create a new bookmark or list existing bookmarks
975 975
976 976 Bookmarks are labels on changesets to help track lines of development.
977 977 Bookmarks are unversioned and can be moved, renamed and deleted.
978 978 Deleting or moving a bookmark has no effect on the associated changesets.
979 979
980 980 Creating or updating to a bookmark causes it to be marked as 'active'.
981 981 The active bookmark is indicated with a '*'.
982 982 When a commit is made, the active bookmark will advance to the new commit.
983 983 A plain :hg:`update` will also advance an active bookmark, if possible.
984 984 Updating away from a bookmark will cause it to be deactivated.
985 985
986 986 Bookmarks can be pushed and pulled between repositories (see
987 987 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
988 988 diverged, a new 'divergent bookmark' of the form 'name@path' will
989 989 be created. Using :hg:`merge` will resolve the divergence.
990 990
991 991 A bookmark named '@' has the special property that :hg:`clone` will
992 992 check it out by default if it exists.
993 993
994 994 .. container:: verbose
995 995
996 996 Examples:
997 997
998 998 - create an active bookmark for a new line of development::
999 999
1000 1000 hg book new-feature
1001 1001
1002 1002 - create an inactive bookmark as a place marker::
1003 1003
1004 1004 hg book -i reviewed
1005 1005
1006 1006 - create an inactive bookmark on another changeset::
1007 1007
1008 1008 hg book -r .^ tested
1009 1009
1010 1010 - rename bookmark turkey to dinner::
1011 1011
1012 1012 hg book -m turkey dinner
1013 1013
1014 1014 - move the '@' bookmark from another branch::
1015 1015
1016 1016 hg book -f @
1017 1017 '''
1018 1018 force = opts.get('force')
1019 1019 rev = opts.get('rev')
1020 1020 delete = opts.get('delete')
1021 1021 rename = opts.get('rename')
1022 1022 inactive = opts.get('inactive')
1023 1023
1024 1024 def checkformat(mark):
1025 1025 mark = mark.strip()
1026 1026 if not mark:
1027 1027 raise error.Abort(_("bookmark names cannot consist entirely of "
1028 1028 "whitespace"))
1029 1029 scmutil.checknewlabel(repo, mark, 'bookmark')
1030 1030 return mark
1031 1031
1032 1032 def checkconflict(repo, mark, cur, force=False, target=None):
1033 1033 if mark in marks and not force:
1034 1034 if target:
1035 1035 if marks[mark] == target and target == cur:
1036 1036 # re-activating a bookmark
1037 1037 return
1038 1038 anc = repo.changelog.ancestors([repo[target].rev()])
1039 1039 bmctx = repo[marks[mark]]
1040 1040 divs = [repo[b].node() for b in marks
1041 1041 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1042 1042
1043 1043 # allow resolving a single divergent bookmark even if moving
1044 1044 # the bookmark across branches when a revision is specified
1045 1045 # that contains a divergent bookmark
1046 1046 if bmctx.rev() not in anc and target in divs:
1047 1047 bookmarks.deletedivergent(repo, [target], mark)
1048 1048 return
1049 1049
1050 1050 deletefrom = [b for b in divs
1051 1051 if repo[b].rev() in anc or b == target]
1052 1052 bookmarks.deletedivergent(repo, deletefrom, mark)
1053 1053 if bookmarks.validdest(repo, bmctx, repo[target]):
1054 1054 ui.status(_("moving bookmark '%s' forward from %s\n") %
1055 1055 (mark, short(bmctx.node())))
1056 1056 return
1057 1057 raise error.Abort(_("bookmark '%s' already exists "
1058 1058 "(use -f to force)") % mark)
1059 1059 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1060 1060 and not force):
1061 1061 raise error.Abort(
1062 1062 _("a bookmark cannot have the name of an existing branch"))
1063 1063
1064 1064 if delete and rename:
1065 1065 raise error.Abort(_("--delete and --rename are incompatible"))
1066 1066 if delete and rev:
1067 1067 raise error.Abort(_("--rev is incompatible with --delete"))
1068 1068 if rename and rev:
1069 1069 raise error.Abort(_("--rev is incompatible with --rename"))
1070 1070 if not names and (delete or rev):
1071 1071 raise error.Abort(_("bookmark name required"))
1072 1072
1073 1073 if delete or rename or names or inactive:
1074 1074 wlock = lock = tr = None
1075 1075 try:
1076 1076 wlock = repo.wlock()
1077 1077 lock = repo.lock()
1078 1078 cur = repo.changectx('.').node()
1079 1079 marks = repo._bookmarks
1080 1080 if delete:
1081 1081 tr = repo.transaction('bookmark')
1082 1082 for mark in names:
1083 1083 if mark not in marks:
1084 1084 raise error.Abort(_("bookmark '%s' does not exist") %
1085 1085 mark)
1086 1086 if mark == repo._activebookmark:
1087 1087 bookmarks.deactivate(repo)
1088 1088 del marks[mark]
1089 1089
1090 1090 elif rename:
1091 1091 tr = repo.transaction('bookmark')
1092 1092 if not names:
1093 1093 raise error.Abort(_("new bookmark name required"))
1094 1094 elif len(names) > 1:
1095 1095 raise error.Abort(_("only one new bookmark name allowed"))
1096 1096 mark = checkformat(names[0])
1097 1097 if rename not in marks:
1098 1098 raise error.Abort(_("bookmark '%s' does not exist")
1099 1099 % rename)
1100 1100 checkconflict(repo, mark, cur, force)
1101 1101 marks[mark] = marks[rename]
1102 1102 if repo._activebookmark == rename and not inactive:
1103 1103 bookmarks.activate(repo, mark)
1104 1104 del marks[rename]
1105 1105 elif names:
1106 1106 tr = repo.transaction('bookmark')
1107 1107 newact = None
1108 1108 for mark in names:
1109 1109 mark = checkformat(mark)
1110 1110 if newact is None:
1111 1111 newact = mark
1112 1112 if inactive and mark == repo._activebookmark:
1113 1113 bookmarks.deactivate(repo)
1114 1114 return
1115 1115 tgt = cur
1116 1116 if rev:
1117 1117 tgt = scmutil.revsingle(repo, rev).node()
1118 1118 checkconflict(repo, mark, cur, force, tgt)
1119 1119 marks[mark] = tgt
1120 1120 if not inactive and cur == marks[newact] and not rev:
1121 1121 bookmarks.activate(repo, newact)
1122 1122 elif cur != tgt and newact == repo._activebookmark:
1123 1123 bookmarks.deactivate(repo)
1124 1124 elif inactive:
1125 1125 if len(marks) == 0:
1126 1126 ui.status(_("no bookmarks set\n"))
1127 1127 elif not repo._activebookmark:
1128 1128 ui.status(_("no active bookmark\n"))
1129 1129 else:
1130 1130 bookmarks.deactivate(repo)
1131 1131 if tr is not None:
1132 1132 marks.recordchange(tr)
1133 1133 tr.close()
1134 1134 finally:
1135 1135 lockmod.release(tr, lock, wlock)
1136 1136 else: # show bookmarks
1137 1137 fm = ui.formatter('bookmarks', opts)
1138 1138 hexfn = fm.hexfunc
1139 1139 marks = repo._bookmarks
1140 1140 if len(marks) == 0 and not fm:
1141 1141 ui.status(_("no bookmarks set\n"))
1142 1142 for bmark, n in sorted(marks.iteritems()):
1143 1143 active = repo._activebookmark
1144 1144 if bmark == active:
1145 1145 prefix, label = '*', activebookmarklabel
1146 1146 else:
1147 1147 prefix, label = ' ', ''
1148 1148
1149 1149 fm.startitem()
1150 1150 if not ui.quiet:
1151 1151 fm.plain(' %s ' % prefix, label=label)
1152 1152 fm.write('bookmark', '%s', bmark, label=label)
1153 1153 pad = " " * (25 - encoding.colwidth(bmark))
1154 1154 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1155 1155 repo.changelog.rev(n), hexfn(n), label=label)
1156 1156 fm.data(active=(bmark == active))
1157 1157 fm.plain('\n')
1158 1158 fm.end()
1159 1159
1160 1160 @command('branch',
1161 1161 [('f', 'force', None,
1162 1162 _('set branch name even if it shadows an existing branch')),
1163 1163 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1164 1164 _('[-fC] [NAME]'))
1165 1165 def branch(ui, repo, label=None, **opts):
1166 1166 """set or show the current branch name
1167 1167
1168 1168 .. note::
1169 1169
1170 1170 Branch names are permanent and global. Use :hg:`bookmark` to create a
1171 1171 light-weight bookmark instead. See :hg:`help glossary` for more
1172 1172 information about named branches and bookmarks.
1173 1173
1174 1174 With no argument, show the current branch name. With one argument,
1175 1175 set the working directory branch name (the branch will not exist
1176 1176 in the repository until the next commit). Standard practice
1177 1177 recommends that primary development take place on the 'default'
1178 1178 branch.
1179 1179
1180 1180 Unless -f/--force is specified, branch will not let you set a
1181 1181 branch name that already exists.
1182 1182
1183 1183 Use -C/--clean to reset the working directory branch to that of
1184 1184 the parent of the working directory, negating a previous branch
1185 1185 change.
1186 1186
1187 1187 Use the command :hg:`update` to switch to an existing branch. Use
1188 1188 :hg:`commit --close-branch` to mark this branch head as closed.
1189 1189 When all heads of the branch are closed, the branch will be
1190 1190 considered closed.
1191 1191
1192 1192 Returns 0 on success.
1193 1193 """
1194 1194 if label:
1195 1195 label = label.strip()
1196 1196
1197 1197 if not opts.get('clean') and not label:
1198 1198 ui.write("%s\n" % repo.dirstate.branch())
1199 1199 return
1200 1200
1201 1201 wlock = repo.wlock()
1202 1202 try:
1203 1203 if opts.get('clean'):
1204 1204 label = repo[None].p1().branch()
1205 1205 repo.dirstate.setbranch(label)
1206 1206 ui.status(_('reset working directory to branch %s\n') % label)
1207 1207 elif label:
1208 1208 if not opts.get('force') and label in repo.branchmap():
1209 1209 if label not in [p.branch() for p in repo[None].parents()]:
1210 1210 raise error.Abort(_('a branch of the same name already'
1211 1211 ' exists'),
1212 1212 # i18n: "it" refers to an existing branch
1213 1213 hint=_("use 'hg update' to switch to it"))
1214 1214 scmutil.checknewlabel(repo, label, 'branch')
1215 1215 repo.dirstate.setbranch(label)
1216 1216 ui.status(_('marked working directory as branch %s\n') % label)
1217 1217
1218 1218 # find any open named branches aside from default
1219 1219 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1220 1220 if n != "default" and not c]
1221 1221 if not others:
1222 1222 ui.status(_('(branches are permanent and global, '
1223 1223 'did you want a bookmark?)\n'))
1224 1224 finally:
1225 1225 wlock.release()
1226 1226
1227 1227 @command('branches',
1228 1228 [('a', 'active', False,
1229 1229 _('show only branches that have unmerged heads (DEPRECATED)')),
1230 1230 ('c', 'closed', False, _('show normal and closed branches')),
1231 1231 ] + formatteropts,
1232 1232 _('[-ac]'))
1233 1233 def branches(ui, repo, active=False, closed=False, **opts):
1234 1234 """list repository named branches
1235 1235
1236 1236 List the repository's named branches, indicating which ones are
1237 1237 inactive. If -c/--closed is specified, also list branches which have
1238 1238 been marked closed (see :hg:`commit --close-branch`).
1239 1239
1240 1240 Use the command :hg:`update` to switch to an existing branch.
1241 1241
1242 1242 Returns 0.
1243 1243 """
1244 1244
1245 1245 fm = ui.formatter('branches', opts)
1246 1246 hexfunc = fm.hexfunc
1247 1247
1248 1248 allheads = set(repo.heads())
1249 1249 branches = []
1250 1250 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1251 1251 isactive = not isclosed and bool(set(heads) & allheads)
1252 1252 branches.append((tag, repo[tip], isactive, not isclosed))
1253 1253 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1254 1254 reverse=True)
1255 1255
1256 1256 for tag, ctx, isactive, isopen in branches:
1257 1257 if active and not isactive:
1258 1258 continue
1259 1259 if isactive:
1260 1260 label = 'branches.active'
1261 1261 notice = ''
1262 1262 elif not isopen:
1263 1263 if not closed:
1264 1264 continue
1265 1265 label = 'branches.closed'
1266 1266 notice = _(' (closed)')
1267 1267 else:
1268 1268 label = 'branches.inactive'
1269 1269 notice = _(' (inactive)')
1270 1270 current = (tag == repo.dirstate.branch())
1271 1271 if current:
1272 1272 label = 'branches.current'
1273 1273
1274 1274 fm.startitem()
1275 1275 fm.write('branch', '%s', tag, label=label)
1276 1276 rev = ctx.rev()
1277 1277 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1278 1278 fmt = ' ' * padsize + ' %d:%s'
1279 1279 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1280 1280 label='log.changeset changeset.%s' % ctx.phasestr())
1281 1281 fm.data(active=isactive, closed=not isopen, current=current)
1282 1282 if not ui.quiet:
1283 1283 fm.plain(notice)
1284 1284 fm.plain('\n')
1285 1285 fm.end()
1286 1286
1287 1287 @command('bundle',
1288 1288 [('f', 'force', None, _('run even when the destination is unrelated')),
1289 1289 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1290 1290 _('REV')),
1291 1291 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1292 1292 _('BRANCH')),
1293 1293 ('', 'base', [],
1294 1294 _('a base changeset assumed to be available at the destination'),
1295 1295 _('REV')),
1296 1296 ('a', 'all', None, _('bundle all changesets in the repository')),
1297 1297 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1298 1298 ] + remoteopts,
1299 1299 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1300 1300 def bundle(ui, repo, fname, dest=None, **opts):
1301 1301 """create a changegroup file
1302 1302
1303 1303 Generate a compressed changegroup file collecting changesets not
1304 1304 known to be in another repository.
1305 1305
1306 1306 If you omit the destination repository, then hg assumes the
1307 1307 destination will have all the nodes you specify with --base
1308 1308 parameters. To create a bundle containing all changesets, use
1309 1309 -a/--all (or --base null).
1310 1310
1311 1311 You can change bundle format with the -t/--type option. You can
1312 1312 specify a compression, a bundle version or both using a dash
1313 1313 (comp-version). The available compression methods are: none, bzip2,
1314 1314 and gzip (by default, bundles are compressed using bzip2). The
1315 1315 available format are: v1, v2 (default to most suitable).
1316 1316
1317 1317 The bundle file can then be transferred using conventional means
1318 1318 and applied to another repository with the unbundle or pull
1319 1319 command. This is useful when direct push and pull are not
1320 1320 available or when exporting an entire repository is undesirable.
1321 1321
1322 1322 Applying bundles preserves all changeset contents including
1323 1323 permissions, copy/rename information, and revision history.
1324 1324
1325 1325 Returns 0 on success, 1 if no changes found.
1326 1326 """
1327 1327 revs = None
1328 1328 if 'rev' in opts:
1329 1329 revs = scmutil.revrange(repo, opts['rev'])
1330 1330
1331 1331 bundletype = opts.get('type', 'bzip2').lower()
1332 1332 try:
1333 1333 bcompression, cgversion, params = exchange.parsebundlespec(
1334 1334 repo, bundletype, strict=False)
1335 1335 except error.UnsupportedBundleSpecification as e:
1336 1336 raise error.Abort(str(e),
1337 1337 hint=_('see "hg help bundle" for supported '
1338 1338 'values for --type'))
1339 1339
1340 1340 # Packed bundles are a pseudo bundle format for now.
1341 1341 if cgversion == 's1':
1342 1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1343 1343 hint=_('use "hg debugcreatestreamclonebundle"'))
1344 1344
1345 1345 if opts.get('all'):
1346 1346 base = ['null']
1347 1347 else:
1348 1348 base = scmutil.revrange(repo, opts.get('base'))
1349 1349 # TODO: get desired bundlecaps from command line.
1350 1350 bundlecaps = None
1351 1351 if base:
1352 1352 if dest:
1353 1353 raise error.Abort(_("--base is incompatible with specifying "
1354 1354 "a destination"))
1355 1355 common = [repo.lookup(rev) for rev in base]
1356 1356 heads = revs and map(repo.lookup, revs) or revs
1357 1357 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1358 1358 common=common, bundlecaps=bundlecaps,
1359 1359 version=cgversion)
1360 1360 outgoing = None
1361 1361 else:
1362 1362 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1363 1363 dest, branches = hg.parseurl(dest, opts.get('branch'))
1364 1364 other = hg.peer(repo, opts, dest)
1365 1365 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1366 1366 heads = revs and map(repo.lookup, revs) or revs
1367 1367 outgoing = discovery.findcommonoutgoing(repo, other,
1368 1368 onlyheads=heads,
1369 1369 force=opts.get('force'),
1370 1370 portable=True)
1371 1371 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1372 1372 bundlecaps, version=cgversion)
1373 1373 if not cg:
1374 1374 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1375 1375 return 1
1376 1376
1377 1377 if cgversion == '01': #bundle1
1378 1378 if bcompression is None:
1379 1379 bcompression = 'UN'
1380 1380 bversion = 'HG10' + bcompression
1381 1381 bcompression = None
1382 1382 else:
1383 1383 assert cgversion == '02'
1384 1384 bversion = 'HG20'
1385 1385
1386 1386
1387 1387 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1388 1388
1389 1389 @command('cat',
1390 1390 [('o', 'output', '',
1391 1391 _('print output to file with formatted name'), _('FORMAT')),
1392 1392 ('r', 'rev', '', _('print the given revision'), _('REV')),
1393 1393 ('', 'decode', None, _('apply any matching decode filter')),
1394 1394 ] + walkopts,
1395 1395 _('[OPTION]... FILE...'),
1396 1396 inferrepo=True)
1397 1397 def cat(ui, repo, file1, *pats, **opts):
1398 1398 """output the current or given revision of files
1399 1399
1400 1400 Print the specified files as they were at the given revision. If
1401 1401 no revision is given, the parent of the working directory is used.
1402 1402
1403 1403 Output may be to a file, in which case the name of the file is
1404 1404 given using a format string. The formatting rules as follows:
1405 1405
1406 1406 :``%%``: literal "%" character
1407 1407 :``%s``: basename of file being printed
1408 1408 :``%d``: dirname of file being printed, or '.' if in repository root
1409 1409 :``%p``: root-relative path name of file being printed
1410 1410 :``%H``: changeset hash (40 hexadecimal digits)
1411 1411 :``%R``: changeset revision number
1412 1412 :``%h``: short-form changeset hash (12 hexadecimal digits)
1413 1413 :``%r``: zero-padded changeset revision number
1414 1414 :``%b``: basename of the exporting repository
1415 1415
1416 1416 Returns 0 on success.
1417 1417 """
1418 1418 ctx = scmutil.revsingle(repo, opts.get('rev'))
1419 1419 m = scmutil.match(ctx, (file1,) + pats, opts)
1420 1420
1421 1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1422 1422
1423 1423 @command('^clone',
1424 1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1425 1425 'directory (only a repository)')),
1426 1426 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1427 1427 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1428 1428 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1429 1429 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 1430 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1431 1431 ] + remoteopts,
1432 1432 _('[OPTION]... SOURCE [DEST]'),
1433 1433 norepo=True)
1434 1434 def clone(ui, source, dest=None, **opts):
1435 1435 """make a copy of an existing repository
1436 1436
1437 1437 Create a copy of an existing repository in a new directory.
1438 1438
1439 1439 If no destination directory name is specified, it defaults to the
1440 1440 basename of the source.
1441 1441
1442 1442 The location of the source is added to the new repository's
1443 1443 ``.hg/hgrc`` file, as the default to be used for future pulls.
1444 1444
1445 1445 Only local paths and ``ssh://`` URLs are supported as
1446 1446 destinations. For ``ssh://`` destinations, no working directory or
1447 1447 ``.hg/hgrc`` will be created on the remote side.
1448 1448
1449 1449 To pull only a subset of changesets, specify one or more revisions
1450 1450 identifiers with -r/--rev or branches with -b/--branch. The
1451 1451 resulting clone will contain only the specified changesets and
1452 1452 their ancestors. These options (or 'clone src#rev dest') imply
1453 1453 --pull, even for local source repositories. Note that specifying a
1454 1454 tag will include the tagged changeset but not the changeset
1455 1455 containing the tag.
1456 1456
1457 1457 If the source repository has a bookmark called '@' set, that
1458 1458 revision will be checked out in the new repository by default.
1459 1459
1460 1460 To check out a particular version, use -u/--update, or
1461 1461 -U/--noupdate to create a clone with no working directory.
1462 1462
1463 1463 .. container:: verbose
1464 1464
1465 1465 For efficiency, hardlinks are used for cloning whenever the
1466 1466 source and destination are on the same filesystem (note this
1467 1467 applies only to the repository data, not to the working
1468 1468 directory). Some filesystems, such as AFS, implement hardlinking
1469 1469 incorrectly, but do not report errors. In these cases, use the
1470 1470 --pull option to avoid hardlinking.
1471 1471
1472 1472 In some cases, you can clone repositories and the working
1473 1473 directory using full hardlinks with ::
1474 1474
1475 1475 $ cp -al REPO REPOCLONE
1476 1476
1477 1477 This is the fastest way to clone, but it is not always safe. The
1478 1478 operation is not atomic (making sure REPO is not modified during
1479 1479 the operation is up to you) and you have to make sure your
1480 1480 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1481 1481 so). Also, this is not compatible with certain extensions that
1482 1482 place their metadata under the .hg directory, such as mq.
1483 1483
1484 1484 Mercurial will update the working directory to the first applicable
1485 1485 revision from this list:
1486 1486
1487 1487 a) null if -U or the source repository has no changesets
1488 1488 b) if -u . and the source repository is local, the first parent of
1489 1489 the source repository's working directory
1490 1490 c) the changeset specified with -u (if a branch name, this means the
1491 1491 latest head of that branch)
1492 1492 d) the changeset specified with -r
1493 1493 e) the tipmost head specified with -b
1494 1494 f) the tipmost head specified with the url#branch source syntax
1495 1495 g) the revision marked with the '@' bookmark, if present
1496 1496 h) the tipmost head of the default branch
1497 1497 i) tip
1498 1498
1499 1499 Examples:
1500 1500
1501 1501 - clone a remote repository to a new directory named hg/::
1502 1502
1503 1503 hg clone http://selenic.com/hg
1504 1504
1505 1505 - create a lightweight local clone::
1506 1506
1507 1507 hg clone project/ project-feature/
1508 1508
1509 1509 - clone from an absolute path on an ssh server (note double-slash)::
1510 1510
1511 1511 hg clone ssh://user@server//home/projects/alpha/
1512 1512
1513 1513 - do a high-speed clone over a LAN while checking out a
1514 1514 specified version::
1515 1515
1516 1516 hg clone --uncompressed http://server/repo -u 1.5
1517 1517
1518 1518 - create a repository without changesets after a particular revision::
1519 1519
1520 1520 hg clone -r 04e544 experimental/ good/
1521 1521
1522 1522 - clone (and track) a particular named branch::
1523 1523
1524 1524 hg clone http://selenic.com/hg#stable
1525 1525
1526 1526 See :hg:`help urls` for details on specifying URLs.
1527 1527
1528 1528 Returns 0 on success.
1529 1529 """
1530 1530 if opts.get('noupdate') and opts.get('updaterev'):
1531 1531 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1532 1532
1533 1533 r = hg.clone(ui, opts, source, dest,
1534 1534 pull=opts.get('pull'),
1535 1535 stream=opts.get('uncompressed'),
1536 1536 rev=opts.get('rev'),
1537 1537 update=opts.get('updaterev') or not opts.get('noupdate'),
1538 1538 branch=opts.get('branch'),
1539 1539 shareopts=opts.get('shareopts'))
1540 1540
1541 1541 return r is None
1542 1542
1543 1543 @command('^commit|ci',
1544 1544 [('A', 'addremove', None,
1545 1545 _('mark new/missing files as added/removed before committing')),
1546 1546 ('', 'close-branch', None,
1547 1547 _('mark a branch head as closed')),
1548 1548 ('', 'amend', None, _('amend the parent of the working directory')),
1549 1549 ('s', 'secret', None, _('use the secret phase for committing')),
1550 1550 ('e', 'edit', None, _('invoke editor on commit messages')),
1551 1551 ('i', 'interactive', None, _('use interactive mode')),
1552 1552 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1553 1553 _('[OPTION]... [FILE]...'),
1554 1554 inferrepo=True)
1555 1555 def commit(ui, repo, *pats, **opts):
1556 1556 """commit the specified files or all outstanding changes
1557 1557
1558 1558 Commit changes to the given files into the repository. Unlike a
1559 1559 centralized SCM, this operation is a local operation. See
1560 1560 :hg:`push` for a way to actively distribute your changes.
1561 1561
1562 1562 If a list of files is omitted, all changes reported by :hg:`status`
1563 1563 will be committed.
1564 1564
1565 1565 If you are committing the result of a merge, do not provide any
1566 1566 filenames or -I/-X filters.
1567 1567
1568 1568 If no commit message is specified, Mercurial starts your
1569 1569 configured editor where you can enter a message. In case your
1570 1570 commit fails, you will find a backup of your message in
1571 1571 ``.hg/last-message.txt``.
1572 1572
1573 1573 The --close-branch flag can be used to mark the current branch
1574 1574 head closed. When all heads of a branch are closed, the branch
1575 1575 will be considered closed and no longer listed.
1576 1576
1577 1577 The --amend flag can be used to amend the parent of the
1578 1578 working directory with a new commit that contains the changes
1579 1579 in the parent in addition to those currently reported by :hg:`status`,
1580 1580 if there are any. The old commit is stored in a backup bundle in
1581 1581 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1582 1582 on how to restore it).
1583 1583
1584 1584 Message, user and date are taken from the amended commit unless
1585 1585 specified. When a message isn't specified on the command line,
1586 1586 the editor will open with the message of the amended commit.
1587 1587
1588 1588 It is not possible to amend public changesets (see :hg:`help phases`)
1589 1589 or changesets that have children.
1590 1590
1591 1591 See :hg:`help dates` for a list of formats valid for -d/--date.
1592 1592
1593 1593 Returns 0 on success, 1 if nothing changed.
1594 1594
1595 1595 .. container:: verbose
1596 1596
1597 1597 Examples:
1598 1598
1599 1599 - commit all files ending in .py::
1600 1600
1601 1601 hg commit --include "set:**.py"
1602 1602
1603 1603 - commit all non-binary files::
1604 1604
1605 1605 hg commit --exclude "set:binary()"
1606 1606
1607 1607 - amend the current commit and set the date to now::
1608 1608
1609 1609 hg commit --amend --date now
1610 1610 """
1611 1611 wlock = lock = None
1612 1612 try:
1613 1613 wlock = repo.wlock()
1614 1614 lock = repo.lock()
1615 1615 return _docommit(ui, repo, *pats, **opts)
1616 1616 finally:
1617 1617 release(lock, wlock)
1618 1618
1619 1619 def _docommit(ui, repo, *pats, **opts):
1620 1620 if opts.get('interactive'):
1621 1621 opts.pop('interactive')
1622 1622 cmdutil.dorecord(ui, repo, commit, None, False,
1623 1623 cmdutil.recordfilter, *pats, **opts)
1624 1624 return
1625 1625
1626 1626 if opts.get('subrepos'):
1627 1627 if opts.get('amend'):
1628 1628 raise error.Abort(_('cannot amend with --subrepos'))
1629 1629 # Let --subrepos on the command line override config setting.
1630 1630 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1631 1631
1632 1632 cmdutil.checkunfinished(repo, commit=True)
1633 1633
1634 1634 branch = repo[None].branch()
1635 1635 bheads = repo.branchheads(branch)
1636 1636
1637 1637 extra = {}
1638 1638 if opts.get('close_branch'):
1639 1639 extra['close'] = 1
1640 1640
1641 1641 if not bheads:
1642 1642 raise error.Abort(_('can only close branch heads'))
1643 1643 elif opts.get('amend'):
1644 1644 if repo[None].parents()[0].p1().branch() != branch and \
1645 1645 repo[None].parents()[0].p2().branch() != branch:
1646 1646 raise error.Abort(_('can only close branch heads'))
1647 1647
1648 1648 if opts.get('amend'):
1649 1649 if ui.configbool('ui', 'commitsubrepos'):
1650 1650 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1651 1651
1652 1652 old = repo['.']
1653 1653 if not old.mutable():
1654 1654 raise error.Abort(_('cannot amend public changesets'))
1655 1655 if len(repo[None].parents()) > 1:
1656 1656 raise error.Abort(_('cannot amend while merging'))
1657 1657 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1658 1658 if not allowunstable and old.children():
1659 1659 raise error.Abort(_('cannot amend changeset with children'))
1660 1660
1661 1661 newextra = extra.copy()
1662 1662 newextra['branch'] = branch
1663 1663 extra = newextra
1664 1664 # commitfunc is used only for temporary amend commit by cmdutil.amend
1665 1665 def commitfunc(ui, repo, message, match, opts):
1666 1666 return repo.commit(message,
1667 1667 opts.get('user') or old.user(),
1668 1668 opts.get('date') or old.date(),
1669 1669 match,
1670 1670 extra=extra)
1671 1671
1672 1672 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1673 1673 if node == old.node():
1674 1674 ui.status(_("nothing changed\n"))
1675 1675 return 1
1676 1676 else:
1677 1677 def commitfunc(ui, repo, message, match, opts):
1678 1678 backup = ui.backupconfig('phases', 'new-commit')
1679 1679 baseui = repo.baseui
1680 1680 basebackup = baseui.backupconfig('phases', 'new-commit')
1681 1681 try:
1682 1682 if opts.get('secret'):
1683 1683 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1684 1684 # Propagate to subrepos
1685 1685 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1686 1686
1687 1687 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1688 1688 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1689 1689 return repo.commit(message, opts.get('user'), opts.get('date'),
1690 1690 match,
1691 1691 editor=editor,
1692 1692 extra=extra)
1693 1693 finally:
1694 1694 ui.restoreconfig(backup)
1695 1695 repo.baseui.restoreconfig(basebackup)
1696 1696
1697 1697
1698 1698 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1699 1699
1700 1700 if not node:
1701 1701 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1702 1702 if stat[3]:
1703 1703 ui.status(_("nothing changed (%d missing files, see "
1704 1704 "'hg status')\n") % len(stat[3]))
1705 1705 else:
1706 1706 ui.status(_("nothing changed\n"))
1707 1707 return 1
1708 1708
1709 1709 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1710 1710
1711 1711 @command('config|showconfig|debugconfig',
1712 1712 [('u', 'untrusted', None, _('show untrusted configuration options')),
1713 1713 ('e', 'edit', None, _('edit user config')),
1714 1714 ('l', 'local', None, _('edit repository config')),
1715 1715 ('g', 'global', None, _('edit global config'))],
1716 1716 _('[-u] [NAME]...'),
1717 1717 optionalrepo=True)
1718 1718 def config(ui, repo, *values, **opts):
1719 1719 """show combined config settings from all hgrc files
1720 1720
1721 1721 With no arguments, print names and values of all config items.
1722 1722
1723 1723 With one argument of the form section.name, print just the value
1724 1724 of that config item.
1725 1725
1726 1726 With multiple arguments, print names and values of all config
1727 1727 items with matching section names.
1728 1728
1729 1729 With --edit, start an editor on the user-level config file. With
1730 1730 --global, edit the system-wide config file. With --local, edit the
1731 1731 repository-level config file.
1732 1732
1733 1733 With --debug, the source (filename and line number) is printed
1734 1734 for each config item.
1735 1735
1736 1736 See :hg:`help config` for more information about config files.
1737 1737
1738 1738 Returns 0 on success, 1 if NAME does not exist.
1739 1739
1740 1740 """
1741 1741
1742 1742 if opts.get('edit') or opts.get('local') or opts.get('global'):
1743 1743 if opts.get('local') and opts.get('global'):
1744 1744 raise error.Abort(_("can't use --local and --global together"))
1745 1745
1746 1746 if opts.get('local'):
1747 1747 if not repo:
1748 1748 raise error.Abort(_("can't use --local outside a repository"))
1749 1749 paths = [repo.join('hgrc')]
1750 1750 elif opts.get('global'):
1751 1751 paths = scmutil.systemrcpath()
1752 1752 else:
1753 1753 paths = scmutil.userrcpath()
1754 1754
1755 1755 for f in paths:
1756 1756 if os.path.exists(f):
1757 1757 break
1758 1758 else:
1759 1759 if opts.get('global'):
1760 1760 samplehgrc = uimod.samplehgrcs['global']
1761 1761 elif opts.get('local'):
1762 1762 samplehgrc = uimod.samplehgrcs['local']
1763 1763 else:
1764 1764 samplehgrc = uimod.samplehgrcs['user']
1765 1765
1766 1766 f = paths[0]
1767 1767 fp = open(f, "w")
1768 1768 fp.write(samplehgrc)
1769 1769 fp.close()
1770 1770
1771 1771 editor = ui.geteditor()
1772 1772 ui.system("%s \"%s\"" % (editor, f),
1773 1773 onerr=error.Abort, errprefix=_("edit failed"))
1774 1774 return
1775 1775
1776 1776 for f in scmutil.rcpath():
1777 1777 ui.debug('read config from: %s\n' % f)
1778 1778 untrusted = bool(opts.get('untrusted'))
1779 1779 if values:
1780 1780 sections = [v for v in values if '.' not in v]
1781 1781 items = [v for v in values if '.' in v]
1782 1782 if len(items) > 1 or items and sections:
1783 1783 raise error.Abort(_('only one config item permitted'))
1784 1784 matched = False
1785 1785 for section, name, value in ui.walkconfig(untrusted=untrusted):
1786 1786 value = str(value).replace('\n', '\\n')
1787 1787 sectname = section + '.' + name
1788 1788 if values:
1789 1789 for v in values:
1790 1790 if v == section:
1791 1791 ui.debug('%s: ' %
1792 1792 ui.configsource(section, name, untrusted))
1793 1793 ui.write('%s=%s\n' % (sectname, value))
1794 1794 matched = True
1795 1795 elif v == sectname:
1796 1796 ui.debug('%s: ' %
1797 1797 ui.configsource(section, name, untrusted))
1798 1798 ui.write(value, '\n')
1799 1799 matched = True
1800 1800 else:
1801 1801 ui.debug('%s: ' %
1802 1802 ui.configsource(section, name, untrusted))
1803 1803 ui.write('%s=%s\n' % (sectname, value))
1804 1804 matched = True
1805 1805 if matched:
1806 1806 return 0
1807 1807 return 1
1808 1808
1809 1809 @command('copy|cp',
1810 1810 [('A', 'after', None, _('record a copy that has already occurred')),
1811 1811 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1812 1812 ] + walkopts + dryrunopts,
1813 1813 _('[OPTION]... [SOURCE]... DEST'))
1814 1814 def copy(ui, repo, *pats, **opts):
1815 1815 """mark files as copied for the next commit
1816 1816
1817 1817 Mark dest as having copies of source files. If dest is a
1818 1818 directory, copies are put in that directory. If dest is a file,
1819 1819 the source must be a single file.
1820 1820
1821 1821 By default, this command copies the contents of files as they
1822 1822 exist in the working directory. If invoked with -A/--after, the
1823 1823 operation is recorded, but no copying is performed.
1824 1824
1825 1825 This command takes effect with the next commit. To undo a copy
1826 1826 before that, see :hg:`revert`.
1827 1827
1828 1828 Returns 0 on success, 1 if errors are encountered.
1829 1829 """
1830 1830 wlock = repo.wlock(False)
1831 1831 try:
1832 1832 return cmdutil.copy(ui, repo, pats, opts)
1833 1833 finally:
1834 1834 wlock.release()
1835 1835
1836 1836 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1837 1837 def debugancestor(ui, repo, *args):
1838 1838 """find the ancestor revision of two revisions in a given index"""
1839 1839 if len(args) == 3:
1840 1840 index, rev1, rev2 = args
1841 1841 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1842 1842 lookup = r.lookup
1843 1843 elif len(args) == 2:
1844 1844 if not repo:
1845 1845 raise error.Abort(_("there is no Mercurial repository here "
1846 1846 "(.hg not found)"))
1847 1847 rev1, rev2 = args
1848 1848 r = repo.changelog
1849 1849 lookup = repo.lookup
1850 1850 else:
1851 1851 raise error.Abort(_('either two or three arguments required'))
1852 1852 a = r.ancestor(lookup(rev1), lookup(rev2))
1853 1853 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1854 1854
1855 1855 @command('debugbuilddag',
1856 1856 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1857 1857 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1858 1858 ('n', 'new-file', None, _('add new file at each rev'))],
1859 1859 _('[OPTION]... [TEXT]'))
1860 1860 def debugbuilddag(ui, repo, text=None,
1861 1861 mergeable_file=False,
1862 1862 overwritten_file=False,
1863 1863 new_file=False):
1864 1864 """builds a repo with a given DAG from scratch in the current empty repo
1865 1865
1866 1866 The description of the DAG is read from stdin if not given on the
1867 1867 command line.
1868 1868
1869 1869 Elements:
1870 1870
1871 1871 - "+n" is a linear run of n nodes based on the current default parent
1872 1872 - "." is a single node based on the current default parent
1873 1873 - "$" resets the default parent to null (implied at the start);
1874 1874 otherwise the default parent is always the last node created
1875 1875 - "<p" sets the default parent to the backref p
1876 1876 - "*p" is a fork at parent p, which is a backref
1877 1877 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1878 1878 - "/p2" is a merge of the preceding node and p2
1879 1879 - ":tag" defines a local tag for the preceding node
1880 1880 - "@branch" sets the named branch for subsequent nodes
1881 1881 - "#...\\n" is a comment up to the end of the line
1882 1882
1883 1883 Whitespace between the above elements is ignored.
1884 1884
1885 1885 A backref is either
1886 1886
1887 1887 - a number n, which references the node curr-n, where curr is the current
1888 1888 node, or
1889 1889 - the name of a local tag you placed earlier using ":tag", or
1890 1890 - empty to denote the default parent.
1891 1891
1892 1892 All string valued-elements are either strictly alphanumeric, or must
1893 1893 be enclosed in double quotes ("..."), with "\\" as escape character.
1894 1894 """
1895 1895
1896 1896 if text is None:
1897 1897 ui.status(_("reading DAG from stdin\n"))
1898 1898 text = ui.fin.read()
1899 1899
1900 1900 cl = repo.changelog
1901 1901 if len(cl) > 0:
1902 1902 raise error.Abort(_('repository is not empty'))
1903 1903
1904 1904 # determine number of revs in DAG
1905 1905 total = 0
1906 1906 for type, data in dagparser.parsedag(text):
1907 1907 if type == 'n':
1908 1908 total += 1
1909 1909
1910 1910 if mergeable_file:
1911 1911 linesperrev = 2
1912 1912 # make a file with k lines per rev
1913 1913 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1914 1914 initialmergedlines.append("")
1915 1915
1916 1916 tags = []
1917 1917
1918 1918 lock = tr = None
1919 1919 try:
1920 1920 lock = repo.lock()
1921 1921 tr = repo.transaction("builddag")
1922 1922
1923 1923 at = -1
1924 1924 atbranch = 'default'
1925 1925 nodeids = []
1926 1926 id = 0
1927 1927 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1928 1928 for type, data in dagparser.parsedag(text):
1929 1929 if type == 'n':
1930 1930 ui.note(('node %s\n' % str(data)))
1931 1931 id, ps = data
1932 1932
1933 1933 files = []
1934 1934 fctxs = {}
1935 1935
1936 1936 p2 = None
1937 1937 if mergeable_file:
1938 1938 fn = "mf"
1939 1939 p1 = repo[ps[0]]
1940 1940 if len(ps) > 1:
1941 1941 p2 = repo[ps[1]]
1942 1942 pa = p1.ancestor(p2)
1943 1943 base, local, other = [x[fn].data() for x in (pa, p1,
1944 1944 p2)]
1945 1945 m3 = simplemerge.Merge3Text(base, local, other)
1946 1946 ml = [l.strip() for l in m3.merge_lines()]
1947 1947 ml.append("")
1948 1948 elif at > 0:
1949 1949 ml = p1[fn].data().split("\n")
1950 1950 else:
1951 1951 ml = initialmergedlines
1952 1952 ml[id * linesperrev] += " r%i" % id
1953 1953 mergedtext = "\n".join(ml)
1954 1954 files.append(fn)
1955 1955 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1956 1956
1957 1957 if overwritten_file:
1958 1958 fn = "of"
1959 1959 files.append(fn)
1960 1960 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1961 1961
1962 1962 if new_file:
1963 1963 fn = "nf%i" % id
1964 1964 files.append(fn)
1965 1965 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1966 1966 if len(ps) > 1:
1967 1967 if not p2:
1968 1968 p2 = repo[ps[1]]
1969 1969 for fn in p2:
1970 1970 if fn.startswith("nf"):
1971 1971 files.append(fn)
1972 1972 fctxs[fn] = p2[fn]
1973 1973
1974 1974 def fctxfn(repo, cx, path):
1975 1975 return fctxs.get(path)
1976 1976
1977 1977 if len(ps) == 0 or ps[0] < 0:
1978 1978 pars = [None, None]
1979 1979 elif len(ps) == 1:
1980 1980 pars = [nodeids[ps[0]], None]
1981 1981 else:
1982 1982 pars = [nodeids[p] for p in ps]
1983 1983 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1984 1984 date=(id, 0),
1985 1985 user="debugbuilddag",
1986 1986 extra={'branch': atbranch})
1987 1987 nodeid = repo.commitctx(cx)
1988 1988 nodeids.append(nodeid)
1989 1989 at = id
1990 1990 elif type == 'l':
1991 1991 id, name = data
1992 1992 ui.note(('tag %s\n' % name))
1993 1993 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1994 1994 elif type == 'a':
1995 1995 ui.note(('branch %s\n' % data))
1996 1996 atbranch = data
1997 1997 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1998 1998 tr.close()
1999 1999
2000 2000 if tags:
2001 2001 repo.vfs.write("localtags", "".join(tags))
2002 2002 finally:
2003 2003 ui.progress(_('building'), None)
2004 2004 release(tr, lock)
2005 2005
2006 2006 @command('debugbundle',
2007 2007 [('a', 'all', None, _('show all details'))],
2008 2008 _('FILE'),
2009 2009 norepo=True)
2010 2010 def debugbundle(ui, bundlepath, all=None, **opts):
2011 2011 """lists the contents of a bundle"""
2012 2012 f = hg.openpath(ui, bundlepath)
2013 2013 try:
2014 2014 gen = exchange.readbundle(ui, f, bundlepath)
2015 2015 if isinstance(gen, bundle2.unbundle20):
2016 2016 return _debugbundle2(ui, gen, all=all, **opts)
2017 2017 if all:
2018 2018 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2019 2019
2020 2020 def showchunks(named):
2021 2021 ui.write("\n%s\n" % named)
2022 2022 chain = None
2023 2023 while True:
2024 2024 chunkdata = gen.deltachunk(chain)
2025 2025 if not chunkdata:
2026 2026 break
2027 2027 node = chunkdata['node']
2028 2028 p1 = chunkdata['p1']
2029 2029 p2 = chunkdata['p2']
2030 2030 cs = chunkdata['cs']
2031 2031 deltabase = chunkdata['deltabase']
2032 2032 delta = chunkdata['delta']
2033 2033 ui.write("%s %s %s %s %s %s\n" %
2034 2034 (hex(node), hex(p1), hex(p2),
2035 2035 hex(cs), hex(deltabase), len(delta)))
2036 2036 chain = node
2037 2037
2038 2038 chunkdata = gen.changelogheader()
2039 2039 showchunks("changelog")
2040 2040 chunkdata = gen.manifestheader()
2041 2041 showchunks("manifest")
2042 2042 while True:
2043 2043 chunkdata = gen.filelogheader()
2044 2044 if not chunkdata:
2045 2045 break
2046 2046 fname = chunkdata['filename']
2047 2047 showchunks(fname)
2048 2048 else:
2049 2049 if isinstance(gen, bundle2.unbundle20):
2050 2050 raise error.Abort(_('use debugbundle2 for this file'))
2051 2051 chunkdata = gen.changelogheader()
2052 2052 chain = None
2053 2053 while True:
2054 2054 chunkdata = gen.deltachunk(chain)
2055 2055 if not chunkdata:
2056 2056 break
2057 2057 node = chunkdata['node']
2058 2058 ui.write("%s\n" % hex(node))
2059 2059 chain = node
2060 2060 finally:
2061 2061 f.close()
2062 2062
2063 2063 def _debugbundle2(ui, gen, **opts):
2064 2064 """lists the contents of a bundle2"""
2065 2065 if not isinstance(gen, bundle2.unbundle20):
2066 2066 raise error.Abort(_('not a bundle2 file'))
2067 2067 ui.write(('Stream params: %s\n' % repr(gen.params)))
2068 2068 for part in gen.iterparts():
2069 2069 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2070 2070 if part.type == 'changegroup':
2071 2071 version = part.params.get('version', '01')
2072 2072 cg = changegroup.packermap[version][1](part, 'UN')
2073 2073 chunkdata = cg.changelogheader()
2074 2074 chain = None
2075 2075 while True:
2076 2076 chunkdata = cg.deltachunk(chain)
2077 2077 if not chunkdata:
2078 2078 break
2079 2079 node = chunkdata['node']
2080 2080 ui.write(" %s\n" % hex(node))
2081 2081 chain = node
2082 2082
2083 2083 @command('debugcreatestreamclonebundle', [], 'FILE')
2084 2084 def debugcreatestreamclonebundle(ui, repo, fname):
2085 2085 """create a stream clone bundle file
2086 2086
2087 2087 Stream bundles are special bundles that are essentially archives of
2088 2088 revlog files. They are commonly used for cloning very quickly.
2089 2089 """
2090 2090 requirements, gen = streamclone.generatebundlev1(repo)
2091 2091 changegroup.writechunks(ui, gen, fname)
2092 2092
2093 2093 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2094 2094
2095 2095 @command('debugapplystreamclonebundle', [], 'FILE')
2096 2096 def debugapplystreamclonebundle(ui, repo, fname):
2097 2097 """apply a stream clone bundle file"""
2098 2098 f = hg.openpath(ui, fname)
2099 2099 gen = exchange.readbundle(ui, f, fname)
2100 2100 gen.apply(repo)
2101 2101
2102 2102 @command('debugcheckstate', [], '')
2103 2103 def debugcheckstate(ui, repo):
2104 2104 """validate the correctness of the current dirstate"""
2105 2105 parent1, parent2 = repo.dirstate.parents()
2106 2106 m1 = repo[parent1].manifest()
2107 2107 m2 = repo[parent2].manifest()
2108 2108 errors = 0
2109 2109 for f in repo.dirstate:
2110 2110 state = repo.dirstate[f]
2111 2111 if state in "nr" and f not in m1:
2112 2112 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2113 2113 errors += 1
2114 2114 if state in "a" and f in m1:
2115 2115 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2116 2116 errors += 1
2117 2117 if state in "m" and f not in m1 and f not in m2:
2118 2118 ui.warn(_("%s in state %s, but not in either manifest\n") %
2119 2119 (f, state))
2120 2120 errors += 1
2121 2121 for f in m1:
2122 2122 state = repo.dirstate[f]
2123 2123 if state not in "nrm":
2124 2124 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2125 2125 errors += 1
2126 2126 if errors:
2127 2127 error = _(".hg/dirstate inconsistent with current parent's manifest")
2128 2128 raise error.Abort(error)
2129 2129
2130 2130 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2131 2131 def debugcommands(ui, cmd='', *args):
2132 2132 """list all available commands and options"""
2133 2133 for cmd, vals in sorted(table.iteritems()):
2134 2134 cmd = cmd.split('|')[0].strip('^')
2135 2135 opts = ', '.join([i[1] for i in vals[1]])
2136 2136 ui.write('%s: %s\n' % (cmd, opts))
2137 2137
2138 2138 @command('debugcomplete',
2139 2139 [('o', 'options', None, _('show the command options'))],
2140 2140 _('[-o] CMD'),
2141 2141 norepo=True)
2142 2142 def debugcomplete(ui, cmd='', **opts):
2143 2143 """returns the completion list associated with the given command"""
2144 2144
2145 2145 if opts.get('options'):
2146 2146 options = []
2147 2147 otables = [globalopts]
2148 2148 if cmd:
2149 2149 aliases, entry = cmdutil.findcmd(cmd, table, False)
2150 2150 otables.append(entry[1])
2151 2151 for t in otables:
2152 2152 for o in t:
2153 2153 if "(DEPRECATED)" in o[3]:
2154 2154 continue
2155 2155 if o[0]:
2156 2156 options.append('-%s' % o[0])
2157 2157 options.append('--%s' % o[1])
2158 2158 ui.write("%s\n" % "\n".join(options))
2159 2159 return
2160 2160
2161 2161 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2162 2162 if ui.verbose:
2163 2163 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2164 2164 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2165 2165
2166 2166 @command('debugdag',
2167 2167 [('t', 'tags', None, _('use tags as labels')),
2168 2168 ('b', 'branches', None, _('annotate with branch names')),
2169 2169 ('', 'dots', None, _('use dots for runs')),
2170 2170 ('s', 'spaces', None, _('separate elements by spaces'))],
2171 2171 _('[OPTION]... [FILE [REV]...]'),
2172 2172 optionalrepo=True)
2173 2173 def debugdag(ui, repo, file_=None, *revs, **opts):
2174 2174 """format the changelog or an index DAG as a concise textual description
2175 2175
2176 2176 If you pass a revlog index, the revlog's DAG is emitted. If you list
2177 2177 revision numbers, they get labeled in the output as rN.
2178 2178
2179 2179 Otherwise, the changelog DAG of the current repo is emitted.
2180 2180 """
2181 2181 spaces = opts.get('spaces')
2182 2182 dots = opts.get('dots')
2183 2183 if file_:
2184 2184 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2185 2185 revs = set((int(r) for r in revs))
2186 2186 def events():
2187 2187 for r in rlog:
2188 2188 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2189 2189 if p != -1))
2190 2190 if r in revs:
2191 2191 yield 'l', (r, "r%i" % r)
2192 2192 elif repo:
2193 2193 cl = repo.changelog
2194 2194 tags = opts.get('tags')
2195 2195 branches = opts.get('branches')
2196 2196 if tags:
2197 2197 labels = {}
2198 2198 for l, n in repo.tags().items():
2199 2199 labels.setdefault(cl.rev(n), []).append(l)
2200 2200 def events():
2201 2201 b = "default"
2202 2202 for r in cl:
2203 2203 if branches:
2204 2204 newb = cl.read(cl.node(r))[5]['branch']
2205 2205 if newb != b:
2206 2206 yield 'a', newb
2207 2207 b = newb
2208 2208 yield 'n', (r, list(p for p in cl.parentrevs(r)
2209 2209 if p != -1))
2210 2210 if tags:
2211 2211 ls = labels.get(r)
2212 2212 if ls:
2213 2213 for l in ls:
2214 2214 yield 'l', (r, l)
2215 2215 else:
2216 2216 raise error.Abort(_('need repo for changelog dag'))
2217 2217
2218 2218 for line in dagparser.dagtextlines(events(),
2219 2219 addspaces=spaces,
2220 2220 wraplabels=True,
2221 2221 wrapannotations=True,
2222 2222 wrapnonlinear=dots,
2223 2223 usedots=dots,
2224 2224 maxlinewidth=70):
2225 2225 ui.write(line)
2226 2226 ui.write("\n")
2227 2227
2228 2228 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2229 2229 def debugdata(ui, repo, file_, rev=None, **opts):
2230 2230 """dump the contents of a data file revision"""
2231 2231 if opts.get('changelog') or opts.get('manifest'):
2232 2232 file_, rev = None, file_
2233 2233 elif rev is None:
2234 2234 raise error.CommandError('debugdata', _('invalid arguments'))
2235 2235 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2236 2236 try:
2237 2237 ui.write(r.revision(r.lookup(rev)))
2238 2238 except KeyError:
2239 2239 raise error.Abort(_('invalid revision identifier %s') % rev)
2240 2240
2241 2241 @command('debugdate',
2242 2242 [('e', 'extended', None, _('try extended date formats'))],
2243 2243 _('[-e] DATE [RANGE]'),
2244 2244 norepo=True, optionalrepo=True)
2245 2245 def debugdate(ui, date, range=None, **opts):
2246 2246 """parse and display a date"""
2247 2247 if opts["extended"]:
2248 2248 d = util.parsedate(date, util.extendeddateformats)
2249 2249 else:
2250 2250 d = util.parsedate(date)
2251 2251 ui.write(("internal: %s %s\n") % d)
2252 2252 ui.write(("standard: %s\n") % util.datestr(d))
2253 2253 if range:
2254 2254 m = util.matchdate(range)
2255 2255 ui.write(("match: %s\n") % m(d[0]))
2256 2256
2257 2257 @command('debugdiscovery',
2258 2258 [('', 'old', None, _('use old-style discovery')),
2259 2259 ('', 'nonheads', None,
2260 2260 _('use old-style discovery with non-heads included')),
2261 2261 ] + remoteopts,
2262 2262 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2263 2263 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2264 2264 """runs the changeset discovery protocol in isolation"""
2265 2265 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2266 2266 opts.get('branch'))
2267 2267 remote = hg.peer(repo, opts, remoteurl)
2268 2268 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2269 2269
2270 2270 # make sure tests are repeatable
2271 2271 random.seed(12323)
2272 2272
2273 2273 def doit(localheads, remoteheads, remote=remote):
2274 2274 if opts.get('old'):
2275 2275 if localheads:
2276 2276 raise error.Abort('cannot use localheads with old style '
2277 2277 'discovery')
2278 2278 if not util.safehasattr(remote, 'branches'):
2279 2279 # enable in-client legacy support
2280 2280 remote = localrepo.locallegacypeer(remote.local())
2281 2281 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2282 2282 force=True)
2283 2283 common = set(common)
2284 2284 if not opts.get('nonheads'):
2285 2285 ui.write(("unpruned common: %s\n") %
2286 2286 " ".join(sorted(short(n) for n in common)))
2287 2287 dag = dagutil.revlogdag(repo.changelog)
2288 2288 all = dag.ancestorset(dag.internalizeall(common))
2289 2289 common = dag.externalizeall(dag.headsetofconnecteds(all))
2290 2290 else:
2291 2291 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2292 2292 common = set(common)
2293 2293 rheads = set(hds)
2294 2294 lheads = set(repo.heads())
2295 2295 ui.write(("common heads: %s\n") %
2296 2296 " ".join(sorted(short(n) for n in common)))
2297 2297 if lheads <= common:
2298 2298 ui.write(("local is subset\n"))
2299 2299 elif rheads <= common:
2300 2300 ui.write(("remote is subset\n"))
2301 2301
2302 2302 serverlogs = opts.get('serverlog')
2303 2303 if serverlogs:
2304 2304 for filename in serverlogs:
2305 2305 logfile = open(filename, 'r')
2306 2306 try:
2307 2307 line = logfile.readline()
2308 2308 while line:
2309 2309 parts = line.strip().split(';')
2310 2310 op = parts[1]
2311 2311 if op == 'cg':
2312 2312 pass
2313 2313 elif op == 'cgss':
2314 2314 doit(parts[2].split(' '), parts[3].split(' '))
2315 2315 elif op == 'unb':
2316 2316 doit(parts[3].split(' '), parts[2].split(' '))
2317 2317 line = logfile.readline()
2318 2318 finally:
2319 2319 logfile.close()
2320 2320
2321 2321 else:
2322 2322 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2323 2323 opts.get('remote_head'))
2324 2324 localrevs = opts.get('local_head')
2325 2325 doit(localrevs, remoterevs)
2326 2326
2327 2327 @command('debugextensions', formatteropts, [], norepo=True)
2328 2328 def debugextensions(ui, **opts):
2329 2329 '''show information about active extensions'''
2330 2330 exts = extensions.extensions(ui)
2331 2331 fm = ui.formatter('debugextensions', opts)
2332 2332 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2333 2333 extsource = extmod.__file__
2334 2334 exttestedwith = getattr(extmod, 'testedwith', None)
2335 2335 if exttestedwith is not None:
2336 2336 exttestedwith = exttestedwith.split()
2337 2337 extbuglink = getattr(extmod, 'buglink', None)
2338 2338
2339 2339 fm.startitem()
2340 2340
2341 2341 if ui.quiet or ui.verbose:
2342 2342 fm.write('name', '%s\n', extname)
2343 2343 else:
2344 2344 fm.write('name', '%s', extname)
2345 2345 if not exttestedwith:
2346 2346 fm.plain(_(' (untested!)\n'))
2347 2347 else:
2348 2348 if exttestedwith == ['internal'] or \
2349 2349 util.version() in exttestedwith:
2350 2350 fm.plain('\n')
2351 2351 else:
2352 2352 lasttestedversion = exttestedwith[-1]
2353 2353 fm.plain(' (%s!)\n' % lasttestedversion)
2354 2354
2355 2355 fm.condwrite(ui.verbose and extsource, 'source',
2356 2356 _(' location: %s\n'), extsource or "")
2357 2357
2358 2358 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2359 2359 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2360 2360
2361 2361 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2362 2362 _(' bug reporting: %s\n'), extbuglink or "")
2363 2363
2364 2364 fm.end()
2365 2365
2366 2366 @command('debugfileset',
2367 2367 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2368 2368 _('[-r REV] FILESPEC'))
2369 2369 def debugfileset(ui, repo, expr, **opts):
2370 2370 '''parse and apply a fileset specification'''
2371 2371 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2372 2372 if ui.verbose:
2373 2373 tree = fileset.parse(expr)
2374 2374 ui.note(fileset.prettyformat(tree), "\n")
2375 2375
2376 2376 for f in ctx.getfileset(expr):
2377 2377 ui.write("%s\n" % f)
2378 2378
2379 2379 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2380 2380 def debugfsinfo(ui, path="."):
2381 2381 """show information detected about current filesystem"""
2382 2382 util.writefile('.debugfsinfo', '')
2383 2383 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2384 2384 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2385 2385 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2386 2386 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2387 2387 and 'yes' or 'no'))
2388 2388 os.unlink('.debugfsinfo')
2389 2389
2390 2390 @command('debuggetbundle',
2391 2391 [('H', 'head', [], _('id of head node'), _('ID')),
2392 2392 ('C', 'common', [], _('id of common node'), _('ID')),
2393 2393 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2394 2394 _('REPO FILE [-H|-C ID]...'),
2395 2395 norepo=True)
2396 2396 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2397 2397 """retrieves a bundle from a repo
2398 2398
2399 2399 Every ID must be a full-length hex node id string. Saves the bundle to the
2400 2400 given file.
2401 2401 """
2402 2402 repo = hg.peer(ui, opts, repopath)
2403 2403 if not repo.capable('getbundle'):
2404 2404 raise error.Abort("getbundle() not supported by target repository")
2405 2405 args = {}
2406 2406 if common:
2407 2407 args['common'] = [bin(s) for s in common]
2408 2408 if head:
2409 2409 args['heads'] = [bin(s) for s in head]
2410 2410 # TODO: get desired bundlecaps from command line.
2411 2411 args['bundlecaps'] = None
2412 2412 bundle = repo.getbundle('debug', **args)
2413 2413
2414 2414 bundletype = opts.get('type', 'bzip2').lower()
2415 2415 btypes = {'none': 'HG10UN',
2416 2416 'bzip2': 'HG10BZ',
2417 2417 'gzip': 'HG10GZ',
2418 2418 'bundle2': 'HG20'}
2419 2419 bundletype = btypes.get(bundletype)
2420 2420 if bundletype not in changegroup.bundletypes:
2421 2421 raise error.Abort(_('unknown bundle type specified with --type'))
2422 2422 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2423 2423
2424 2424 @command('debugignore', [], '')
2425 2425 def debugignore(ui, repo, *values, **opts):
2426 2426 """display the combined ignore pattern"""
2427 2427 ignore = repo.dirstate._ignore
2428 2428 includepat = getattr(ignore, 'includepat', None)
2429 2429 if includepat is not None:
2430 2430 ui.write("%s\n" % includepat)
2431 2431 else:
2432 2432 raise error.Abort(_("no ignore patterns found"))
2433 2433
2434 2434 @command('debugindex', debugrevlogopts +
2435 2435 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2436 2436 _('[-f FORMAT] -c|-m|FILE'),
2437 2437 optionalrepo=True)
2438 2438 def debugindex(ui, repo, file_=None, **opts):
2439 2439 """dump the contents of an index file"""
2440 2440 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2441 2441 format = opts.get('format', 0)
2442 2442 if format not in (0, 1):
2443 2443 raise error.Abort(_("unknown format %d") % format)
2444 2444
2445 2445 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2446 2446 if generaldelta:
2447 2447 basehdr = ' delta'
2448 2448 else:
2449 2449 basehdr = ' base'
2450 2450
2451 2451 if ui.debugflag:
2452 2452 shortfn = hex
2453 2453 else:
2454 2454 shortfn = short
2455 2455
2456 2456 # There might not be anything in r, so have a sane default
2457 2457 idlen = 12
2458 2458 for i in r:
2459 2459 idlen = len(shortfn(r.node(i)))
2460 2460 break
2461 2461
2462 2462 if format == 0:
2463 2463 ui.write(" rev offset length " + basehdr + " linkrev"
2464 2464 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2465 2465 elif format == 1:
2466 2466 ui.write(" rev flag offset length"
2467 2467 " size " + basehdr + " link p1 p2"
2468 2468 " %s\n" % "nodeid".rjust(idlen))
2469 2469
2470 2470 for i in r:
2471 2471 node = r.node(i)
2472 2472 if generaldelta:
2473 2473 base = r.deltaparent(i)
2474 2474 else:
2475 2475 base = r.chainbase(i)
2476 2476 if format == 0:
2477 2477 try:
2478 2478 pp = r.parents(node)
2479 2479 except Exception:
2480 2480 pp = [nullid, nullid]
2481 2481 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2482 2482 i, r.start(i), r.length(i), base, r.linkrev(i),
2483 2483 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2484 2484 elif format == 1:
2485 2485 pr = r.parentrevs(i)
2486 2486 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2487 2487 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2488 2488 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2489 2489
2490 2490 @command('debugindexdot', debugrevlogopts,
2491 2491 _('-c|-m|FILE'), optionalrepo=True)
2492 2492 def debugindexdot(ui, repo, file_=None, **opts):
2493 2493 """dump an index DAG as a graphviz dot file"""
2494 2494 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2495 2495 ui.write(("digraph G {\n"))
2496 2496 for i in r:
2497 2497 node = r.node(i)
2498 2498 pp = r.parents(node)
2499 2499 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2500 2500 if pp[1] != nullid:
2501 2501 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2502 2502 ui.write("}\n")
2503 2503
2504 @command('debugdeltachain',
2505 debugrevlogopts + formatteropts,
2506 _('-c|-m|FILE'),
2507 optionalrepo=True)
2508 def debugdeltachain(ui, repo, file_=None, **opts):
2509 """dump information about delta chains in a revlog
2510
2511 Output can be templatized. Available template keywords are:
2512
2513 rev revision number
2514 chainid delta chain identifier (numbered by unique base)
2515 chainlen delta chain length to this revision
2516 prevrev previous revision in delta chain
2517 deltatype role of delta / how it was computed
2518 compsize compressed size of revision
2519 uncompsize uncompressed size of revision
2520 chainsize total size of compressed revisions in chain
2521 chainratio total chain size divided by uncompressed revision size
2522 (new delta chains typically start at ratio 2.00)
2523 lindist linear distance from base revision in delta chain to end
2524 of this revision
2525 extradist total size of revisions not part of this delta chain from
2526 base of delta chain to end of this revision; a measurement
2527 of how much extra data we need to read/seek across to read
2528 the delta chain for this revision
2529 extraratio extradist divided by chainsize; another representation of
2530 how much unrelated data is needed to load this delta chain
2531 """
2532 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2533 index = r.index
2534 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2535
2536 def revinfo(rev):
2537 iterrev = rev
2538 e = index[iterrev]
2539 chain = []
2540 compsize = e[1]
2541 uncompsize = e[2]
2542 chainsize = 0
2543
2544 if generaldelta:
2545 if e[3] == e[5]:
2546 deltatype = 'p1'
2547 elif e[3] == e[6]:
2548 deltatype = 'p2'
2549 elif e[3] == rev - 1:
2550 deltatype = 'prev'
2551 elif e[3] == rev:
2552 deltatype = 'base'
2553 else:
2554 deltatype = 'other'
2555 else:
2556 if e[3] == rev:
2557 deltatype = 'base'
2558 else:
2559 deltatype = 'prev'
2560
2561 while iterrev != e[3]:
2562 chain.append(iterrev)
2563 chainsize += e[1]
2564 if generaldelta:
2565 iterrev = e[3]
2566 else:
2567 iterrev -= 1
2568 e = index[iterrev]
2569 else:
2570 chainsize += e[1]
2571 chain.append(iterrev)
2572
2573 chain.reverse()
2574 return compsize, uncompsize, deltatype, chain, chainsize
2575
2576 fm = ui.formatter('debugdeltachain', opts)
2577
2578 fm.plain(' rev chain# chainlen prev delta '
2579 'size rawsize chainsize ratio lindist extradist '
2580 'extraratio\n')
2581
2582 chainbases = {}
2583 for rev in r:
2584 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2585 chainbase = chain[0]
2586 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2587 basestart = r.start(chainbase)
2588 revstart = r.start(rev)
2589 lineardist = revstart + comp - basestart
2590 extradist = lineardist - chainsize
2591 try:
2592 prevrev = chain[-2]
2593 except IndexError:
2594 prevrev = -1
2595
2596 chainratio = float(chainsize) / float(uncomp)
2597 extraratio = float(extradist) / float(chainsize)
2598
2599 fm.startitem()
2600 fm.write('rev chainid chainlen prevrev deltatype compsize '
2601 'uncompsize chainsize chainratio lindist extradist '
2602 'extraratio',
2603 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2604 rev, chainid, len(chain), prevrev, deltatype, comp,
2605 uncomp, chainsize, chainratio, lineardist, extradist,
2606 extraratio,
2607 rev=rev, chainid=chainid, chainlen=len(chain),
2608 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2609 uncompsize=uncomp, chainsize=chainsize,
2610 chainratio=chainratio, lindist=lineardist,
2611 extradist=extradist, extraratio=extraratio)
2612
2613 fm.end()
2614
2504 2615 @command('debuginstall', [], '', norepo=True)
2505 2616 def debuginstall(ui):
2506 2617 '''test Mercurial installation
2507 2618
2508 2619 Returns 0 on success.
2509 2620 '''
2510 2621
2511 2622 def writetemp(contents):
2512 2623 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2513 2624 f = os.fdopen(fd, "wb")
2514 2625 f.write(contents)
2515 2626 f.close()
2516 2627 return name
2517 2628
2518 2629 problems = 0
2519 2630
2520 2631 # encoding
2521 2632 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2522 2633 try:
2523 2634 encoding.fromlocal("test")
2524 2635 except error.Abort as inst:
2525 2636 ui.write(" %s\n" % inst)
2526 2637 ui.write(_(" (check that your locale is properly set)\n"))
2527 2638 problems += 1
2528 2639
2529 2640 # Python
2530 2641 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2531 2642 ui.status(_("checking Python version (%s)\n")
2532 2643 % ("%s.%s.%s" % sys.version_info[:3]))
2533 2644 ui.status(_("checking Python lib (%s)...\n")
2534 2645 % os.path.dirname(os.__file__))
2535 2646
2536 2647 # compiled modules
2537 2648 ui.status(_("checking installed modules (%s)...\n")
2538 2649 % os.path.dirname(__file__))
2539 2650 try:
2540 2651 import bdiff, mpatch, base85, osutil
2541 2652 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2542 2653 except Exception as inst:
2543 2654 ui.write(" %s\n" % inst)
2544 2655 ui.write(_(" One or more extensions could not be found"))
2545 2656 ui.write(_(" (check that you compiled the extensions)\n"))
2546 2657 problems += 1
2547 2658
2548 2659 # templates
2549 2660 import templater
2550 2661 p = templater.templatepaths()
2551 2662 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2552 2663 if p:
2553 2664 m = templater.templatepath("map-cmdline.default")
2554 2665 if m:
2555 2666 # template found, check if it is working
2556 2667 try:
2557 2668 templater.templater(m)
2558 2669 except Exception as inst:
2559 2670 ui.write(" %s\n" % inst)
2560 2671 p = None
2561 2672 else:
2562 2673 ui.write(_(" template 'default' not found\n"))
2563 2674 p = None
2564 2675 else:
2565 2676 ui.write(_(" no template directories found\n"))
2566 2677 if not p:
2567 2678 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2568 2679 problems += 1
2569 2680
2570 2681 # editor
2571 2682 ui.status(_("checking commit editor...\n"))
2572 2683 editor = ui.geteditor()
2573 2684 editor = util.expandpath(editor)
2574 2685 cmdpath = util.findexe(shlex.split(editor)[0])
2575 2686 if not cmdpath:
2576 2687 if editor == 'vi':
2577 2688 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2578 2689 ui.write(_(" (specify a commit editor in your configuration"
2579 2690 " file)\n"))
2580 2691 else:
2581 2692 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2582 2693 ui.write(_(" (specify a commit editor in your configuration"
2583 2694 " file)\n"))
2584 2695 problems += 1
2585 2696
2586 2697 # check username
2587 2698 ui.status(_("checking username...\n"))
2588 2699 try:
2589 2700 ui.username()
2590 2701 except error.Abort as e:
2591 2702 ui.write(" %s\n" % e)
2592 2703 ui.write(_(" (specify a username in your configuration file)\n"))
2593 2704 problems += 1
2594 2705
2595 2706 if not problems:
2596 2707 ui.status(_("no problems detected\n"))
2597 2708 else:
2598 2709 ui.write(_("%s problems detected,"
2599 2710 " please check your install!\n") % problems)
2600 2711
2601 2712 return problems
2602 2713
2603 2714 @command('debugknown', [], _('REPO ID...'), norepo=True)
2604 2715 def debugknown(ui, repopath, *ids, **opts):
2605 2716 """test whether node ids are known to a repo
2606 2717
2607 2718 Every ID must be a full-length hex node id string. Returns a list of 0s
2608 2719 and 1s indicating unknown/known.
2609 2720 """
2610 2721 repo = hg.peer(ui, opts, repopath)
2611 2722 if not repo.capable('known'):
2612 2723 raise error.Abort("known() not supported by target repository")
2613 2724 flags = repo.known([bin(s) for s in ids])
2614 2725 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2615 2726
2616 2727 @command('debuglabelcomplete', [], _('LABEL...'))
2617 2728 def debuglabelcomplete(ui, repo, *args):
2618 2729 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2619 2730 debugnamecomplete(ui, repo, *args)
2620 2731
2621 2732 @command('debugmergestate', [], '')
2622 2733 def debugmergestate(ui, repo, *args):
2623 2734 """print merge state
2624 2735
2625 2736 Use --verbose to print out information about whether v1 or v2 merge state
2626 2737 was chosen."""
2627 2738 def _hashornull(h):
2628 2739 if h == nullhex:
2629 2740 return 'null'
2630 2741 else:
2631 2742 return h
2632 2743
2633 2744 def printrecords(version):
2634 2745 ui.write(('* version %s records\n') % version)
2635 2746 if version == 1:
2636 2747 records = v1records
2637 2748 else:
2638 2749 records = v2records
2639 2750
2640 2751 for rtype, record in records:
2641 2752 # pretty print some record types
2642 2753 if rtype == 'L':
2643 2754 ui.write(('local: %s\n') % record)
2644 2755 elif rtype == 'O':
2645 2756 ui.write(('other: %s\n') % record)
2646 2757 elif rtype == 'm':
2647 2758 driver, mdstate = record.split('\0', 1)
2648 2759 ui.write(('merge driver: %s (state "%s")\n')
2649 2760 % (driver, mdstate))
2650 2761 elif rtype in 'FDC':
2651 2762 r = record.split('\0')
2652 2763 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2653 2764 if version == 1:
2654 2765 onode = 'not stored in v1 format'
2655 2766 flags = r[7]
2656 2767 else:
2657 2768 onode, flags = r[7:9]
2658 2769 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2659 2770 % (f, rtype, state, _hashornull(hash)))
2660 2771 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2661 2772 ui.write((' ancestor path: %s (node %s)\n')
2662 2773 % (afile, _hashornull(anode)))
2663 2774 ui.write((' other path: %s (node %s)\n')
2664 2775 % (ofile, _hashornull(onode)))
2665 2776 else:
2666 2777 ui.write(('unrecognized entry: %s\t%s\n')
2667 2778 % (rtype, record.replace('\0', '\t')))
2668 2779
2669 2780 # Avoid mergestate.read() since it may raise an exception for unsupported
2670 2781 # merge state records. We shouldn't be doing this, but this is OK since this
2671 2782 # command is pretty low-level.
2672 2783 ms = mergemod.mergestate(repo)
2673 2784
2674 2785 # sort so that reasonable information is on top
2675 2786 v1records = ms._readrecordsv1()
2676 2787 v2records = ms._readrecordsv2()
2677 2788 order = 'LOm'
2678 2789 def key(r):
2679 2790 idx = order.find(r[0])
2680 2791 if idx == -1:
2681 2792 return (1, r[1])
2682 2793 else:
2683 2794 return (0, idx)
2684 2795 v1records.sort(key=key)
2685 2796 v2records.sort(key=key)
2686 2797
2687 2798 if not v1records and not v2records:
2688 2799 ui.write(('no merge state found\n'))
2689 2800 elif not v2records:
2690 2801 ui.note(('no version 2 merge state\n'))
2691 2802 printrecords(1)
2692 2803 elif ms._v1v2match(v1records, v2records):
2693 2804 ui.note(('v1 and v2 states match: using v2\n'))
2694 2805 printrecords(2)
2695 2806 else:
2696 2807 ui.note(('v1 and v2 states mismatch: using v1\n'))
2697 2808 printrecords(1)
2698 2809 if ui.verbose:
2699 2810 printrecords(2)
2700 2811
2701 2812 @command('debugnamecomplete', [], _('NAME...'))
2702 2813 def debugnamecomplete(ui, repo, *args):
2703 2814 '''complete "names" - tags, open branch names, bookmark names'''
2704 2815
2705 2816 names = set()
2706 2817 # since we previously only listed open branches, we will handle that
2707 2818 # specially (after this for loop)
2708 2819 for name, ns in repo.names.iteritems():
2709 2820 if name != 'branches':
2710 2821 names.update(ns.listnames(repo))
2711 2822 names.update(tag for (tag, heads, tip, closed)
2712 2823 in repo.branchmap().iterbranches() if not closed)
2713 2824 completions = set()
2714 2825 if not args:
2715 2826 args = ['']
2716 2827 for a in args:
2717 2828 completions.update(n for n in names if n.startswith(a))
2718 2829 ui.write('\n'.join(sorted(completions)))
2719 2830 ui.write('\n')
2720 2831
2721 2832 @command('debuglocks',
2722 2833 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2723 2834 ('W', 'force-wlock', None,
2724 2835 _('free the working state lock (DANGEROUS)'))],
2725 2836 _('[OPTION]...'))
2726 2837 def debuglocks(ui, repo, **opts):
2727 2838 """show or modify state of locks
2728 2839
2729 2840 By default, this command will show which locks are held. This
2730 2841 includes the user and process holding the lock, the amount of time
2731 2842 the lock has been held, and the machine name where the process is
2732 2843 running if it's not local.
2733 2844
2734 2845 Locks protect the integrity of Mercurial's data, so should be
2735 2846 treated with care. System crashes or other interruptions may cause
2736 2847 locks to not be properly released, though Mercurial will usually
2737 2848 detect and remove such stale locks automatically.
2738 2849
2739 2850 However, detecting stale locks may not always be possible (for
2740 2851 instance, on a shared filesystem). Removing locks may also be
2741 2852 blocked by filesystem permissions.
2742 2853
2743 2854 Returns 0 if no locks are held.
2744 2855
2745 2856 """
2746 2857
2747 2858 if opts.get('force_lock'):
2748 2859 repo.svfs.unlink('lock')
2749 2860 if opts.get('force_wlock'):
2750 2861 repo.vfs.unlink('wlock')
2751 2862 if opts.get('force_lock') or opts.get('force_lock'):
2752 2863 return 0
2753 2864
2754 2865 now = time.time()
2755 2866 held = 0
2756 2867
2757 2868 def report(vfs, name, method):
2758 2869 # this causes stale locks to get reaped for more accurate reporting
2759 2870 try:
2760 2871 l = method(False)
2761 2872 except error.LockHeld:
2762 2873 l = None
2763 2874
2764 2875 if l:
2765 2876 l.release()
2766 2877 else:
2767 2878 try:
2768 2879 stat = vfs.lstat(name)
2769 2880 age = now - stat.st_mtime
2770 2881 user = util.username(stat.st_uid)
2771 2882 locker = vfs.readlock(name)
2772 2883 if ":" in locker:
2773 2884 host, pid = locker.split(':')
2774 2885 if host == socket.gethostname():
2775 2886 locker = 'user %s, process %s' % (user, pid)
2776 2887 else:
2777 2888 locker = 'user %s, process %s, host %s' \
2778 2889 % (user, pid, host)
2779 2890 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2780 2891 return 1
2781 2892 except OSError as e:
2782 2893 if e.errno != errno.ENOENT:
2783 2894 raise
2784 2895
2785 2896 ui.write("%-6s free\n" % (name + ":"))
2786 2897 return 0
2787 2898
2788 2899 held += report(repo.svfs, "lock", repo.lock)
2789 2900 held += report(repo.vfs, "wlock", repo.wlock)
2790 2901
2791 2902 return held
2792 2903
2793 2904 @command('debugobsolete',
2794 2905 [('', 'flags', 0, _('markers flag')),
2795 2906 ('', 'record-parents', False,
2796 2907 _('record parent information for the precursor')),
2797 2908 ('r', 'rev', [], _('display markers relevant to REV')),
2798 2909 ] + commitopts2,
2799 2910 _('[OBSOLETED [REPLACEMENT ...]]'))
2800 2911 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2801 2912 """create arbitrary obsolete marker
2802 2913
2803 2914 With no arguments, displays the list of obsolescence markers."""
2804 2915
2805 2916 def parsenodeid(s):
2806 2917 try:
2807 2918 # We do not use revsingle/revrange functions here to accept
2808 2919 # arbitrary node identifiers, possibly not present in the
2809 2920 # local repository.
2810 2921 n = bin(s)
2811 2922 if len(n) != len(nullid):
2812 2923 raise TypeError()
2813 2924 return n
2814 2925 except TypeError:
2815 2926 raise error.Abort('changeset references must be full hexadecimal '
2816 2927 'node identifiers')
2817 2928
2818 2929 if precursor is not None:
2819 2930 if opts['rev']:
2820 2931 raise error.Abort('cannot select revision when creating marker')
2821 2932 metadata = {}
2822 2933 metadata['user'] = opts['user'] or ui.username()
2823 2934 succs = tuple(parsenodeid(succ) for succ in successors)
2824 2935 l = repo.lock()
2825 2936 try:
2826 2937 tr = repo.transaction('debugobsolete')
2827 2938 try:
2828 2939 date = opts.get('date')
2829 2940 if date:
2830 2941 date = util.parsedate(date)
2831 2942 else:
2832 2943 date = None
2833 2944 prec = parsenodeid(precursor)
2834 2945 parents = None
2835 2946 if opts['record_parents']:
2836 2947 if prec not in repo.unfiltered():
2837 2948 raise error.Abort('cannot used --record-parents on '
2838 2949 'unknown changesets')
2839 2950 parents = repo.unfiltered()[prec].parents()
2840 2951 parents = tuple(p.node() for p in parents)
2841 2952 repo.obsstore.create(tr, prec, succs, opts['flags'],
2842 2953 parents=parents, date=date,
2843 2954 metadata=metadata)
2844 2955 tr.close()
2845 2956 except ValueError as exc:
2846 2957 raise error.Abort(_('bad obsmarker input: %s') % exc)
2847 2958 finally:
2848 2959 tr.release()
2849 2960 finally:
2850 2961 l.release()
2851 2962 else:
2852 2963 if opts['rev']:
2853 2964 revs = scmutil.revrange(repo, opts['rev'])
2854 2965 nodes = [repo[r].node() for r in revs]
2855 2966 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2856 2967 markers.sort(key=lambda x: x._data)
2857 2968 else:
2858 2969 markers = obsolete.getmarkers(repo)
2859 2970
2860 2971 for m in markers:
2861 2972 cmdutil.showmarker(ui, m)
2862 2973
2863 2974 @command('debugpathcomplete',
2864 2975 [('f', 'full', None, _('complete an entire path')),
2865 2976 ('n', 'normal', None, _('show only normal files')),
2866 2977 ('a', 'added', None, _('show only added files')),
2867 2978 ('r', 'removed', None, _('show only removed files'))],
2868 2979 _('FILESPEC...'))
2869 2980 def debugpathcomplete(ui, repo, *specs, **opts):
2870 2981 '''complete part or all of a tracked path
2871 2982
2872 2983 This command supports shells that offer path name completion. It
2873 2984 currently completes only files already known to the dirstate.
2874 2985
2875 2986 Completion extends only to the next path segment unless
2876 2987 --full is specified, in which case entire paths are used.'''
2877 2988
2878 2989 def complete(path, acceptable):
2879 2990 dirstate = repo.dirstate
2880 2991 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2881 2992 rootdir = repo.root + os.sep
2882 2993 if spec != repo.root and not spec.startswith(rootdir):
2883 2994 return [], []
2884 2995 if os.path.isdir(spec):
2885 2996 spec += '/'
2886 2997 spec = spec[len(rootdir):]
2887 2998 fixpaths = os.sep != '/'
2888 2999 if fixpaths:
2889 3000 spec = spec.replace(os.sep, '/')
2890 3001 speclen = len(spec)
2891 3002 fullpaths = opts['full']
2892 3003 files, dirs = set(), set()
2893 3004 adddir, addfile = dirs.add, files.add
2894 3005 for f, st in dirstate.iteritems():
2895 3006 if f.startswith(spec) and st[0] in acceptable:
2896 3007 if fixpaths:
2897 3008 f = f.replace('/', os.sep)
2898 3009 if fullpaths:
2899 3010 addfile(f)
2900 3011 continue
2901 3012 s = f.find(os.sep, speclen)
2902 3013 if s >= 0:
2903 3014 adddir(f[:s])
2904 3015 else:
2905 3016 addfile(f)
2906 3017 return files, dirs
2907 3018
2908 3019 acceptable = ''
2909 3020 if opts['normal']:
2910 3021 acceptable += 'nm'
2911 3022 if opts['added']:
2912 3023 acceptable += 'a'
2913 3024 if opts['removed']:
2914 3025 acceptable += 'r'
2915 3026 cwd = repo.getcwd()
2916 3027 if not specs:
2917 3028 specs = ['.']
2918 3029
2919 3030 files, dirs = set(), set()
2920 3031 for spec in specs:
2921 3032 f, d = complete(spec, acceptable or 'nmar')
2922 3033 files.update(f)
2923 3034 dirs.update(d)
2924 3035 files.update(dirs)
2925 3036 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2926 3037 ui.write('\n')
2927 3038
2928 3039 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2929 3040 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2930 3041 '''access the pushkey key/value protocol
2931 3042
2932 3043 With two args, list the keys in the given namespace.
2933 3044
2934 3045 With five args, set a key to new if it currently is set to old.
2935 3046 Reports success or failure.
2936 3047 '''
2937 3048
2938 3049 target = hg.peer(ui, {}, repopath)
2939 3050 if keyinfo:
2940 3051 key, old, new = keyinfo
2941 3052 r = target.pushkey(namespace, key, old, new)
2942 3053 ui.status(str(r) + '\n')
2943 3054 return not r
2944 3055 else:
2945 3056 for k, v in sorted(target.listkeys(namespace).iteritems()):
2946 3057 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2947 3058 v.encode('string-escape')))
2948 3059
2949 3060 @command('debugpvec', [], _('A B'))
2950 3061 def debugpvec(ui, repo, a, b=None):
2951 3062 ca = scmutil.revsingle(repo, a)
2952 3063 cb = scmutil.revsingle(repo, b)
2953 3064 pa = pvec.ctxpvec(ca)
2954 3065 pb = pvec.ctxpvec(cb)
2955 3066 if pa == pb:
2956 3067 rel = "="
2957 3068 elif pa > pb:
2958 3069 rel = ">"
2959 3070 elif pa < pb:
2960 3071 rel = "<"
2961 3072 elif pa | pb:
2962 3073 rel = "|"
2963 3074 ui.write(_("a: %s\n") % pa)
2964 3075 ui.write(_("b: %s\n") % pb)
2965 3076 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2966 3077 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2967 3078 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2968 3079 pa.distance(pb), rel))
2969 3080
2970 3081 @command('debugrebuilddirstate|debugrebuildstate',
2971 3082 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2972 3083 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2973 3084 'the working copy parent')),
2974 3085 ],
2975 3086 _('[-r REV]'))
2976 3087 def debugrebuilddirstate(ui, repo, rev, **opts):
2977 3088 """rebuild the dirstate as it would look like for the given revision
2978 3089
2979 3090 If no revision is specified the first current parent will be used.
2980 3091
2981 3092 The dirstate will be set to the files of the given revision.
2982 3093 The actual working directory content or existing dirstate
2983 3094 information such as adds or removes is not considered.
2984 3095
2985 3096 ``minimal`` will only rebuild the dirstate status for files that claim to be
2986 3097 tracked but are not in the parent manifest, or that exist in the parent
2987 3098 manifest but are not in the dirstate. It will not change adds, removes, or
2988 3099 modified files that are in the working copy parent.
2989 3100
2990 3101 One use of this command is to make the next :hg:`status` invocation
2991 3102 check the actual file content.
2992 3103 """
2993 3104 ctx = scmutil.revsingle(repo, rev)
2994 3105 wlock = repo.wlock()
2995 3106 try:
2996 3107 dirstate = repo.dirstate
2997 3108 changedfiles = None
2998 3109 # See command doc for what minimal does.
2999 3110 if opts.get('minimal'):
3000 3111 manifestfiles = set(ctx.manifest().keys())
3001 3112 dirstatefiles = set(dirstate)
3002 3113 manifestonly = manifestfiles - dirstatefiles
3003 3114 dsonly = dirstatefiles - manifestfiles
3004 3115 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3005 3116 changedfiles = manifestonly | dsnotadded
3006 3117
3007 3118 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3008 3119 finally:
3009 3120 wlock.release()
3010 3121
3011 3122 @command('debugrebuildfncache', [], '')
3012 3123 def debugrebuildfncache(ui, repo):
3013 3124 """rebuild the fncache file"""
3014 3125 repair.rebuildfncache(ui, repo)
3015 3126
3016 3127 @command('debugrename',
3017 3128 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3018 3129 _('[-r REV] FILE'))
3019 3130 def debugrename(ui, repo, file1, *pats, **opts):
3020 3131 """dump rename information"""
3021 3132
3022 3133 ctx = scmutil.revsingle(repo, opts.get('rev'))
3023 3134 m = scmutil.match(ctx, (file1,) + pats, opts)
3024 3135 for abs in ctx.walk(m):
3025 3136 fctx = ctx[abs]
3026 3137 o = fctx.filelog().renamed(fctx.filenode())
3027 3138 rel = m.rel(abs)
3028 3139 if o:
3029 3140 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3030 3141 else:
3031 3142 ui.write(_("%s not renamed\n") % rel)
3032 3143
3033 3144 @command('debugrevlog', debugrevlogopts +
3034 3145 [('d', 'dump', False, _('dump index data'))],
3035 3146 _('-c|-m|FILE'),
3036 3147 optionalrepo=True)
3037 3148 def debugrevlog(ui, repo, file_=None, **opts):
3038 3149 """show data and statistics about a revlog"""
3039 3150 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3040 3151
3041 3152 if opts.get("dump"):
3042 3153 numrevs = len(r)
3043 3154 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3044 3155 " rawsize totalsize compression heads chainlen\n")
3045 3156 ts = 0
3046 3157 heads = set()
3047 3158
3048 3159 for rev in xrange(numrevs):
3049 3160 dbase = r.deltaparent(rev)
3050 3161 if dbase == -1:
3051 3162 dbase = rev
3052 3163 cbase = r.chainbase(rev)
3053 3164 clen = r.chainlen(rev)
3054 3165 p1, p2 = r.parentrevs(rev)
3055 3166 rs = r.rawsize(rev)
3056 3167 ts = ts + rs
3057 3168 heads -= set(r.parentrevs(rev))
3058 3169 heads.add(rev)
3059 3170 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3060 3171 "%11d %5d %8d\n" %
3061 3172 (rev, p1, p2, r.start(rev), r.end(rev),
3062 3173 r.start(dbase), r.start(cbase),
3063 3174 r.start(p1), r.start(p2),
3064 3175 rs, ts, ts / r.end(rev), len(heads), clen))
3065 3176 return 0
3066 3177
3067 3178 v = r.version
3068 3179 format = v & 0xFFFF
3069 3180 flags = []
3070 3181 gdelta = False
3071 3182 if v & revlog.REVLOGNGINLINEDATA:
3072 3183 flags.append('inline')
3073 3184 if v & revlog.REVLOGGENERALDELTA:
3074 3185 gdelta = True
3075 3186 flags.append('generaldelta')
3076 3187 if not flags:
3077 3188 flags = ['(none)']
3078 3189
3079 3190 nummerges = 0
3080 3191 numfull = 0
3081 3192 numprev = 0
3082 3193 nump1 = 0
3083 3194 nump2 = 0
3084 3195 numother = 0
3085 3196 nump1prev = 0
3086 3197 nump2prev = 0
3087 3198 chainlengths = []
3088 3199
3089 3200 datasize = [None, 0, 0L]
3090 3201 fullsize = [None, 0, 0L]
3091 3202 deltasize = [None, 0, 0L]
3092 3203
3093 3204 def addsize(size, l):
3094 3205 if l[0] is None or size < l[0]:
3095 3206 l[0] = size
3096 3207 if size > l[1]:
3097 3208 l[1] = size
3098 3209 l[2] += size
3099 3210
3100 3211 numrevs = len(r)
3101 3212 for rev in xrange(numrevs):
3102 3213 p1, p2 = r.parentrevs(rev)
3103 3214 delta = r.deltaparent(rev)
3104 3215 if format > 0:
3105 3216 addsize(r.rawsize(rev), datasize)
3106 3217 if p2 != nullrev:
3107 3218 nummerges += 1
3108 3219 size = r.length(rev)
3109 3220 if delta == nullrev:
3110 3221 chainlengths.append(0)
3111 3222 numfull += 1
3112 3223 addsize(size, fullsize)
3113 3224 else:
3114 3225 chainlengths.append(chainlengths[delta] + 1)
3115 3226 addsize(size, deltasize)
3116 3227 if delta == rev - 1:
3117 3228 numprev += 1
3118 3229 if delta == p1:
3119 3230 nump1prev += 1
3120 3231 elif delta == p2:
3121 3232 nump2prev += 1
3122 3233 elif delta == p1:
3123 3234 nump1 += 1
3124 3235 elif delta == p2:
3125 3236 nump2 += 1
3126 3237 elif delta != nullrev:
3127 3238 numother += 1
3128 3239
3129 3240 # Adjust size min value for empty cases
3130 3241 for size in (datasize, fullsize, deltasize):
3131 3242 if size[0] is None:
3132 3243 size[0] = 0
3133 3244
3134 3245 numdeltas = numrevs - numfull
3135 3246 numoprev = numprev - nump1prev - nump2prev
3136 3247 totalrawsize = datasize[2]
3137 3248 datasize[2] /= numrevs
3138 3249 fulltotal = fullsize[2]
3139 3250 fullsize[2] /= numfull
3140 3251 deltatotal = deltasize[2]
3141 3252 if numrevs - numfull > 0:
3142 3253 deltasize[2] /= numrevs - numfull
3143 3254 totalsize = fulltotal + deltatotal
3144 3255 avgchainlen = sum(chainlengths) / numrevs
3145 3256 maxchainlen = max(chainlengths)
3146 3257 compratio = 1
3147 3258 if totalsize:
3148 3259 compratio = totalrawsize / totalsize
3149 3260
3150 3261 basedfmtstr = '%%%dd\n'
3151 3262 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3152 3263
3153 3264 def dfmtstr(max):
3154 3265 return basedfmtstr % len(str(max))
3155 3266 def pcfmtstr(max, padding=0):
3156 3267 return basepcfmtstr % (len(str(max)), ' ' * padding)
3157 3268
3158 3269 def pcfmt(value, total):
3159 3270 if total:
3160 3271 return (value, 100 * float(value) / total)
3161 3272 else:
3162 3273 return value, 100.0
3163 3274
3164 3275 ui.write(('format : %d\n') % format)
3165 3276 ui.write(('flags : %s\n') % ', '.join(flags))
3166 3277
3167 3278 ui.write('\n')
3168 3279 fmt = pcfmtstr(totalsize)
3169 3280 fmt2 = dfmtstr(totalsize)
3170 3281 ui.write(('revisions : ') + fmt2 % numrevs)
3171 3282 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3172 3283 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3173 3284 ui.write(('revisions : ') + fmt2 % numrevs)
3174 3285 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3175 3286 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3176 3287 ui.write(('revision size : ') + fmt2 % totalsize)
3177 3288 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3178 3289 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3179 3290
3180 3291 ui.write('\n')
3181 3292 fmt = dfmtstr(max(avgchainlen, compratio))
3182 3293 ui.write(('avg chain length : ') + fmt % avgchainlen)
3183 3294 ui.write(('max chain length : ') + fmt % maxchainlen)
3184 3295 ui.write(('compression ratio : ') + fmt % compratio)
3185 3296
3186 3297 if format > 0:
3187 3298 ui.write('\n')
3188 3299 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3189 3300 % tuple(datasize))
3190 3301 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3191 3302 % tuple(fullsize))
3192 3303 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3193 3304 % tuple(deltasize))
3194 3305
3195 3306 if numdeltas > 0:
3196 3307 ui.write('\n')
3197 3308 fmt = pcfmtstr(numdeltas)
3198 3309 fmt2 = pcfmtstr(numdeltas, 4)
3199 3310 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3200 3311 if numprev > 0:
3201 3312 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3202 3313 numprev))
3203 3314 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3204 3315 numprev))
3205 3316 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3206 3317 numprev))
3207 3318 if gdelta:
3208 3319 ui.write(('deltas against p1 : ')
3209 3320 + fmt % pcfmt(nump1, numdeltas))
3210 3321 ui.write(('deltas against p2 : ')
3211 3322 + fmt % pcfmt(nump2, numdeltas))
3212 3323 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3213 3324 numdeltas))
3214 3325
3215 3326 @command('debugrevspec',
3216 3327 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3217 3328 ('REVSPEC'))
3218 3329 def debugrevspec(ui, repo, expr, **opts):
3219 3330 """parse and apply a revision specification
3220 3331
3221 3332 Use --verbose to print the parsed tree before and after aliases
3222 3333 expansion.
3223 3334 """
3224 3335 if ui.verbose:
3225 3336 tree = revset.parse(expr, lookup=repo.__contains__)
3226 3337 ui.note(revset.prettyformat(tree), "\n")
3227 3338 newtree = revset.findaliases(ui, tree)
3228 3339 if newtree != tree:
3229 3340 ui.note(revset.prettyformat(newtree), "\n")
3230 3341 tree = newtree
3231 3342 newtree = revset.foldconcat(tree)
3232 3343 if newtree != tree:
3233 3344 ui.note(revset.prettyformat(newtree), "\n")
3234 3345 if opts["optimize"]:
3235 3346 weight, optimizedtree = revset.optimize(newtree, True)
3236 3347 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3237 3348 func = revset.match(ui, expr, repo)
3238 3349 revs = func(repo)
3239 3350 if ui.verbose:
3240 3351 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3241 3352 for c in revs:
3242 3353 ui.write("%s\n" % c)
3243 3354
3244 3355 @command('debugsetparents', [], _('REV1 [REV2]'))
3245 3356 def debugsetparents(ui, repo, rev1, rev2=None):
3246 3357 """manually set the parents of the current working directory
3247 3358
3248 3359 This is useful for writing repository conversion tools, but should
3249 3360 be used with care. For example, neither the working directory nor the
3250 3361 dirstate is updated, so file status may be incorrect after running this
3251 3362 command.
3252 3363
3253 3364 Returns 0 on success.
3254 3365 """
3255 3366
3256 3367 r1 = scmutil.revsingle(repo, rev1).node()
3257 3368 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3258 3369
3259 3370 wlock = repo.wlock()
3260 3371 try:
3261 3372 repo.dirstate.beginparentchange()
3262 3373 repo.setparents(r1, r2)
3263 3374 repo.dirstate.endparentchange()
3264 3375 finally:
3265 3376 wlock.release()
3266 3377
3267 3378 @command('debugdirstate|debugstate',
3268 3379 [('', 'nodates', None, _('do not display the saved mtime')),
3269 3380 ('', 'datesort', None, _('sort by saved mtime'))],
3270 3381 _('[OPTION]...'))
3271 3382 def debugstate(ui, repo, **opts):
3272 3383 """show the contents of the current dirstate"""
3273 3384
3274 3385 nodates = opts.get('nodates')
3275 3386 datesort = opts.get('datesort')
3276 3387
3277 3388 timestr = ""
3278 3389 if datesort:
3279 3390 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3280 3391 else:
3281 3392 keyfunc = None # sort by filename
3282 3393 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3283 3394 if ent[3] == -1:
3284 3395 timestr = 'unset '
3285 3396 elif nodates:
3286 3397 timestr = 'set '
3287 3398 else:
3288 3399 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3289 3400 time.localtime(ent[3]))
3290 3401 if ent[1] & 0o20000:
3291 3402 mode = 'lnk'
3292 3403 else:
3293 3404 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3294 3405 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3295 3406 for f in repo.dirstate.copies():
3296 3407 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3297 3408
3298 3409 @command('debugsub',
3299 3410 [('r', 'rev', '',
3300 3411 _('revision to check'), _('REV'))],
3301 3412 _('[-r REV] [REV]'))
3302 3413 def debugsub(ui, repo, rev=None):
3303 3414 ctx = scmutil.revsingle(repo, rev, None)
3304 3415 for k, v in sorted(ctx.substate.items()):
3305 3416 ui.write(('path %s\n') % k)
3306 3417 ui.write((' source %s\n') % v[0])
3307 3418 ui.write((' revision %s\n') % v[1])
3308 3419
3309 3420 @command('debugsuccessorssets',
3310 3421 [],
3311 3422 _('[REV]'))
3312 3423 def debugsuccessorssets(ui, repo, *revs):
3313 3424 """show set of successors for revision
3314 3425
3315 3426 A successors set of changeset A is a consistent group of revisions that
3316 3427 succeed A. It contains non-obsolete changesets only.
3317 3428
3318 3429 In most cases a changeset A has a single successors set containing a single
3319 3430 successor (changeset A replaced by A').
3320 3431
3321 3432 A changeset that is made obsolete with no successors are called "pruned".
3322 3433 Such changesets have no successors sets at all.
3323 3434
3324 3435 A changeset that has been "split" will have a successors set containing
3325 3436 more than one successor.
3326 3437
3327 3438 A changeset that has been rewritten in multiple different ways is called
3328 3439 "divergent". Such changesets have multiple successor sets (each of which
3329 3440 may also be split, i.e. have multiple successors).
3330 3441
3331 3442 Results are displayed as follows::
3332 3443
3333 3444 <rev1>
3334 3445 <successors-1A>
3335 3446 <rev2>
3336 3447 <successors-2A>
3337 3448 <successors-2B1> <successors-2B2> <successors-2B3>
3338 3449
3339 3450 Here rev2 has two possible (i.e. divergent) successors sets. The first
3340 3451 holds one element, whereas the second holds three (i.e. the changeset has
3341 3452 been split).
3342 3453 """
3343 3454 # passed to successorssets caching computation from one call to another
3344 3455 cache = {}
3345 3456 ctx2str = str
3346 3457 node2str = short
3347 3458 if ui.debug():
3348 3459 def ctx2str(ctx):
3349 3460 return ctx.hex()
3350 3461 node2str = hex
3351 3462 for rev in scmutil.revrange(repo, revs):
3352 3463 ctx = repo[rev]
3353 3464 ui.write('%s\n'% ctx2str(ctx))
3354 3465 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3355 3466 if succsset:
3356 3467 ui.write(' ')
3357 3468 ui.write(node2str(succsset[0]))
3358 3469 for node in succsset[1:]:
3359 3470 ui.write(' ')
3360 3471 ui.write(node2str(node))
3361 3472 ui.write('\n')
3362 3473
3363 3474 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3364 3475 def debugwalk(ui, repo, *pats, **opts):
3365 3476 """show how files match on given patterns"""
3366 3477 m = scmutil.match(repo[None], pats, opts)
3367 3478 items = list(repo.walk(m))
3368 3479 if not items:
3369 3480 return
3370 3481 f = lambda fn: fn
3371 3482 if ui.configbool('ui', 'slash') and os.sep != '/':
3372 3483 f = lambda fn: util.normpath(fn)
3373 3484 fmt = 'f %%-%ds %%-%ds %%s' % (
3374 3485 max([len(abs) for abs in items]),
3375 3486 max([len(m.rel(abs)) for abs in items]))
3376 3487 for abs in items:
3377 3488 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3378 3489 ui.write("%s\n" % line.rstrip())
3379 3490
3380 3491 @command('debugwireargs',
3381 3492 [('', 'three', '', 'three'),
3382 3493 ('', 'four', '', 'four'),
3383 3494 ('', 'five', '', 'five'),
3384 3495 ] + remoteopts,
3385 3496 _('REPO [OPTIONS]... [ONE [TWO]]'),
3386 3497 norepo=True)
3387 3498 def debugwireargs(ui, repopath, *vals, **opts):
3388 3499 repo = hg.peer(ui, opts, repopath)
3389 3500 for opt in remoteopts:
3390 3501 del opts[opt[1]]
3391 3502 args = {}
3392 3503 for k, v in opts.iteritems():
3393 3504 if v:
3394 3505 args[k] = v
3395 3506 # run twice to check that we don't mess up the stream for the next command
3396 3507 res1 = repo.debugwireargs(*vals, **args)
3397 3508 res2 = repo.debugwireargs(*vals, **args)
3398 3509 ui.write("%s\n" % res1)
3399 3510 if res1 != res2:
3400 3511 ui.warn("%s\n" % res2)
3401 3512
3402 3513 @command('^diff',
3403 3514 [('r', 'rev', [], _('revision'), _('REV')),
3404 3515 ('c', 'change', '', _('change made by revision'), _('REV'))
3405 3516 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3406 3517 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3407 3518 inferrepo=True)
3408 3519 def diff(ui, repo, *pats, **opts):
3409 3520 """diff repository (or selected files)
3410 3521
3411 3522 Show differences between revisions for the specified files.
3412 3523
3413 3524 Differences between files are shown using the unified diff format.
3414 3525
3415 3526 .. note::
3416 3527
3417 3528 diff may generate unexpected results for merges, as it will
3418 3529 default to comparing against the working directory's first
3419 3530 parent changeset if no revisions are specified.
3420 3531
3421 3532 When two revision arguments are given, then changes are shown
3422 3533 between those revisions. If only one revision is specified then
3423 3534 that revision is compared to the working directory, and, when no
3424 3535 revisions are specified, the working directory files are compared
3425 3536 to its parent.
3426 3537
3427 3538 Alternatively you can specify -c/--change with a revision to see
3428 3539 the changes in that changeset relative to its first parent.
3429 3540
3430 3541 Without the -a/--text option, diff will avoid generating diffs of
3431 3542 files it detects as binary. With -a, diff will generate a diff
3432 3543 anyway, probably with undesirable results.
3433 3544
3434 3545 Use the -g/--git option to generate diffs in the git extended diff
3435 3546 format. For more information, read :hg:`help diffs`.
3436 3547
3437 3548 .. container:: verbose
3438 3549
3439 3550 Examples:
3440 3551
3441 3552 - compare a file in the current working directory to its parent::
3442 3553
3443 3554 hg diff foo.c
3444 3555
3445 3556 - compare two historical versions of a directory, with rename info::
3446 3557
3447 3558 hg diff --git -r 1.0:1.2 lib/
3448 3559
3449 3560 - get change stats relative to the last change on some date::
3450 3561
3451 3562 hg diff --stat -r "date('may 2')"
3452 3563
3453 3564 - diff all newly-added files that contain a keyword::
3454 3565
3455 3566 hg diff "set:added() and grep(GNU)"
3456 3567
3457 3568 - compare a revision and its parents::
3458 3569
3459 3570 hg diff -c 9353 # compare against first parent
3460 3571 hg diff -r 9353^:9353 # same using revset syntax
3461 3572 hg diff -r 9353^2:9353 # compare against the second parent
3462 3573
3463 3574 Returns 0 on success.
3464 3575 """
3465 3576
3466 3577 revs = opts.get('rev')
3467 3578 change = opts.get('change')
3468 3579 stat = opts.get('stat')
3469 3580 reverse = opts.get('reverse')
3470 3581
3471 3582 if revs and change:
3472 3583 msg = _('cannot specify --rev and --change at the same time')
3473 3584 raise error.Abort(msg)
3474 3585 elif change:
3475 3586 node2 = scmutil.revsingle(repo, change, None).node()
3476 3587 node1 = repo[node2].p1().node()
3477 3588 else:
3478 3589 node1, node2 = scmutil.revpair(repo, revs)
3479 3590
3480 3591 if reverse:
3481 3592 node1, node2 = node2, node1
3482 3593
3483 3594 diffopts = patch.diffallopts(ui, opts)
3484 3595 m = scmutil.match(repo[node2], pats, opts)
3485 3596 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3486 3597 listsubrepos=opts.get('subrepos'),
3487 3598 root=opts.get('root'))
3488 3599
3489 3600 @command('^export',
3490 3601 [('o', 'output', '',
3491 3602 _('print output to file with formatted name'), _('FORMAT')),
3492 3603 ('', 'switch-parent', None, _('diff against the second parent')),
3493 3604 ('r', 'rev', [], _('revisions to export'), _('REV')),
3494 3605 ] + diffopts,
3495 3606 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3496 3607 def export(ui, repo, *changesets, **opts):
3497 3608 """dump the header and diffs for one or more changesets
3498 3609
3499 3610 Print the changeset header and diffs for one or more revisions.
3500 3611 If no revision is given, the parent of the working directory is used.
3501 3612
3502 3613 The information shown in the changeset header is: author, date,
3503 3614 branch name (if non-default), changeset hash, parent(s) and commit
3504 3615 comment.
3505 3616
3506 3617 .. note::
3507 3618
3508 3619 export may generate unexpected diff output for merge
3509 3620 changesets, as it will compare the merge changeset against its
3510 3621 first parent only.
3511 3622
3512 3623 Output may be to a file, in which case the name of the file is
3513 3624 given using a format string. The formatting rules are as follows:
3514 3625
3515 3626 :``%%``: literal "%" character
3516 3627 :``%H``: changeset hash (40 hexadecimal digits)
3517 3628 :``%N``: number of patches being generated
3518 3629 :``%R``: changeset revision number
3519 3630 :``%b``: basename of the exporting repository
3520 3631 :``%h``: short-form changeset hash (12 hexadecimal digits)
3521 3632 :``%m``: first line of the commit message (only alphanumeric characters)
3522 3633 :``%n``: zero-padded sequence number, starting at 1
3523 3634 :``%r``: zero-padded changeset revision number
3524 3635
3525 3636 Without the -a/--text option, export will avoid generating diffs
3526 3637 of files it detects as binary. With -a, export will generate a
3527 3638 diff anyway, probably with undesirable results.
3528 3639
3529 3640 Use the -g/--git option to generate diffs in the git extended diff
3530 3641 format. See :hg:`help diffs` for more information.
3531 3642
3532 3643 With the --switch-parent option, the diff will be against the
3533 3644 second parent. It can be useful to review a merge.
3534 3645
3535 3646 .. container:: verbose
3536 3647
3537 3648 Examples:
3538 3649
3539 3650 - use export and import to transplant a bugfix to the current
3540 3651 branch::
3541 3652
3542 3653 hg export -r 9353 | hg import -
3543 3654
3544 3655 - export all the changesets between two revisions to a file with
3545 3656 rename information::
3546 3657
3547 3658 hg export --git -r 123:150 > changes.txt
3548 3659
3549 3660 - split outgoing changes into a series of patches with
3550 3661 descriptive names::
3551 3662
3552 3663 hg export -r "outgoing()" -o "%n-%m.patch"
3553 3664
3554 3665 Returns 0 on success.
3555 3666 """
3556 3667 changesets += tuple(opts.get('rev', []))
3557 3668 if not changesets:
3558 3669 changesets = ['.']
3559 3670 revs = scmutil.revrange(repo, changesets)
3560 3671 if not revs:
3561 3672 raise error.Abort(_("export requires at least one changeset"))
3562 3673 if len(revs) > 1:
3563 3674 ui.note(_('exporting patches:\n'))
3564 3675 else:
3565 3676 ui.note(_('exporting patch:\n'))
3566 3677 cmdutil.export(repo, revs, template=opts.get('output'),
3567 3678 switch_parent=opts.get('switch_parent'),
3568 3679 opts=patch.diffallopts(ui, opts))
3569 3680
3570 3681 @command('files',
3571 3682 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3572 3683 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3573 3684 ] + walkopts + formatteropts + subrepoopts,
3574 3685 _('[OPTION]... [PATTERN]...'))
3575 3686 def files(ui, repo, *pats, **opts):
3576 3687 """list tracked files
3577 3688
3578 3689 Print files under Mercurial control in the working directory or
3579 3690 specified revision whose names match the given patterns (excluding
3580 3691 removed files).
3581 3692
3582 3693 If no patterns are given to match, this command prints the names
3583 3694 of all files under Mercurial control in the working directory.
3584 3695
3585 3696 .. container:: verbose
3586 3697
3587 3698 Examples:
3588 3699
3589 3700 - list all files under the current directory::
3590 3701
3591 3702 hg files .
3592 3703
3593 3704 - shows sizes and flags for current revision::
3594 3705
3595 3706 hg files -vr .
3596 3707
3597 3708 - list all files named README::
3598 3709
3599 3710 hg files -I "**/README"
3600 3711
3601 3712 - list all binary files::
3602 3713
3603 3714 hg files "set:binary()"
3604 3715
3605 3716 - find files containing a regular expression::
3606 3717
3607 3718 hg files "set:grep('bob')"
3608 3719
3609 3720 - search tracked file contents with xargs and grep::
3610 3721
3611 3722 hg files -0 | xargs -0 grep foo
3612 3723
3613 3724 See :hg:`help patterns` and :hg:`help filesets` for more information
3614 3725 on specifying file patterns.
3615 3726
3616 3727 Returns 0 if a match is found, 1 otherwise.
3617 3728
3618 3729 """
3619 3730 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3620 3731
3621 3732 end = '\n'
3622 3733 if opts.get('print0'):
3623 3734 end = '\0'
3624 3735 fm = ui.formatter('files', opts)
3625 3736 fmt = '%s' + end
3626 3737
3627 3738 m = scmutil.match(ctx, pats, opts)
3628 3739 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3629 3740
3630 3741 fm.end()
3631 3742
3632 3743 return ret
3633 3744
3634 3745 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3635 3746 def forget(ui, repo, *pats, **opts):
3636 3747 """forget the specified files on the next commit
3637 3748
3638 3749 Mark the specified files so they will no longer be tracked
3639 3750 after the next commit.
3640 3751
3641 3752 This only removes files from the current branch, not from the
3642 3753 entire project history, and it does not delete them from the
3643 3754 working directory.
3644 3755
3645 3756 To delete the file from the working directory, see :hg:`remove`.
3646 3757
3647 3758 To undo a forget before the next commit, see :hg:`add`.
3648 3759
3649 3760 .. container:: verbose
3650 3761
3651 3762 Examples:
3652 3763
3653 3764 - forget newly-added binary files::
3654 3765
3655 3766 hg forget "set:added() and binary()"
3656 3767
3657 3768 - forget files that would be excluded by .hgignore::
3658 3769
3659 3770 hg forget "set:hgignore()"
3660 3771
3661 3772 Returns 0 on success.
3662 3773 """
3663 3774
3664 3775 if not pats:
3665 3776 raise error.Abort(_('no files specified'))
3666 3777
3667 3778 m = scmutil.match(repo[None], pats, opts)
3668 3779 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3669 3780 return rejected and 1 or 0
3670 3781
3671 3782 @command(
3672 3783 'graft',
3673 3784 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3674 3785 ('c', 'continue', False, _('resume interrupted graft')),
3675 3786 ('e', 'edit', False, _('invoke editor on commit messages')),
3676 3787 ('', 'log', None, _('append graft info to log message')),
3677 3788 ('f', 'force', False, _('force graft')),
3678 3789 ('D', 'currentdate', False,
3679 3790 _('record the current date as commit date')),
3680 3791 ('U', 'currentuser', False,
3681 3792 _('record the current user as committer'), _('DATE'))]
3682 3793 + commitopts2 + mergetoolopts + dryrunopts,
3683 3794 _('[OPTION]... [-r] REV...'))
3684 3795 def graft(ui, repo, *revs, **opts):
3685 3796 '''copy changes from other branches onto the current branch
3686 3797
3687 3798 This command uses Mercurial's merge logic to copy individual
3688 3799 changes from other branches without merging branches in the
3689 3800 history graph. This is sometimes known as 'backporting' or
3690 3801 'cherry-picking'. By default, graft will copy user, date, and
3691 3802 description from the source changesets.
3692 3803
3693 3804 Changesets that are ancestors of the current revision, that have
3694 3805 already been grafted, or that are merges will be skipped.
3695 3806
3696 3807 If --log is specified, log messages will have a comment appended
3697 3808 of the form::
3698 3809
3699 3810 (grafted from CHANGESETHASH)
3700 3811
3701 3812 If --force is specified, revisions will be grafted even if they
3702 3813 are already ancestors of or have been grafted to the destination.
3703 3814 This is useful when the revisions have since been backed out.
3704 3815
3705 3816 If a graft merge results in conflicts, the graft process is
3706 3817 interrupted so that the current merge can be manually resolved.
3707 3818 Once all conflicts are addressed, the graft process can be
3708 3819 continued with the -c/--continue option.
3709 3820
3710 3821 .. note::
3711 3822
3712 3823 The -c/--continue option does not reapply earlier options, except
3713 3824 for --force.
3714 3825
3715 3826 .. container:: verbose
3716 3827
3717 3828 Examples:
3718 3829
3719 3830 - copy a single change to the stable branch and edit its description::
3720 3831
3721 3832 hg update stable
3722 3833 hg graft --edit 9393
3723 3834
3724 3835 - graft a range of changesets with one exception, updating dates::
3725 3836
3726 3837 hg graft -D "2085::2093 and not 2091"
3727 3838
3728 3839 - continue a graft after resolving conflicts::
3729 3840
3730 3841 hg graft -c
3731 3842
3732 3843 - show the source of a grafted changeset::
3733 3844
3734 3845 hg log --debug -r .
3735 3846
3736 3847 See :hg:`help revisions` and :hg:`help revsets` for more about
3737 3848 specifying revisions.
3738 3849
3739 3850 Returns 0 on successful completion.
3740 3851 '''
3741 3852 wlock = None
3742 3853 try:
3743 3854 wlock = repo.wlock()
3744 3855 return _dograft(ui, repo, *revs, **opts)
3745 3856 finally:
3746 3857 release(wlock)
3747 3858
3748 3859 def _dograft(ui, repo, *revs, **opts):
3749 3860 revs = list(revs)
3750 3861 revs.extend(opts['rev'])
3751 3862
3752 3863 if not opts.get('user') and opts.get('currentuser'):
3753 3864 opts['user'] = ui.username()
3754 3865 if not opts.get('date') and opts.get('currentdate'):
3755 3866 opts['date'] = "%d %d" % util.makedate()
3756 3867
3757 3868 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3758 3869
3759 3870 cont = False
3760 3871 if opts['continue']:
3761 3872 cont = True
3762 3873 if revs:
3763 3874 raise error.Abort(_("can't specify --continue and revisions"))
3764 3875 # read in unfinished revisions
3765 3876 try:
3766 3877 nodes = repo.vfs.read('graftstate').splitlines()
3767 3878 revs = [repo[node].rev() for node in nodes]
3768 3879 except IOError as inst:
3769 3880 if inst.errno != errno.ENOENT:
3770 3881 raise
3771 3882 raise error.Abort(_("no graft state found, can't continue"))
3772 3883 else:
3773 3884 cmdutil.checkunfinished(repo)
3774 3885 cmdutil.bailifchanged(repo)
3775 3886 if not revs:
3776 3887 raise error.Abort(_('no revisions specified'))
3777 3888 revs = scmutil.revrange(repo, revs)
3778 3889
3779 3890 skipped = set()
3780 3891 # check for merges
3781 3892 for rev in repo.revs('%ld and merge()', revs):
3782 3893 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3783 3894 skipped.add(rev)
3784 3895 revs = [r for r in revs if r not in skipped]
3785 3896 if not revs:
3786 3897 return -1
3787 3898
3788 3899 # Don't check in the --continue case, in effect retaining --force across
3789 3900 # --continues. That's because without --force, any revisions we decided to
3790 3901 # skip would have been filtered out here, so they wouldn't have made their
3791 3902 # way to the graftstate. With --force, any revisions we would have otherwise
3792 3903 # skipped would not have been filtered out, and if they hadn't been applied
3793 3904 # already, they'd have been in the graftstate.
3794 3905 if not (cont or opts.get('force')):
3795 3906 # check for ancestors of dest branch
3796 3907 crev = repo['.'].rev()
3797 3908 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3798 3909 # Cannot use x.remove(y) on smart set, this has to be a list.
3799 3910 # XXX make this lazy in the future
3800 3911 revs = list(revs)
3801 3912 # don't mutate while iterating, create a copy
3802 3913 for rev in list(revs):
3803 3914 if rev in ancestors:
3804 3915 ui.warn(_('skipping ancestor revision %d:%s\n') %
3805 3916 (rev, repo[rev]))
3806 3917 # XXX remove on list is slow
3807 3918 revs.remove(rev)
3808 3919 if not revs:
3809 3920 return -1
3810 3921
3811 3922 # analyze revs for earlier grafts
3812 3923 ids = {}
3813 3924 for ctx in repo.set("%ld", revs):
3814 3925 ids[ctx.hex()] = ctx.rev()
3815 3926 n = ctx.extra().get('source')
3816 3927 if n:
3817 3928 ids[n] = ctx.rev()
3818 3929
3819 3930 # check ancestors for earlier grafts
3820 3931 ui.debug('scanning for duplicate grafts\n')
3821 3932
3822 3933 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3823 3934 ctx = repo[rev]
3824 3935 n = ctx.extra().get('source')
3825 3936 if n in ids:
3826 3937 try:
3827 3938 r = repo[n].rev()
3828 3939 except error.RepoLookupError:
3829 3940 r = None
3830 3941 if r in revs:
3831 3942 ui.warn(_('skipping revision %d:%s '
3832 3943 '(already grafted to %d:%s)\n')
3833 3944 % (r, repo[r], rev, ctx))
3834 3945 revs.remove(r)
3835 3946 elif ids[n] in revs:
3836 3947 if r is None:
3837 3948 ui.warn(_('skipping already grafted revision %d:%s '
3838 3949 '(%d:%s also has unknown origin %s)\n')
3839 3950 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3840 3951 else:
3841 3952 ui.warn(_('skipping already grafted revision %d:%s '
3842 3953 '(%d:%s also has origin %d:%s)\n')
3843 3954 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3844 3955 revs.remove(ids[n])
3845 3956 elif ctx.hex() in ids:
3846 3957 r = ids[ctx.hex()]
3847 3958 ui.warn(_('skipping already grafted revision %d:%s '
3848 3959 '(was grafted from %d:%s)\n') %
3849 3960 (r, repo[r], rev, ctx))
3850 3961 revs.remove(r)
3851 3962 if not revs:
3852 3963 return -1
3853 3964
3854 3965 try:
3855 3966 for pos, ctx in enumerate(repo.set("%ld", revs)):
3856 3967 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3857 3968 ctx.description().split('\n', 1)[0])
3858 3969 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3859 3970 if names:
3860 3971 desc += ' (%s)' % ' '.join(names)
3861 3972 ui.status(_('grafting %s\n') % desc)
3862 3973 if opts.get('dry_run'):
3863 3974 continue
3864 3975
3865 3976 extra = ctx.extra().copy()
3866 3977 del extra['branch']
3867 3978 source = extra.get('source')
3868 3979 if source:
3869 3980 extra['intermediate-source'] = ctx.hex()
3870 3981 else:
3871 3982 extra['source'] = ctx.hex()
3872 3983 user = ctx.user()
3873 3984 if opts.get('user'):
3874 3985 user = opts['user']
3875 3986 date = ctx.date()
3876 3987 if opts.get('date'):
3877 3988 date = opts['date']
3878 3989 message = ctx.description()
3879 3990 if opts.get('log'):
3880 3991 message += '\n(grafted from %s)' % ctx.hex()
3881 3992
3882 3993 # we don't merge the first commit when continuing
3883 3994 if not cont:
3884 3995 # perform the graft merge with p1(rev) as 'ancestor'
3885 3996 try:
3886 3997 # ui.forcemerge is an internal variable, do not document
3887 3998 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3888 3999 'graft')
3889 4000 stats = mergemod.graft(repo, ctx, ctx.p1(),
3890 4001 ['local', 'graft'])
3891 4002 finally:
3892 4003 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3893 4004 # report any conflicts
3894 4005 if stats and stats[3] > 0:
3895 4006 # write out state for --continue
3896 4007 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3897 4008 repo.vfs.write('graftstate', ''.join(nodelines))
3898 4009 extra = ''
3899 4010 if opts.get('user'):
3900 4011 extra += ' --user %s' % opts['user']
3901 4012 if opts.get('date'):
3902 4013 extra += ' --date %s' % opts['date']
3903 4014 if opts.get('log'):
3904 4015 extra += ' --log'
3905 4016 hint=_('use hg resolve and hg graft --continue%s') % extra
3906 4017 raise error.Abort(
3907 4018 _("unresolved conflicts, can't continue"),
3908 4019 hint=hint)
3909 4020 else:
3910 4021 cont = False
3911 4022
3912 4023 # commit
3913 4024 node = repo.commit(text=message, user=user,
3914 4025 date=date, extra=extra, editor=editor)
3915 4026 if node is None:
3916 4027 ui.warn(
3917 4028 _('note: graft of %d:%s created no changes to commit\n') %
3918 4029 (ctx.rev(), ctx))
3919 4030 finally:
3920 4031 # TODO: get rid of this meaningless try/finally enclosing.
3921 4032 # this is kept only to reduce changes in a patch.
3922 4033 pass
3923 4034
3924 4035 # remove state when we complete successfully
3925 4036 if not opts.get('dry_run'):
3926 4037 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3927 4038
3928 4039 return 0
3929 4040
3930 4041 @command('grep',
3931 4042 [('0', 'print0', None, _('end fields with NUL')),
3932 4043 ('', 'all', None, _('print all revisions that match')),
3933 4044 ('a', 'text', None, _('treat all files as text')),
3934 4045 ('f', 'follow', None,
3935 4046 _('follow changeset history,'
3936 4047 ' or file history across copies and renames')),
3937 4048 ('i', 'ignore-case', None, _('ignore case when matching')),
3938 4049 ('l', 'files-with-matches', None,
3939 4050 _('print only filenames and revisions that match')),
3940 4051 ('n', 'line-number', None, _('print matching line numbers')),
3941 4052 ('r', 'rev', [],
3942 4053 _('only search files changed within revision range'), _('REV')),
3943 4054 ('u', 'user', None, _('list the author (long with -v)')),
3944 4055 ('d', 'date', None, _('list the date (short with -q)')),
3945 4056 ] + walkopts,
3946 4057 _('[OPTION]... PATTERN [FILE]...'),
3947 4058 inferrepo=True)
3948 4059 def grep(ui, repo, pattern, *pats, **opts):
3949 4060 """search for a pattern in specified files and revisions
3950 4061
3951 4062 Search revisions of files for a regular expression.
3952 4063
3953 4064 This command behaves differently than Unix grep. It only accepts
3954 4065 Python/Perl regexps. It searches repository history, not the
3955 4066 working directory. It always prints the revision number in which a
3956 4067 match appears.
3957 4068
3958 4069 By default, grep only prints output for the first revision of a
3959 4070 file in which it finds a match. To get it to print every revision
3960 4071 that contains a change in match status ("-" for a match that
3961 4072 becomes a non-match, or "+" for a non-match that becomes a match),
3962 4073 use the --all flag.
3963 4074
3964 4075 Returns 0 if a match is found, 1 otherwise.
3965 4076 """
3966 4077 reflags = re.M
3967 4078 if opts.get('ignore_case'):
3968 4079 reflags |= re.I
3969 4080 try:
3970 4081 regexp = util.re.compile(pattern, reflags)
3971 4082 except re.error as inst:
3972 4083 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3973 4084 return 1
3974 4085 sep, eol = ':', '\n'
3975 4086 if opts.get('print0'):
3976 4087 sep = eol = '\0'
3977 4088
3978 4089 getfile = util.lrucachefunc(repo.file)
3979 4090
3980 4091 def matchlines(body):
3981 4092 begin = 0
3982 4093 linenum = 0
3983 4094 while begin < len(body):
3984 4095 match = regexp.search(body, begin)
3985 4096 if not match:
3986 4097 break
3987 4098 mstart, mend = match.span()
3988 4099 linenum += body.count('\n', begin, mstart) + 1
3989 4100 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3990 4101 begin = body.find('\n', mend) + 1 or len(body) + 1
3991 4102 lend = begin - 1
3992 4103 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3993 4104
3994 4105 class linestate(object):
3995 4106 def __init__(self, line, linenum, colstart, colend):
3996 4107 self.line = line
3997 4108 self.linenum = linenum
3998 4109 self.colstart = colstart
3999 4110 self.colend = colend
4000 4111
4001 4112 def __hash__(self):
4002 4113 return hash((self.linenum, self.line))
4003 4114
4004 4115 def __eq__(self, other):
4005 4116 return self.line == other.line
4006 4117
4007 4118 def __iter__(self):
4008 4119 yield (self.line[:self.colstart], '')
4009 4120 yield (self.line[self.colstart:self.colend], 'grep.match')
4010 4121 rest = self.line[self.colend:]
4011 4122 while rest != '':
4012 4123 match = regexp.search(rest)
4013 4124 if not match:
4014 4125 yield (rest, '')
4015 4126 break
4016 4127 mstart, mend = match.span()
4017 4128 yield (rest[:mstart], '')
4018 4129 yield (rest[mstart:mend], 'grep.match')
4019 4130 rest = rest[mend:]
4020 4131
4021 4132 matches = {}
4022 4133 copies = {}
4023 4134 def grepbody(fn, rev, body):
4024 4135 matches[rev].setdefault(fn, [])
4025 4136 m = matches[rev][fn]
4026 4137 for lnum, cstart, cend, line in matchlines(body):
4027 4138 s = linestate(line, lnum, cstart, cend)
4028 4139 m.append(s)
4029 4140
4030 4141 def difflinestates(a, b):
4031 4142 sm = difflib.SequenceMatcher(None, a, b)
4032 4143 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4033 4144 if tag == 'insert':
4034 4145 for i in xrange(blo, bhi):
4035 4146 yield ('+', b[i])
4036 4147 elif tag == 'delete':
4037 4148 for i in xrange(alo, ahi):
4038 4149 yield ('-', a[i])
4039 4150 elif tag == 'replace':
4040 4151 for i in xrange(alo, ahi):
4041 4152 yield ('-', a[i])
4042 4153 for i in xrange(blo, bhi):
4043 4154 yield ('+', b[i])
4044 4155
4045 4156 def display(fn, ctx, pstates, states):
4046 4157 rev = ctx.rev()
4047 4158 if ui.quiet:
4048 4159 datefunc = util.shortdate
4049 4160 else:
4050 4161 datefunc = util.datestr
4051 4162 found = False
4052 4163 @util.cachefunc
4053 4164 def binary():
4054 4165 flog = getfile(fn)
4055 4166 return util.binary(flog.read(ctx.filenode(fn)))
4056 4167
4057 4168 if opts.get('all'):
4058 4169 iter = difflinestates(pstates, states)
4059 4170 else:
4060 4171 iter = [('', l) for l in states]
4061 4172 for change, l in iter:
4062 4173 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4063 4174
4064 4175 if opts.get('line_number'):
4065 4176 cols.append((str(l.linenum), 'grep.linenumber'))
4066 4177 if opts.get('all'):
4067 4178 cols.append((change, 'grep.change'))
4068 4179 if opts.get('user'):
4069 4180 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4070 4181 if opts.get('date'):
4071 4182 cols.append((datefunc(ctx.date()), 'grep.date'))
4072 4183 for col, label in cols[:-1]:
4073 4184 ui.write(col, label=label)
4074 4185 ui.write(sep, label='grep.sep')
4075 4186 ui.write(cols[-1][0], label=cols[-1][1])
4076 4187 if not opts.get('files_with_matches'):
4077 4188 ui.write(sep, label='grep.sep')
4078 4189 if not opts.get('text') and binary():
4079 4190 ui.write(" Binary file matches")
4080 4191 else:
4081 4192 for s, label in l:
4082 4193 ui.write(s, label=label)
4083 4194 ui.write(eol)
4084 4195 found = True
4085 4196 if opts.get('files_with_matches'):
4086 4197 break
4087 4198 return found
4088 4199
4089 4200 skip = {}
4090 4201 revfiles = {}
4091 4202 matchfn = scmutil.match(repo[None], pats, opts)
4092 4203 found = False
4093 4204 follow = opts.get('follow')
4094 4205
4095 4206 def prep(ctx, fns):
4096 4207 rev = ctx.rev()
4097 4208 pctx = ctx.p1()
4098 4209 parent = pctx.rev()
4099 4210 matches.setdefault(rev, {})
4100 4211 matches.setdefault(parent, {})
4101 4212 files = revfiles.setdefault(rev, [])
4102 4213 for fn in fns:
4103 4214 flog = getfile(fn)
4104 4215 try:
4105 4216 fnode = ctx.filenode(fn)
4106 4217 except error.LookupError:
4107 4218 continue
4108 4219
4109 4220 copied = flog.renamed(fnode)
4110 4221 copy = follow and copied and copied[0]
4111 4222 if copy:
4112 4223 copies.setdefault(rev, {})[fn] = copy
4113 4224 if fn in skip:
4114 4225 if copy:
4115 4226 skip[copy] = True
4116 4227 continue
4117 4228 files.append(fn)
4118 4229
4119 4230 if fn not in matches[rev]:
4120 4231 grepbody(fn, rev, flog.read(fnode))
4121 4232
4122 4233 pfn = copy or fn
4123 4234 if pfn not in matches[parent]:
4124 4235 try:
4125 4236 fnode = pctx.filenode(pfn)
4126 4237 grepbody(pfn, parent, flog.read(fnode))
4127 4238 except error.LookupError:
4128 4239 pass
4129 4240
4130 4241 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4131 4242 rev = ctx.rev()
4132 4243 parent = ctx.p1().rev()
4133 4244 for fn in sorted(revfiles.get(rev, [])):
4134 4245 states = matches[rev][fn]
4135 4246 copy = copies.get(rev, {}).get(fn)
4136 4247 if fn in skip:
4137 4248 if copy:
4138 4249 skip[copy] = True
4139 4250 continue
4140 4251 pstates = matches.get(parent, {}).get(copy or fn, [])
4141 4252 if pstates or states:
4142 4253 r = display(fn, ctx, pstates, states)
4143 4254 found = found or r
4144 4255 if r and not opts.get('all'):
4145 4256 skip[fn] = True
4146 4257 if copy:
4147 4258 skip[copy] = True
4148 4259 del matches[rev]
4149 4260 del revfiles[rev]
4150 4261
4151 4262 return not found
4152 4263
4153 4264 @command('heads',
4154 4265 [('r', 'rev', '',
4155 4266 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4156 4267 ('t', 'topo', False, _('show topological heads only')),
4157 4268 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4158 4269 ('c', 'closed', False, _('show normal and closed branch heads')),
4159 4270 ] + templateopts,
4160 4271 _('[-ct] [-r STARTREV] [REV]...'))
4161 4272 def heads(ui, repo, *branchrevs, **opts):
4162 4273 """show branch heads
4163 4274
4164 4275 With no arguments, show all open branch heads in the repository.
4165 4276 Branch heads are changesets that have no descendants on the
4166 4277 same branch. They are where development generally takes place and
4167 4278 are the usual targets for update and merge operations.
4168 4279
4169 4280 If one or more REVs are given, only open branch heads on the
4170 4281 branches associated with the specified changesets are shown. This
4171 4282 means that you can use :hg:`heads .` to see the heads on the
4172 4283 currently checked-out branch.
4173 4284
4174 4285 If -c/--closed is specified, also show branch heads marked closed
4175 4286 (see :hg:`commit --close-branch`).
4176 4287
4177 4288 If STARTREV is specified, only those heads that are descendants of
4178 4289 STARTREV will be displayed.
4179 4290
4180 4291 If -t/--topo is specified, named branch mechanics will be ignored and only
4181 4292 topological heads (changesets with no children) will be shown.
4182 4293
4183 4294 Returns 0 if matching heads are found, 1 if not.
4184 4295 """
4185 4296
4186 4297 start = None
4187 4298 if 'rev' in opts:
4188 4299 start = scmutil.revsingle(repo, opts['rev'], None).node()
4189 4300
4190 4301 if opts.get('topo'):
4191 4302 heads = [repo[h] for h in repo.heads(start)]
4192 4303 else:
4193 4304 heads = []
4194 4305 for branch in repo.branchmap():
4195 4306 heads += repo.branchheads(branch, start, opts.get('closed'))
4196 4307 heads = [repo[h] for h in heads]
4197 4308
4198 4309 if branchrevs:
4199 4310 branches = set(repo[br].branch() for br in branchrevs)
4200 4311 heads = [h for h in heads if h.branch() in branches]
4201 4312
4202 4313 if opts.get('active') and branchrevs:
4203 4314 dagheads = repo.heads(start)
4204 4315 heads = [h for h in heads if h.node() in dagheads]
4205 4316
4206 4317 if branchrevs:
4207 4318 haveheads = set(h.branch() for h in heads)
4208 4319 if branches - haveheads:
4209 4320 headless = ', '.join(b for b in branches - haveheads)
4210 4321 msg = _('no open branch heads found on branches %s')
4211 4322 if opts.get('rev'):
4212 4323 msg += _(' (started at %s)') % opts['rev']
4213 4324 ui.warn((msg + '\n') % headless)
4214 4325
4215 4326 if not heads:
4216 4327 return 1
4217 4328
4218 4329 heads = sorted(heads, key=lambda x: -x.rev())
4219 4330 displayer = cmdutil.show_changeset(ui, repo, opts)
4220 4331 for ctx in heads:
4221 4332 displayer.show(ctx)
4222 4333 displayer.close()
4223 4334
4224 4335 @command('help',
4225 4336 [('e', 'extension', None, _('show only help for extensions')),
4226 4337 ('c', 'command', None, _('show only help for commands')),
4227 4338 ('k', 'keyword', None, _('show topics matching keyword')),
4228 4339 ],
4229 4340 _('[-eck] [TOPIC]'),
4230 4341 norepo=True)
4231 4342 def help_(ui, name=None, **opts):
4232 4343 """show help for a given topic or a help overview
4233 4344
4234 4345 With no arguments, print a list of commands with short help messages.
4235 4346
4236 4347 Given a topic, extension, or command name, print help for that
4237 4348 topic.
4238 4349
4239 4350 Returns 0 if successful.
4240 4351 """
4241 4352
4242 4353 textwidth = min(ui.termwidth(), 80) - 2
4243 4354
4244 4355 keep = []
4245 4356 if ui.verbose:
4246 4357 keep.append('verbose')
4247 4358 if sys.platform.startswith('win'):
4248 4359 keep.append('windows')
4249 4360 elif sys.platform == 'OpenVMS':
4250 4361 keep.append('vms')
4251 4362 elif sys.platform == 'plan9':
4252 4363 keep.append('plan9')
4253 4364 else:
4254 4365 keep.append('unix')
4255 4366 keep.append(sys.platform.lower())
4256 4367
4257 4368 section = None
4258 4369 if name and '.' in name:
4259 4370 name, section = name.split('.', 1)
4260 4371 section = section.lower()
4261 4372
4262 4373 text = help.help_(ui, name, **opts)
4263 4374
4264 4375 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4265 4376 section=section)
4266 4377
4267 4378 # We could have been given a weird ".foo" section without a name
4268 4379 # to look for, or we could have simply failed to found "foo.bar"
4269 4380 # because bar isn't a section of foo
4270 4381 if section and not (formatted and name):
4271 4382 raise error.Abort(_("help section not found"))
4272 4383
4273 4384 if 'verbose' in pruned:
4274 4385 keep.append('omitted')
4275 4386 else:
4276 4387 keep.append('notomitted')
4277 4388 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4278 4389 section=section)
4279 4390 ui.write(formatted)
4280 4391
4281 4392
4282 4393 @command('identify|id',
4283 4394 [('r', 'rev', '',
4284 4395 _('identify the specified revision'), _('REV')),
4285 4396 ('n', 'num', None, _('show local revision number')),
4286 4397 ('i', 'id', None, _('show global revision id')),
4287 4398 ('b', 'branch', None, _('show branch')),
4288 4399 ('t', 'tags', None, _('show tags')),
4289 4400 ('B', 'bookmarks', None, _('show bookmarks')),
4290 4401 ] + remoteopts,
4291 4402 _('[-nibtB] [-r REV] [SOURCE]'),
4292 4403 optionalrepo=True)
4293 4404 def identify(ui, repo, source=None, rev=None,
4294 4405 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4295 4406 """identify the working directory or specified revision
4296 4407
4297 4408 Print a summary identifying the repository state at REV using one or
4298 4409 two parent hash identifiers, followed by a "+" if the working
4299 4410 directory has uncommitted changes, the branch name (if not default),
4300 4411 a list of tags, and a list of bookmarks.
4301 4412
4302 4413 When REV is not given, print a summary of the current state of the
4303 4414 repository.
4304 4415
4305 4416 Specifying a path to a repository root or Mercurial bundle will
4306 4417 cause lookup to operate on that repository/bundle.
4307 4418
4308 4419 .. container:: verbose
4309 4420
4310 4421 Examples:
4311 4422
4312 4423 - generate a build identifier for the working directory::
4313 4424
4314 4425 hg id --id > build-id.dat
4315 4426
4316 4427 - find the revision corresponding to a tag::
4317 4428
4318 4429 hg id -n -r 1.3
4319 4430
4320 4431 - check the most recent revision of a remote repository::
4321 4432
4322 4433 hg id -r tip http://selenic.com/hg/
4323 4434
4324 4435 See :hg:`log` for generating more information about specific revisions,
4325 4436 including full hash identifiers.
4326 4437
4327 4438 Returns 0 if successful.
4328 4439 """
4329 4440
4330 4441 if not repo and not source:
4331 4442 raise error.Abort(_("there is no Mercurial repository here "
4332 4443 "(.hg not found)"))
4333 4444
4334 4445 if ui.debugflag:
4335 4446 hexfunc = hex
4336 4447 else:
4337 4448 hexfunc = short
4338 4449 default = not (num or id or branch or tags or bookmarks)
4339 4450 output = []
4340 4451 revs = []
4341 4452
4342 4453 if source:
4343 4454 source, branches = hg.parseurl(ui.expandpath(source))
4344 4455 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4345 4456 repo = peer.local()
4346 4457 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4347 4458
4348 4459 if not repo:
4349 4460 if num or branch or tags:
4350 4461 raise error.Abort(
4351 4462 _("can't query remote revision number, branch, or tags"))
4352 4463 if not rev and revs:
4353 4464 rev = revs[0]
4354 4465 if not rev:
4355 4466 rev = "tip"
4356 4467
4357 4468 remoterev = peer.lookup(rev)
4358 4469 if default or id:
4359 4470 output = [hexfunc(remoterev)]
4360 4471
4361 4472 def getbms():
4362 4473 bms = []
4363 4474
4364 4475 if 'bookmarks' in peer.listkeys('namespaces'):
4365 4476 hexremoterev = hex(remoterev)
4366 4477 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4367 4478 if bmr == hexremoterev]
4368 4479
4369 4480 return sorted(bms)
4370 4481
4371 4482 if bookmarks:
4372 4483 output.extend(getbms())
4373 4484 elif default and not ui.quiet:
4374 4485 # multiple bookmarks for a single parent separated by '/'
4375 4486 bm = '/'.join(getbms())
4376 4487 if bm:
4377 4488 output.append(bm)
4378 4489 else:
4379 4490 ctx = scmutil.revsingle(repo, rev, None)
4380 4491
4381 4492 if ctx.rev() is None:
4382 4493 ctx = repo[None]
4383 4494 parents = ctx.parents()
4384 4495 taglist = []
4385 4496 for p in parents:
4386 4497 taglist.extend(p.tags())
4387 4498
4388 4499 changed = ""
4389 4500 if default or id or num:
4390 4501 if (any(repo.status())
4391 4502 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4392 4503 changed = '+'
4393 4504 if default or id:
4394 4505 output = ["%s%s" %
4395 4506 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4396 4507 if num:
4397 4508 output.append("%s%s" %
4398 4509 ('+'.join([str(p.rev()) for p in parents]), changed))
4399 4510 else:
4400 4511 if default or id:
4401 4512 output = [hexfunc(ctx.node())]
4402 4513 if num:
4403 4514 output.append(str(ctx.rev()))
4404 4515 taglist = ctx.tags()
4405 4516
4406 4517 if default and not ui.quiet:
4407 4518 b = ctx.branch()
4408 4519 if b != 'default':
4409 4520 output.append("(%s)" % b)
4410 4521
4411 4522 # multiple tags for a single parent separated by '/'
4412 4523 t = '/'.join(taglist)
4413 4524 if t:
4414 4525 output.append(t)
4415 4526
4416 4527 # multiple bookmarks for a single parent separated by '/'
4417 4528 bm = '/'.join(ctx.bookmarks())
4418 4529 if bm:
4419 4530 output.append(bm)
4420 4531 else:
4421 4532 if branch:
4422 4533 output.append(ctx.branch())
4423 4534
4424 4535 if tags:
4425 4536 output.extend(taglist)
4426 4537
4427 4538 if bookmarks:
4428 4539 output.extend(ctx.bookmarks())
4429 4540
4430 4541 ui.write("%s\n" % ' '.join(output))
4431 4542
4432 4543 @command('import|patch',
4433 4544 [('p', 'strip', 1,
4434 4545 _('directory strip option for patch. This has the same '
4435 4546 'meaning as the corresponding patch option'), _('NUM')),
4436 4547 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4437 4548 ('e', 'edit', False, _('invoke editor on commit messages')),
4438 4549 ('f', 'force', None,
4439 4550 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4440 4551 ('', 'no-commit', None,
4441 4552 _("don't commit, just update the working directory")),
4442 4553 ('', 'bypass', None,
4443 4554 _("apply patch without touching the working directory")),
4444 4555 ('', 'partial', None,
4445 4556 _('commit even if some hunks fail')),
4446 4557 ('', 'exact', None,
4447 4558 _('apply patch to the nodes from which it was generated')),
4448 4559 ('', 'prefix', '',
4449 4560 _('apply patch to subdirectory'), _('DIR')),
4450 4561 ('', 'import-branch', None,
4451 4562 _('use any branch information in patch (implied by --exact)'))] +
4452 4563 commitopts + commitopts2 + similarityopts,
4453 4564 _('[OPTION]... PATCH...'))
4454 4565 def import_(ui, repo, patch1=None, *patches, **opts):
4455 4566 """import an ordered set of patches
4456 4567
4457 4568 Import a list of patches and commit them individually (unless
4458 4569 --no-commit is specified).
4459 4570
4460 4571 Because import first applies changes to the working directory,
4461 4572 import will abort if there are outstanding changes.
4462 4573
4463 4574 You can import a patch straight from a mail message. Even patches
4464 4575 as attachments work (to use the body part, it must have type
4465 4576 text/plain or text/x-patch). From and Subject headers of email
4466 4577 message are used as default committer and commit message. All
4467 4578 text/plain body parts before first diff are added to commit
4468 4579 message.
4469 4580
4470 4581 If the imported patch was generated by :hg:`export`, user and
4471 4582 description from patch override values from message headers and
4472 4583 body. Values given on command line with -m/--message and -u/--user
4473 4584 override these.
4474 4585
4475 4586 If --exact is specified, import will set the working directory to
4476 4587 the parent of each patch before applying it, and will abort if the
4477 4588 resulting changeset has a different ID than the one recorded in
4478 4589 the patch. This may happen due to character set problems or other
4479 4590 deficiencies in the text patch format.
4480 4591
4481 4592 Use --bypass to apply and commit patches directly to the
4482 4593 repository, not touching the working directory. Without --exact,
4483 4594 patches will be applied on top of the working directory parent
4484 4595 revision.
4485 4596
4486 4597 With -s/--similarity, hg will attempt to discover renames and
4487 4598 copies in the patch in the same way as :hg:`addremove`.
4488 4599
4489 4600 Use --partial to ensure a changeset will be created from the patch
4490 4601 even if some hunks fail to apply. Hunks that fail to apply will be
4491 4602 written to a <target-file>.rej file. Conflicts can then be resolved
4492 4603 by hand before :hg:`commit --amend` is run to update the created
4493 4604 changeset. This flag exists to let people import patches that
4494 4605 partially apply without losing the associated metadata (author,
4495 4606 date, description, ...). Note that when none of the hunk applies
4496 4607 cleanly, :hg:`import --partial` will create an empty changeset,
4497 4608 importing only the patch metadata.
4498 4609
4499 4610 It is possible to use external patch programs to perform the patch
4500 4611 by setting the ``ui.patch`` configuration option. For the default
4501 4612 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4502 4613 See :hg:`help config` for more information about configuration
4503 4614 files and how to use these options.
4504 4615
4505 4616 To read a patch from standard input, use "-" as the patch name. If
4506 4617 a URL is specified, the patch will be downloaded from it.
4507 4618 See :hg:`help dates` for a list of formats valid for -d/--date.
4508 4619
4509 4620 .. container:: verbose
4510 4621
4511 4622 Examples:
4512 4623
4513 4624 - import a traditional patch from a website and detect renames::
4514 4625
4515 4626 hg import -s 80 http://example.com/bugfix.patch
4516 4627
4517 4628 - import a changeset from an hgweb server::
4518 4629
4519 4630 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4520 4631
4521 4632 - import all the patches in an Unix-style mbox::
4522 4633
4523 4634 hg import incoming-patches.mbox
4524 4635
4525 4636 - attempt to exactly restore an exported changeset (not always
4526 4637 possible)::
4527 4638
4528 4639 hg import --exact proposed-fix.patch
4529 4640
4530 4641 - use an external tool to apply a patch which is too fuzzy for
4531 4642 the default internal tool.
4532 4643
4533 4644 hg import --config ui.patch="patch --merge" fuzzy.patch
4534 4645
4535 4646 - change the default fuzzing from 2 to a less strict 7
4536 4647
4537 4648 hg import --config ui.fuzz=7 fuzz.patch
4538 4649
4539 4650 Returns 0 on success, 1 on partial success (see --partial).
4540 4651 """
4541 4652
4542 4653 if not patch1:
4543 4654 raise error.Abort(_('need at least one patch to import'))
4544 4655
4545 4656 patches = (patch1,) + patches
4546 4657
4547 4658 date = opts.get('date')
4548 4659 if date:
4549 4660 opts['date'] = util.parsedate(date)
4550 4661
4551 4662 update = not opts.get('bypass')
4552 4663 if not update and opts.get('no_commit'):
4553 4664 raise error.Abort(_('cannot use --no-commit with --bypass'))
4554 4665 try:
4555 4666 sim = float(opts.get('similarity') or 0)
4556 4667 except ValueError:
4557 4668 raise error.Abort(_('similarity must be a number'))
4558 4669 if sim < 0 or sim > 100:
4559 4670 raise error.Abort(_('similarity must be between 0 and 100'))
4560 4671 if sim and not update:
4561 4672 raise error.Abort(_('cannot use --similarity with --bypass'))
4562 4673 if opts.get('exact') and opts.get('edit'):
4563 4674 raise error.Abort(_('cannot use --exact with --edit'))
4564 4675 if opts.get('exact') and opts.get('prefix'):
4565 4676 raise error.Abort(_('cannot use --exact with --prefix'))
4566 4677
4567 4678 base = opts["base"]
4568 4679 wlock = dsguard = lock = tr = None
4569 4680 msgs = []
4570 4681 ret = 0
4571 4682
4572 4683
4573 4684 try:
4574 4685 try:
4575 4686 wlock = repo.wlock()
4576 4687
4577 4688 if update:
4578 4689 cmdutil.checkunfinished(repo)
4579 4690 if (opts.get('exact') or not opts.get('force')) and update:
4580 4691 cmdutil.bailifchanged(repo)
4581 4692
4582 4693 if not opts.get('no_commit'):
4583 4694 lock = repo.lock()
4584 4695 tr = repo.transaction('import')
4585 4696 else:
4586 4697 dsguard = cmdutil.dirstateguard(repo, 'import')
4587 4698 parents = repo[None].parents()
4588 4699 for patchurl in patches:
4589 4700 if patchurl == '-':
4590 4701 ui.status(_('applying patch from stdin\n'))
4591 4702 patchfile = ui.fin
4592 4703 patchurl = 'stdin' # for error message
4593 4704 else:
4594 4705 patchurl = os.path.join(base, patchurl)
4595 4706 ui.status(_('applying %s\n') % patchurl)
4596 4707 patchfile = hg.openpath(ui, patchurl)
4597 4708
4598 4709 haspatch = False
4599 4710 for hunk in patch.split(patchfile):
4600 4711 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4601 4712 parents, opts,
4602 4713 msgs, hg.clean)
4603 4714 if msg:
4604 4715 haspatch = True
4605 4716 ui.note(msg + '\n')
4606 4717 if update or opts.get('exact'):
4607 4718 parents = repo[None].parents()
4608 4719 else:
4609 4720 parents = [repo[node]]
4610 4721 if rej:
4611 4722 ui.write_err(_("patch applied partially\n"))
4612 4723 ui.write_err(_("(fix the .rej files and run "
4613 4724 "`hg commit --amend`)\n"))
4614 4725 ret = 1
4615 4726 break
4616 4727
4617 4728 if not haspatch:
4618 4729 raise error.Abort(_('%s: no diffs found') % patchurl)
4619 4730
4620 4731 if tr:
4621 4732 tr.close()
4622 4733 if msgs:
4623 4734 repo.savecommitmessage('\n* * *\n'.join(msgs))
4624 4735 if dsguard:
4625 4736 dsguard.close()
4626 4737 return ret
4627 4738 finally:
4628 4739 # TODO: get rid of this meaningless try/finally enclosing.
4629 4740 # this is kept only to reduce changes in a patch.
4630 4741 pass
4631 4742 finally:
4632 4743 if tr:
4633 4744 tr.release()
4634 4745 release(lock, dsguard, wlock)
4635 4746
4636 4747 @command('incoming|in',
4637 4748 [('f', 'force', None,
4638 4749 _('run even if remote repository is unrelated')),
4639 4750 ('n', 'newest-first', None, _('show newest record first')),
4640 4751 ('', 'bundle', '',
4641 4752 _('file to store the bundles into'), _('FILE')),
4642 4753 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4643 4754 ('B', 'bookmarks', False, _("compare bookmarks")),
4644 4755 ('b', 'branch', [],
4645 4756 _('a specific branch you would like to pull'), _('BRANCH')),
4646 4757 ] + logopts + remoteopts + subrepoopts,
4647 4758 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4648 4759 def incoming(ui, repo, source="default", **opts):
4649 4760 """show new changesets found in source
4650 4761
4651 4762 Show new changesets found in the specified path/URL or the default
4652 4763 pull location. These are the changesets that would have been pulled
4653 4764 if a pull at the time you issued this command.
4654 4765
4655 4766 See pull for valid source format details.
4656 4767
4657 4768 .. container:: verbose
4658 4769
4659 4770 With -B/--bookmarks, the result of bookmark comparison between
4660 4771 local and remote repositories is displayed. With -v/--verbose,
4661 4772 status is also displayed for each bookmark like below::
4662 4773
4663 4774 BM1 01234567890a added
4664 4775 BM2 1234567890ab advanced
4665 4776 BM3 234567890abc diverged
4666 4777 BM4 34567890abcd changed
4667 4778
4668 4779 The action taken locally when pulling depends on the
4669 4780 status of each bookmark:
4670 4781
4671 4782 :``added``: pull will create it
4672 4783 :``advanced``: pull will update it
4673 4784 :``diverged``: pull will create a divergent bookmark
4674 4785 :``changed``: result depends on remote changesets
4675 4786
4676 4787 From the point of view of pulling behavior, bookmark
4677 4788 existing only in the remote repository are treated as ``added``,
4678 4789 even if it is in fact locally deleted.
4679 4790
4680 4791 .. container:: verbose
4681 4792
4682 4793 For remote repository, using --bundle avoids downloading the
4683 4794 changesets twice if the incoming is followed by a pull.
4684 4795
4685 4796 Examples:
4686 4797
4687 4798 - show incoming changes with patches and full description::
4688 4799
4689 4800 hg incoming -vp
4690 4801
4691 4802 - show incoming changes excluding merges, store a bundle::
4692 4803
4693 4804 hg in -vpM --bundle incoming.hg
4694 4805 hg pull incoming.hg
4695 4806
4696 4807 - briefly list changes inside a bundle::
4697 4808
4698 4809 hg in changes.hg -T "{desc|firstline}\\n"
4699 4810
4700 4811 Returns 0 if there are incoming changes, 1 otherwise.
4701 4812 """
4702 4813 if opts.get('graph'):
4703 4814 cmdutil.checkunsupportedgraphflags([], opts)
4704 4815 def display(other, chlist, displayer):
4705 4816 revdag = cmdutil.graphrevs(other, chlist, opts)
4706 4817 cmdutil.displaygraph(ui, repo, revdag, displayer,
4707 4818 graphmod.asciiedges)
4708 4819
4709 4820 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4710 4821 return 0
4711 4822
4712 4823 if opts.get('bundle') and opts.get('subrepos'):
4713 4824 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4714 4825
4715 4826 if opts.get('bookmarks'):
4716 4827 source, branches = hg.parseurl(ui.expandpath(source),
4717 4828 opts.get('branch'))
4718 4829 other = hg.peer(repo, opts, source)
4719 4830 if 'bookmarks' not in other.listkeys('namespaces'):
4720 4831 ui.warn(_("remote doesn't support bookmarks\n"))
4721 4832 return 0
4722 4833 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4723 4834 return bookmarks.incoming(ui, repo, other)
4724 4835
4725 4836 repo._subtoppath = ui.expandpath(source)
4726 4837 try:
4727 4838 return hg.incoming(ui, repo, source, opts)
4728 4839 finally:
4729 4840 del repo._subtoppath
4730 4841
4731 4842
4732 4843 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4733 4844 norepo=True)
4734 4845 def init(ui, dest=".", **opts):
4735 4846 """create a new repository in the given directory
4736 4847
4737 4848 Initialize a new repository in the given directory. If the given
4738 4849 directory does not exist, it will be created.
4739 4850
4740 4851 If no directory is given, the current directory is used.
4741 4852
4742 4853 It is possible to specify an ``ssh://`` URL as the destination.
4743 4854 See :hg:`help urls` for more information.
4744 4855
4745 4856 Returns 0 on success.
4746 4857 """
4747 4858 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4748 4859
4749 4860 @command('locate',
4750 4861 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4751 4862 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4752 4863 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4753 4864 ] + walkopts,
4754 4865 _('[OPTION]... [PATTERN]...'))
4755 4866 def locate(ui, repo, *pats, **opts):
4756 4867 """locate files matching specific patterns (DEPRECATED)
4757 4868
4758 4869 Print files under Mercurial control in the working directory whose
4759 4870 names match the given patterns.
4760 4871
4761 4872 By default, this command searches all directories in the working
4762 4873 directory. To search just the current directory and its
4763 4874 subdirectories, use "--include .".
4764 4875
4765 4876 If no patterns are given to match, this command prints the names
4766 4877 of all files under Mercurial control in the working directory.
4767 4878
4768 4879 If you want to feed the output of this command into the "xargs"
4769 4880 command, use the -0 option to both this command and "xargs". This
4770 4881 will avoid the problem of "xargs" treating single filenames that
4771 4882 contain whitespace as multiple filenames.
4772 4883
4773 4884 See :hg:`help files` for a more versatile command.
4774 4885
4775 4886 Returns 0 if a match is found, 1 otherwise.
4776 4887 """
4777 4888 if opts.get('print0'):
4778 4889 end = '\0'
4779 4890 else:
4780 4891 end = '\n'
4781 4892 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4782 4893
4783 4894 ret = 1
4784 4895 ctx = repo[rev]
4785 4896 m = scmutil.match(ctx, pats, opts, default='relglob',
4786 4897 badfn=lambda x, y: False)
4787 4898
4788 4899 for abs in ctx.matches(m):
4789 4900 if opts.get('fullpath'):
4790 4901 ui.write(repo.wjoin(abs), end)
4791 4902 else:
4792 4903 ui.write(((pats and m.rel(abs)) or abs), end)
4793 4904 ret = 0
4794 4905
4795 4906 return ret
4796 4907
4797 4908 @command('^log|history',
4798 4909 [('f', 'follow', None,
4799 4910 _('follow changeset history, or file history across copies and renames')),
4800 4911 ('', 'follow-first', None,
4801 4912 _('only follow the first parent of merge changesets (DEPRECATED)')),
4802 4913 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4803 4914 ('C', 'copies', None, _('show copied files')),
4804 4915 ('k', 'keyword', [],
4805 4916 _('do case-insensitive search for a given text'), _('TEXT')),
4806 4917 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4807 4918 ('', 'removed', None, _('include revisions where files were removed')),
4808 4919 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4809 4920 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4810 4921 ('', 'only-branch', [],
4811 4922 _('show only changesets within the given named branch (DEPRECATED)'),
4812 4923 _('BRANCH')),
4813 4924 ('b', 'branch', [],
4814 4925 _('show changesets within the given named branch'), _('BRANCH')),
4815 4926 ('P', 'prune', [],
4816 4927 _('do not display revision or any of its ancestors'), _('REV')),
4817 4928 ] + logopts + walkopts,
4818 4929 _('[OPTION]... [FILE]'),
4819 4930 inferrepo=True)
4820 4931 def log(ui, repo, *pats, **opts):
4821 4932 """show revision history of entire repository or files
4822 4933
4823 4934 Print the revision history of the specified files or the entire
4824 4935 project.
4825 4936
4826 4937 If no revision range is specified, the default is ``tip:0`` unless
4827 4938 --follow is set, in which case the working directory parent is
4828 4939 used as the starting revision.
4829 4940
4830 4941 File history is shown without following rename or copy history of
4831 4942 files. Use -f/--follow with a filename to follow history across
4832 4943 renames and copies. --follow without a filename will only show
4833 4944 ancestors or descendants of the starting revision.
4834 4945
4835 4946 By default this command prints revision number and changeset id,
4836 4947 tags, non-trivial parents, user, date and time, and a summary for
4837 4948 each commit. When the -v/--verbose switch is used, the list of
4838 4949 changed files and full commit message are shown.
4839 4950
4840 4951 With --graph the revisions are shown as an ASCII art DAG with the most
4841 4952 recent changeset at the top.
4842 4953 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4843 4954 and '+' represents a fork where the changeset from the lines below is a
4844 4955 parent of the 'o' merge on the same line.
4845 4956
4846 4957 .. note::
4847 4958
4848 4959 log -p/--patch may generate unexpected diff output for merge
4849 4960 changesets, as it will only compare the merge changeset against
4850 4961 its first parent. Also, only files different from BOTH parents
4851 4962 will appear in files:.
4852 4963
4853 4964 .. note::
4854 4965
4855 4966 for performance reasons, log FILE may omit duplicate changes
4856 4967 made on branches and will not show removals or mode changes. To
4857 4968 see all such changes, use the --removed switch.
4858 4969
4859 4970 .. container:: verbose
4860 4971
4861 4972 Some examples:
4862 4973
4863 4974 - changesets with full descriptions and file lists::
4864 4975
4865 4976 hg log -v
4866 4977
4867 4978 - changesets ancestral to the working directory::
4868 4979
4869 4980 hg log -f
4870 4981
4871 4982 - last 10 commits on the current branch::
4872 4983
4873 4984 hg log -l 10 -b .
4874 4985
4875 4986 - changesets showing all modifications of a file, including removals::
4876 4987
4877 4988 hg log --removed file.c
4878 4989
4879 4990 - all changesets that touch a directory, with diffs, excluding merges::
4880 4991
4881 4992 hg log -Mp lib/
4882 4993
4883 4994 - all revision numbers that match a keyword::
4884 4995
4885 4996 hg log -k bug --template "{rev}\\n"
4886 4997
4887 4998 - the full hash identifier of the working directory parent::
4888 4999
4889 5000 hg log -r . --template "{node}\\n"
4890 5001
4891 5002 - list available log templates::
4892 5003
4893 5004 hg log -T list
4894 5005
4895 5006 - check if a given changeset is included in a tagged release::
4896 5007
4897 5008 hg log -r "a21ccf and ancestor(1.9)"
4898 5009
4899 5010 - find all changesets by some user in a date range::
4900 5011
4901 5012 hg log -k alice -d "may 2008 to jul 2008"
4902 5013
4903 5014 - summary of all changesets after the last tag::
4904 5015
4905 5016 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4906 5017
4907 5018 See :hg:`help dates` for a list of formats valid for -d/--date.
4908 5019
4909 5020 See :hg:`help revisions` and :hg:`help revsets` for more about
4910 5021 specifying revisions.
4911 5022
4912 5023 See :hg:`help templates` for more about pre-packaged styles and
4913 5024 specifying custom templates.
4914 5025
4915 5026 Returns 0 on success.
4916 5027
4917 5028 """
4918 5029 if opts.get('follow') and opts.get('rev'):
4919 5030 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4920 5031 del opts['follow']
4921 5032
4922 5033 if opts.get('graph'):
4923 5034 return cmdutil.graphlog(ui, repo, *pats, **opts)
4924 5035
4925 5036 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4926 5037 limit = cmdutil.loglimit(opts)
4927 5038 count = 0
4928 5039
4929 5040 getrenamed = None
4930 5041 if opts.get('copies'):
4931 5042 endrev = None
4932 5043 if opts.get('rev'):
4933 5044 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4934 5045 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4935 5046
4936 5047 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4937 5048 for rev in revs:
4938 5049 if count == limit:
4939 5050 break
4940 5051 ctx = repo[rev]
4941 5052 copies = None
4942 5053 if getrenamed is not None and rev:
4943 5054 copies = []
4944 5055 for fn in ctx.files():
4945 5056 rename = getrenamed(fn, rev)
4946 5057 if rename:
4947 5058 copies.append((fn, rename[0]))
4948 5059 if filematcher:
4949 5060 revmatchfn = filematcher(ctx.rev())
4950 5061 else:
4951 5062 revmatchfn = None
4952 5063 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4953 5064 if displayer.flush(ctx):
4954 5065 count += 1
4955 5066
4956 5067 displayer.close()
4957 5068
4958 5069 @command('manifest',
4959 5070 [('r', 'rev', '', _('revision to display'), _('REV')),
4960 5071 ('', 'all', False, _("list files from all revisions"))]
4961 5072 + formatteropts,
4962 5073 _('[-r REV]'))
4963 5074 def manifest(ui, repo, node=None, rev=None, **opts):
4964 5075 """output the current or given revision of the project manifest
4965 5076
4966 5077 Print a list of version controlled files for the given revision.
4967 5078 If no revision is given, the first parent of the working directory
4968 5079 is used, or the null revision if no revision is checked out.
4969 5080
4970 5081 With -v, print file permissions, symlink and executable bits.
4971 5082 With --debug, print file revision hashes.
4972 5083
4973 5084 If option --all is specified, the list of all files from all revisions
4974 5085 is printed. This includes deleted and renamed files.
4975 5086
4976 5087 Returns 0 on success.
4977 5088 """
4978 5089
4979 5090 fm = ui.formatter('manifest', opts)
4980 5091
4981 5092 if opts.get('all'):
4982 5093 if rev or node:
4983 5094 raise error.Abort(_("can't specify a revision with --all"))
4984 5095
4985 5096 res = []
4986 5097 prefix = "data/"
4987 5098 suffix = ".i"
4988 5099 plen = len(prefix)
4989 5100 slen = len(suffix)
4990 5101 lock = repo.lock()
4991 5102 try:
4992 5103 for fn, b, size in repo.store.datafiles():
4993 5104 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4994 5105 res.append(fn[plen:-slen])
4995 5106 finally:
4996 5107 lock.release()
4997 5108 for f in res:
4998 5109 fm.startitem()
4999 5110 fm.write("path", '%s\n', f)
5000 5111 fm.end()
5001 5112 return
5002 5113
5003 5114 if rev and node:
5004 5115 raise error.Abort(_("please specify just one revision"))
5005 5116
5006 5117 if not node:
5007 5118 node = rev
5008 5119
5009 5120 char = {'l': '@', 'x': '*', '': ''}
5010 5121 mode = {'l': '644', 'x': '755', '': '644'}
5011 5122 ctx = scmutil.revsingle(repo, node)
5012 5123 mf = ctx.manifest()
5013 5124 for f in ctx:
5014 5125 fm.startitem()
5015 5126 fl = ctx[f].flags()
5016 5127 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5017 5128 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5018 5129 fm.write('path', '%s\n', f)
5019 5130 fm.end()
5020 5131
5021 5132 @command('^merge',
5022 5133 [('f', 'force', None,
5023 5134 _('force a merge including outstanding changes (DEPRECATED)')),
5024 5135 ('r', 'rev', '', _('revision to merge'), _('REV')),
5025 5136 ('P', 'preview', None,
5026 5137 _('review revisions to merge (no merge is performed)'))
5027 5138 ] + mergetoolopts,
5028 5139 _('[-P] [-f] [[-r] REV]'))
5029 5140 def merge(ui, repo, node=None, **opts):
5030 5141 """merge another revision into working directory
5031 5142
5032 5143 The current working directory is updated with all changes made in
5033 5144 the requested revision since the last common predecessor revision.
5034 5145
5035 5146 Files that changed between either parent are marked as changed for
5036 5147 the next commit and a commit must be performed before any further
5037 5148 updates to the repository are allowed. The next commit will have
5038 5149 two parents.
5039 5150
5040 5151 ``--tool`` can be used to specify the merge tool used for file
5041 5152 merges. It overrides the HGMERGE environment variable and your
5042 5153 configuration files. See :hg:`help merge-tools` for options.
5043 5154
5044 5155 If no revision is specified, the working directory's parent is a
5045 5156 head revision, and the current branch contains exactly one other
5046 5157 head, the other head is merged with by default. Otherwise, an
5047 5158 explicit revision with which to merge with must be provided.
5048 5159
5049 5160 :hg:`resolve` must be used to resolve unresolved files.
5050 5161
5051 5162 To undo an uncommitted merge, use :hg:`update --clean .` which
5052 5163 will check out a clean copy of the original merge parent, losing
5053 5164 all changes.
5054 5165
5055 5166 Returns 0 on success, 1 if there are unresolved files.
5056 5167 """
5057 5168
5058 5169 if opts.get('rev') and node:
5059 5170 raise error.Abort(_("please specify just one revision"))
5060 5171 if not node:
5061 5172 node = opts.get('rev')
5062 5173
5063 5174 if node:
5064 5175 node = scmutil.revsingle(repo, node).node()
5065 5176
5066 5177 if not node:
5067 5178 node = repo[destutil.destmerge(repo)].node()
5068 5179
5069 5180 if opts.get('preview'):
5070 5181 # find nodes that are ancestors of p2 but not of p1
5071 5182 p1 = repo.lookup('.')
5072 5183 p2 = repo.lookup(node)
5073 5184 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5074 5185
5075 5186 displayer = cmdutil.show_changeset(ui, repo, opts)
5076 5187 for node in nodes:
5077 5188 displayer.show(repo[node])
5078 5189 displayer.close()
5079 5190 return 0
5080 5191
5081 5192 try:
5082 5193 # ui.forcemerge is an internal variable, do not document
5083 5194 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5084 5195 return hg.merge(repo, node, force=opts.get('force'))
5085 5196 finally:
5086 5197 ui.setconfig('ui', 'forcemerge', '', 'merge')
5087 5198
5088 5199 @command('outgoing|out',
5089 5200 [('f', 'force', None, _('run even when the destination is unrelated')),
5090 5201 ('r', 'rev', [],
5091 5202 _('a changeset intended to be included in the destination'), _('REV')),
5092 5203 ('n', 'newest-first', None, _('show newest record first')),
5093 5204 ('B', 'bookmarks', False, _('compare bookmarks')),
5094 5205 ('b', 'branch', [], _('a specific branch you would like to push'),
5095 5206 _('BRANCH')),
5096 5207 ] + logopts + remoteopts + subrepoopts,
5097 5208 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5098 5209 def outgoing(ui, repo, dest=None, **opts):
5099 5210 """show changesets not found in the destination
5100 5211
5101 5212 Show changesets not found in the specified destination repository
5102 5213 or the default push location. These are the changesets that would
5103 5214 be pushed if a push was requested.
5104 5215
5105 5216 See pull for details of valid destination formats.
5106 5217
5107 5218 .. container:: verbose
5108 5219
5109 5220 With -B/--bookmarks, the result of bookmark comparison between
5110 5221 local and remote repositories is displayed. With -v/--verbose,
5111 5222 status is also displayed for each bookmark like below::
5112 5223
5113 5224 BM1 01234567890a added
5114 5225 BM2 deleted
5115 5226 BM3 234567890abc advanced
5116 5227 BM4 34567890abcd diverged
5117 5228 BM5 4567890abcde changed
5118 5229
5119 5230 The action taken when pushing depends on the
5120 5231 status of each bookmark:
5121 5232
5122 5233 :``added``: push with ``-B`` will create it
5123 5234 :``deleted``: push with ``-B`` will delete it
5124 5235 :``advanced``: push will update it
5125 5236 :``diverged``: push with ``-B`` will update it
5126 5237 :``changed``: push with ``-B`` will update it
5127 5238
5128 5239 From the point of view of pushing behavior, bookmarks
5129 5240 existing only in the remote repository are treated as
5130 5241 ``deleted``, even if it is in fact added remotely.
5131 5242
5132 5243 Returns 0 if there are outgoing changes, 1 otherwise.
5133 5244 """
5134 5245 if opts.get('graph'):
5135 5246 cmdutil.checkunsupportedgraphflags([], opts)
5136 5247 o, other = hg._outgoing(ui, repo, dest, opts)
5137 5248 if not o:
5138 5249 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5139 5250 return
5140 5251
5141 5252 revdag = cmdutil.graphrevs(repo, o, opts)
5142 5253 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5143 5254 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5144 5255 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5145 5256 return 0
5146 5257
5147 5258 if opts.get('bookmarks'):
5148 5259 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5149 5260 dest, branches = hg.parseurl(dest, opts.get('branch'))
5150 5261 other = hg.peer(repo, opts, dest)
5151 5262 if 'bookmarks' not in other.listkeys('namespaces'):
5152 5263 ui.warn(_("remote doesn't support bookmarks\n"))
5153 5264 return 0
5154 5265 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5155 5266 return bookmarks.outgoing(ui, repo, other)
5156 5267
5157 5268 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5158 5269 try:
5159 5270 return hg.outgoing(ui, repo, dest, opts)
5160 5271 finally:
5161 5272 del repo._subtoppath
5162 5273
5163 5274 @command('parents',
5164 5275 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5165 5276 ] + templateopts,
5166 5277 _('[-r REV] [FILE]'),
5167 5278 inferrepo=True)
5168 5279 def parents(ui, repo, file_=None, **opts):
5169 5280 """show the parents of the working directory or revision (DEPRECATED)
5170 5281
5171 5282 Print the working directory's parent revisions. If a revision is
5172 5283 given via -r/--rev, the parent of that revision will be printed.
5173 5284 If a file argument is given, the revision in which the file was
5174 5285 last changed (before the working directory revision or the
5175 5286 argument to --rev if given) is printed.
5176 5287
5177 5288 See :hg:`summary` and :hg:`help revsets` for related information.
5178 5289
5179 5290 Returns 0 on success.
5180 5291 """
5181 5292
5182 5293 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5183 5294
5184 5295 if file_:
5185 5296 m = scmutil.match(ctx, (file_,), opts)
5186 5297 if m.anypats() or len(m.files()) != 1:
5187 5298 raise error.Abort(_('can only specify an explicit filename'))
5188 5299 file_ = m.files()[0]
5189 5300 filenodes = []
5190 5301 for cp in ctx.parents():
5191 5302 if not cp:
5192 5303 continue
5193 5304 try:
5194 5305 filenodes.append(cp.filenode(file_))
5195 5306 except error.LookupError:
5196 5307 pass
5197 5308 if not filenodes:
5198 5309 raise error.Abort(_("'%s' not found in manifest!") % file_)
5199 5310 p = []
5200 5311 for fn in filenodes:
5201 5312 fctx = repo.filectx(file_, fileid=fn)
5202 5313 p.append(fctx.node())
5203 5314 else:
5204 5315 p = [cp.node() for cp in ctx.parents()]
5205 5316
5206 5317 displayer = cmdutil.show_changeset(ui, repo, opts)
5207 5318 for n in p:
5208 5319 if n != nullid:
5209 5320 displayer.show(repo[n])
5210 5321 displayer.close()
5211 5322
5212 5323 @command('paths', [], _('[NAME]'), optionalrepo=True)
5213 5324 def paths(ui, repo, search=None):
5214 5325 """show aliases for remote repositories
5215 5326
5216 5327 Show definition of symbolic path name NAME. If no name is given,
5217 5328 show definition of all available names.
5218 5329
5219 5330 Option -q/--quiet suppresses all output when searching for NAME
5220 5331 and shows only the path names when listing all definitions.
5221 5332
5222 5333 Path names are defined in the [paths] section of your
5223 5334 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5224 5335 repository, ``.hg/hgrc`` is used, too.
5225 5336
5226 5337 The path names ``default`` and ``default-push`` have a special
5227 5338 meaning. When performing a push or pull operation, they are used
5228 5339 as fallbacks if no location is specified on the command-line.
5229 5340 When ``default-push`` is set, it will be used for push and
5230 5341 ``default`` will be used for pull; otherwise ``default`` is used
5231 5342 as the fallback for both. When cloning a repository, the clone
5232 5343 source is written as ``default`` in ``.hg/hgrc``. Note that
5233 5344 ``default`` and ``default-push`` apply to all inbound (e.g.
5234 5345 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5235 5346 :hg:`bundle`) operations.
5236 5347
5237 5348 See :hg:`help urls` for more information.
5238 5349
5239 5350 Returns 0 on success.
5240 5351 """
5241 5352 if search:
5242 5353 for name, path in sorted(ui.paths.iteritems()):
5243 5354 if name == search:
5244 5355 ui.status("%s\n" % util.hidepassword(path.loc))
5245 5356 return
5246 5357 if not ui.quiet:
5247 5358 ui.warn(_("not found!\n"))
5248 5359 return 1
5249 5360 else:
5250 5361 for name, path in sorted(ui.paths.iteritems()):
5251 5362 if ui.quiet:
5252 5363 ui.write("%s\n" % name)
5253 5364 else:
5254 5365 ui.write("%s = %s\n" % (name,
5255 5366 util.hidepassword(path.loc)))
5256 5367
5257 5368 @command('phase',
5258 5369 [('p', 'public', False, _('set changeset phase to public')),
5259 5370 ('d', 'draft', False, _('set changeset phase to draft')),
5260 5371 ('s', 'secret', False, _('set changeset phase to secret')),
5261 5372 ('f', 'force', False, _('allow to move boundary backward')),
5262 5373 ('r', 'rev', [], _('target revision'), _('REV')),
5263 5374 ],
5264 5375 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5265 5376 def phase(ui, repo, *revs, **opts):
5266 5377 """set or show the current phase name
5267 5378
5268 5379 With no argument, show the phase name of the current revision(s).
5269 5380
5270 5381 With one of -p/--public, -d/--draft or -s/--secret, change the
5271 5382 phase value of the specified revisions.
5272 5383
5273 5384 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5274 5385 lower phase to an higher phase. Phases are ordered as follows::
5275 5386
5276 5387 public < draft < secret
5277 5388
5278 5389 Returns 0 on success, 1 if some phases could not be changed.
5279 5390
5280 5391 (For more information about the phases concept, see :hg:`help phases`.)
5281 5392 """
5282 5393 # search for a unique phase argument
5283 5394 targetphase = None
5284 5395 for idx, name in enumerate(phases.phasenames):
5285 5396 if opts[name]:
5286 5397 if targetphase is not None:
5287 5398 raise error.Abort(_('only one phase can be specified'))
5288 5399 targetphase = idx
5289 5400
5290 5401 # look for specified revision
5291 5402 revs = list(revs)
5292 5403 revs.extend(opts['rev'])
5293 5404 if not revs:
5294 5405 # display both parents as the second parent phase can influence
5295 5406 # the phase of a merge commit
5296 5407 revs = [c.rev() for c in repo[None].parents()]
5297 5408
5298 5409 revs = scmutil.revrange(repo, revs)
5299 5410
5300 5411 lock = None
5301 5412 ret = 0
5302 5413 if targetphase is None:
5303 5414 # display
5304 5415 for r in revs:
5305 5416 ctx = repo[r]
5306 5417 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5307 5418 else:
5308 5419 tr = None
5309 5420 lock = repo.lock()
5310 5421 try:
5311 5422 tr = repo.transaction("phase")
5312 5423 # set phase
5313 5424 if not revs:
5314 5425 raise error.Abort(_('empty revision set'))
5315 5426 nodes = [repo[r].node() for r in revs]
5316 5427 # moving revision from public to draft may hide them
5317 5428 # We have to check result on an unfiltered repository
5318 5429 unfi = repo.unfiltered()
5319 5430 getphase = unfi._phasecache.phase
5320 5431 olddata = [getphase(unfi, r) for r in unfi]
5321 5432 phases.advanceboundary(repo, tr, targetphase, nodes)
5322 5433 if opts['force']:
5323 5434 phases.retractboundary(repo, tr, targetphase, nodes)
5324 5435 tr.close()
5325 5436 finally:
5326 5437 if tr is not None:
5327 5438 tr.release()
5328 5439 lock.release()
5329 5440 getphase = unfi._phasecache.phase
5330 5441 newdata = [getphase(unfi, r) for r in unfi]
5331 5442 changes = sum(newdata[r] != olddata[r] for r in unfi)
5332 5443 cl = unfi.changelog
5333 5444 rejected = [n for n in nodes
5334 5445 if newdata[cl.rev(n)] < targetphase]
5335 5446 if rejected:
5336 5447 ui.warn(_('cannot move %i changesets to a higher '
5337 5448 'phase, use --force\n') % len(rejected))
5338 5449 ret = 1
5339 5450 if changes:
5340 5451 msg = _('phase changed for %i changesets\n') % changes
5341 5452 if ret:
5342 5453 ui.status(msg)
5343 5454 else:
5344 5455 ui.note(msg)
5345 5456 else:
5346 5457 ui.warn(_('no phases changed\n'))
5347 5458 return ret
5348 5459
5349 5460 def postincoming(ui, repo, modheads, optupdate, checkout):
5350 5461 if modheads == 0:
5351 5462 return
5352 5463 if optupdate:
5353 5464 try:
5354 5465 brev = checkout
5355 5466 movemarkfrom = None
5356 5467 if not checkout:
5357 5468 updata = destutil.destupdate(repo)
5358 5469 checkout, movemarkfrom, brev = updata
5359 5470 ret = hg.update(repo, checkout)
5360 5471 except error.UpdateAbort as inst:
5361 5472 msg = _("not updating: %s") % str(inst)
5362 5473 hint = inst.hint
5363 5474 raise error.UpdateAbort(msg, hint=hint)
5364 5475 if not ret and not checkout:
5365 5476 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5366 5477 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5367 5478 return ret
5368 5479 if modheads > 1:
5369 5480 currentbranchheads = len(repo.branchheads())
5370 5481 if currentbranchheads == modheads:
5371 5482 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5372 5483 elif currentbranchheads > 1:
5373 5484 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5374 5485 "merge)\n"))
5375 5486 else:
5376 5487 ui.status(_("(run 'hg heads' to see heads)\n"))
5377 5488 else:
5378 5489 ui.status(_("(run 'hg update' to get a working copy)\n"))
5379 5490
5380 5491 @command('^pull',
5381 5492 [('u', 'update', None,
5382 5493 _('update to new branch head if changesets were pulled')),
5383 5494 ('f', 'force', None, _('run even when remote repository is unrelated')),
5384 5495 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5385 5496 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5386 5497 ('b', 'branch', [], _('a specific branch you would like to pull'),
5387 5498 _('BRANCH')),
5388 5499 ] + remoteopts,
5389 5500 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5390 5501 def pull(ui, repo, source="default", **opts):
5391 5502 """pull changes from the specified source
5392 5503
5393 5504 Pull changes from a remote repository to a local one.
5394 5505
5395 5506 This finds all changes from the repository at the specified path
5396 5507 or URL and adds them to a local repository (the current one unless
5397 5508 -R is specified). By default, this does not update the copy of the
5398 5509 project in the working directory.
5399 5510
5400 5511 Use :hg:`incoming` if you want to see what would have been added
5401 5512 by a pull at the time you issued this command. If you then decide
5402 5513 to add those changes to the repository, you should use :hg:`pull
5403 5514 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5404 5515
5405 5516 If SOURCE is omitted, the 'default' path will be used.
5406 5517 See :hg:`help urls` for more information.
5407 5518
5408 5519 Returns 0 on success, 1 if an update had unresolved files.
5409 5520 """
5410 5521 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5411 5522 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5412 5523 other = hg.peer(repo, opts, source)
5413 5524 try:
5414 5525 revs, checkout = hg.addbranchrevs(repo, other, branches,
5415 5526 opts.get('rev'))
5416 5527
5417 5528
5418 5529 pullopargs = {}
5419 5530 if opts.get('bookmark'):
5420 5531 if not revs:
5421 5532 revs = []
5422 5533 # The list of bookmark used here is not the one used to actually
5423 5534 # update the bookmark name. This can result in the revision pulled
5424 5535 # not ending up with the name of the bookmark because of a race
5425 5536 # condition on the server. (See issue 4689 for details)
5426 5537 remotebookmarks = other.listkeys('bookmarks')
5427 5538 pullopargs['remotebookmarks'] = remotebookmarks
5428 5539 for b in opts['bookmark']:
5429 5540 if b not in remotebookmarks:
5430 5541 raise error.Abort(_('remote bookmark %s not found!') % b)
5431 5542 revs.append(remotebookmarks[b])
5432 5543
5433 5544 if revs:
5434 5545 try:
5435 5546 # When 'rev' is a bookmark name, we cannot guarantee that it
5436 5547 # will be updated with that name because of a race condition
5437 5548 # server side. (See issue 4689 for details)
5438 5549 oldrevs = revs
5439 5550 revs = [] # actually, nodes
5440 5551 for r in oldrevs:
5441 5552 node = other.lookup(r)
5442 5553 revs.append(node)
5443 5554 if r == checkout:
5444 5555 checkout = node
5445 5556 except error.CapabilityError:
5446 5557 err = _("other repository doesn't support revision lookup, "
5447 5558 "so a rev cannot be specified.")
5448 5559 raise error.Abort(err)
5449 5560
5450 5561 pullopargs.update(opts.get('opargs', {}))
5451 5562 modheads = exchange.pull(repo, other, heads=revs,
5452 5563 force=opts.get('force'),
5453 5564 bookmarks=opts.get('bookmark', ()),
5454 5565 opargs=pullopargs).cgresult
5455 5566 if checkout:
5456 5567 checkout = str(repo.changelog.rev(checkout))
5457 5568 repo._subtoppath = source
5458 5569 try:
5459 5570 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5460 5571
5461 5572 finally:
5462 5573 del repo._subtoppath
5463 5574
5464 5575 finally:
5465 5576 other.close()
5466 5577 return ret
5467 5578
5468 5579 @command('^push',
5469 5580 [('f', 'force', None, _('force push')),
5470 5581 ('r', 'rev', [],
5471 5582 _('a changeset intended to be included in the destination'),
5472 5583 _('REV')),
5473 5584 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5474 5585 ('b', 'branch', [],
5475 5586 _('a specific branch you would like to push'), _('BRANCH')),
5476 5587 ('', 'new-branch', False, _('allow pushing a new branch')),
5477 5588 ] + remoteopts,
5478 5589 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5479 5590 def push(ui, repo, dest=None, **opts):
5480 5591 """push changes to the specified destination
5481 5592
5482 5593 Push changesets from the local repository to the specified
5483 5594 destination.
5484 5595
5485 5596 This operation is symmetrical to pull: it is identical to a pull
5486 5597 in the destination repository from the current one.
5487 5598
5488 5599 By default, push will not allow creation of new heads at the
5489 5600 destination, since multiple heads would make it unclear which head
5490 5601 to use. In this situation, it is recommended to pull and merge
5491 5602 before pushing.
5492 5603
5493 5604 Use --new-branch if you want to allow push to create a new named
5494 5605 branch that is not present at the destination. This allows you to
5495 5606 only create a new branch without forcing other changes.
5496 5607
5497 5608 .. note::
5498 5609
5499 5610 Extra care should be taken with the -f/--force option,
5500 5611 which will push all new heads on all branches, an action which will
5501 5612 almost always cause confusion for collaborators.
5502 5613
5503 5614 If -r/--rev is used, the specified revision and all its ancestors
5504 5615 will be pushed to the remote repository.
5505 5616
5506 5617 If -B/--bookmark is used, the specified bookmarked revision, its
5507 5618 ancestors, and the bookmark will be pushed to the remote
5508 5619 repository.
5509 5620
5510 5621 Please see :hg:`help urls` for important details about ``ssh://``
5511 5622 URLs. If DESTINATION is omitted, a default path will be used.
5512 5623
5513 5624 Returns 0 if push was successful, 1 if nothing to push.
5514 5625 """
5515 5626
5516 5627 if opts.get('bookmark'):
5517 5628 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5518 5629 for b in opts['bookmark']:
5519 5630 # translate -B options to -r so changesets get pushed
5520 5631 if b in repo._bookmarks:
5521 5632 opts.setdefault('rev', []).append(b)
5522 5633 else:
5523 5634 # if we try to push a deleted bookmark, translate it to null
5524 5635 # this lets simultaneous -r, -b options continue working
5525 5636 opts.setdefault('rev', []).append("null")
5526 5637
5527 5638 path = ui.paths.getpath(dest, default='default')
5528 5639 if not path:
5529 5640 raise error.Abort(_('default repository not configured!'),
5530 5641 hint=_('see the "path" section in "hg help config"'))
5531 5642 dest, branches = path.pushloc, (path.branch, opts.get('branch') or [])
5532 5643 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5533 5644 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5534 5645 other = hg.peer(repo, opts, dest)
5535 5646
5536 5647 if revs:
5537 5648 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5538 5649 if not revs:
5539 5650 raise error.Abort(_("specified revisions evaluate to an empty set"),
5540 5651 hint=_("use different revision arguments"))
5541 5652
5542 5653 repo._subtoppath = dest
5543 5654 try:
5544 5655 # push subrepos depth-first for coherent ordering
5545 5656 c = repo['']
5546 5657 subs = c.substate # only repos that are committed
5547 5658 for s in sorted(subs):
5548 5659 result = c.sub(s).push(opts)
5549 5660 if result == 0:
5550 5661 return not result
5551 5662 finally:
5552 5663 del repo._subtoppath
5553 5664 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5554 5665 newbranch=opts.get('new_branch'),
5555 5666 bookmarks=opts.get('bookmark', ()),
5556 5667 opargs=opts.get('opargs'))
5557 5668
5558 5669 result = not pushop.cgresult
5559 5670
5560 5671 if pushop.bkresult is not None:
5561 5672 if pushop.bkresult == 2:
5562 5673 result = 2
5563 5674 elif not result and pushop.bkresult:
5564 5675 result = 2
5565 5676
5566 5677 return result
5567 5678
5568 5679 @command('recover', [])
5569 5680 def recover(ui, repo):
5570 5681 """roll back an interrupted transaction
5571 5682
5572 5683 Recover from an interrupted commit or pull.
5573 5684
5574 5685 This command tries to fix the repository status after an
5575 5686 interrupted operation. It should only be necessary when Mercurial
5576 5687 suggests it.
5577 5688
5578 5689 Returns 0 if successful, 1 if nothing to recover or verify fails.
5579 5690 """
5580 5691 if repo.recover():
5581 5692 return hg.verify(repo)
5582 5693 return 1
5583 5694
5584 5695 @command('^remove|rm',
5585 5696 [('A', 'after', None, _('record delete for missing files')),
5586 5697 ('f', 'force', None,
5587 5698 _('remove (and delete) file even if added or modified')),
5588 5699 ] + subrepoopts + walkopts,
5589 5700 _('[OPTION]... FILE...'),
5590 5701 inferrepo=True)
5591 5702 def remove(ui, repo, *pats, **opts):
5592 5703 """remove the specified files on the next commit
5593 5704
5594 5705 Schedule the indicated files for removal from the current branch.
5595 5706
5596 5707 This command schedules the files to be removed at the next commit.
5597 5708 To undo a remove before that, see :hg:`revert`. To undo added
5598 5709 files, see :hg:`forget`.
5599 5710
5600 5711 .. container:: verbose
5601 5712
5602 5713 -A/--after can be used to remove only files that have already
5603 5714 been deleted, -f/--force can be used to force deletion, and -Af
5604 5715 can be used to remove files from the next revision without
5605 5716 deleting them from the working directory.
5606 5717
5607 5718 The following table details the behavior of remove for different
5608 5719 file states (columns) and option combinations (rows). The file
5609 5720 states are Added [A], Clean [C], Modified [M] and Missing [!]
5610 5721 (as reported by :hg:`status`). The actions are Warn, Remove
5611 5722 (from branch) and Delete (from disk):
5612 5723
5613 5724 ========= == == == ==
5614 5725 opt/state A C M !
5615 5726 ========= == == == ==
5616 5727 none W RD W R
5617 5728 -f R RD RD R
5618 5729 -A W W W R
5619 5730 -Af R R R R
5620 5731 ========= == == == ==
5621 5732
5622 5733 Note that remove never deletes files in Added [A] state from the
5623 5734 working directory, not even if option --force is specified.
5624 5735
5625 5736 Returns 0 on success, 1 if any warnings encountered.
5626 5737 """
5627 5738
5628 5739 after, force = opts.get('after'), opts.get('force')
5629 5740 if not pats and not after:
5630 5741 raise error.Abort(_('no files specified'))
5631 5742
5632 5743 m = scmutil.match(repo[None], pats, opts)
5633 5744 subrepos = opts.get('subrepos')
5634 5745 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5635 5746
5636 5747 @command('rename|move|mv',
5637 5748 [('A', 'after', None, _('record a rename that has already occurred')),
5638 5749 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5639 5750 ] + walkopts + dryrunopts,
5640 5751 _('[OPTION]... SOURCE... DEST'))
5641 5752 def rename(ui, repo, *pats, **opts):
5642 5753 """rename files; equivalent of copy + remove
5643 5754
5644 5755 Mark dest as copies of sources; mark sources for deletion. If dest
5645 5756 is a directory, copies are put in that directory. If dest is a
5646 5757 file, there can only be one source.
5647 5758
5648 5759 By default, this command copies the contents of files as they
5649 5760 exist in the working directory. If invoked with -A/--after, the
5650 5761 operation is recorded, but no copying is performed.
5651 5762
5652 5763 This command takes effect at the next commit. To undo a rename
5653 5764 before that, see :hg:`revert`.
5654 5765
5655 5766 Returns 0 on success, 1 if errors are encountered.
5656 5767 """
5657 5768 wlock = repo.wlock(False)
5658 5769 try:
5659 5770 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5660 5771 finally:
5661 5772 wlock.release()
5662 5773
5663 5774 @command('resolve',
5664 5775 [('a', 'all', None, _('select all unresolved files')),
5665 5776 ('l', 'list', None, _('list state of files needing merge')),
5666 5777 ('m', 'mark', None, _('mark files as resolved')),
5667 5778 ('u', 'unmark', None, _('mark files as unresolved')),
5668 5779 ('n', 'no-status', None, _('hide status prefix'))]
5669 5780 + mergetoolopts + walkopts + formatteropts,
5670 5781 _('[OPTION]... [FILE]...'),
5671 5782 inferrepo=True)
5672 5783 def resolve(ui, repo, *pats, **opts):
5673 5784 """redo merges or set/view the merge status of files
5674 5785
5675 5786 Merges with unresolved conflicts are often the result of
5676 5787 non-interactive merging using the ``internal:merge`` configuration
5677 5788 setting, or a command-line merge tool like ``diff3``. The resolve
5678 5789 command is used to manage the files involved in a merge, after
5679 5790 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5680 5791 working directory must have two parents). See :hg:`help
5681 5792 merge-tools` for information on configuring merge tools.
5682 5793
5683 5794 The resolve command can be used in the following ways:
5684 5795
5685 5796 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5686 5797 files, discarding any previous merge attempts. Re-merging is not
5687 5798 performed for files already marked as resolved. Use ``--all/-a``
5688 5799 to select all unresolved files. ``--tool`` can be used to specify
5689 5800 the merge tool used for the given files. It overrides the HGMERGE
5690 5801 environment variable and your configuration files. Previous file
5691 5802 contents are saved with a ``.orig`` suffix.
5692 5803
5693 5804 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5694 5805 (e.g. after having manually fixed-up the files). The default is
5695 5806 to mark all unresolved files.
5696 5807
5697 5808 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5698 5809 default is to mark all resolved files.
5699 5810
5700 5811 - :hg:`resolve -l`: list files which had or still have conflicts.
5701 5812 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5702 5813
5703 5814 Note that Mercurial will not let you commit files with unresolved
5704 5815 merge conflicts. You must use :hg:`resolve -m ...` before you can
5705 5816 commit after a conflicting merge.
5706 5817
5707 5818 Returns 0 on success, 1 if any files fail a resolve attempt.
5708 5819 """
5709 5820
5710 5821 all, mark, unmark, show, nostatus = \
5711 5822 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5712 5823
5713 5824 if (show and (mark or unmark)) or (mark and unmark):
5714 5825 raise error.Abort(_("too many options specified"))
5715 5826 if pats and all:
5716 5827 raise error.Abort(_("can't specify --all and patterns"))
5717 5828 if not (all or pats or show or mark or unmark):
5718 5829 raise error.Abort(_('no files or directories specified'),
5719 5830 hint=('use --all to re-merge all unresolved files'))
5720 5831
5721 5832 if show:
5722 5833 fm = ui.formatter('resolve', opts)
5723 5834 ms = mergemod.mergestate.read(repo)
5724 5835 m = scmutil.match(repo[None], pats, opts)
5725 5836 for f in ms:
5726 5837 if not m(f):
5727 5838 continue
5728 5839 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5729 5840 'd': 'driverresolved'}[ms[f]]
5730 5841 fm.startitem()
5731 5842 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5732 5843 fm.write('path', '%s\n', f, label=l)
5733 5844 fm.end()
5734 5845 return 0
5735 5846
5736 5847 wlock = repo.wlock()
5737 5848 try:
5738 5849 ms = mergemod.mergestate.read(repo)
5739 5850
5740 5851 if not (ms.active() or repo.dirstate.p2() != nullid):
5741 5852 raise error.Abort(
5742 5853 _('resolve command not applicable when not merging'))
5743 5854
5744 5855 wctx = repo[None]
5745 5856
5746 5857 if ms.mergedriver and ms.mdstate() == 'u':
5747 5858 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5748 5859 ms.commit()
5749 5860 # allow mark and unmark to go through
5750 5861 if not mark and not unmark and not proceed:
5751 5862 return 1
5752 5863
5753 5864 m = scmutil.match(wctx, pats, opts)
5754 5865 ret = 0
5755 5866 didwork = False
5756 5867 runconclude = False
5757 5868
5758 5869 tocomplete = []
5759 5870 for f in ms:
5760 5871 if not m(f):
5761 5872 continue
5762 5873
5763 5874 didwork = True
5764 5875
5765 5876 # don't let driver-resolved files be marked, and run the conclude
5766 5877 # step if asked to resolve
5767 5878 if ms[f] == "d":
5768 5879 exact = m.exact(f)
5769 5880 if mark:
5770 5881 if exact:
5771 5882 ui.warn(_('not marking %s as it is driver-resolved\n')
5772 5883 % f)
5773 5884 elif unmark:
5774 5885 if exact:
5775 5886 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5776 5887 % f)
5777 5888 else:
5778 5889 runconclude = True
5779 5890 continue
5780 5891
5781 5892 if mark:
5782 5893 ms.mark(f, "r")
5783 5894 elif unmark:
5784 5895 ms.mark(f, "u")
5785 5896 else:
5786 5897 # backup pre-resolve (merge uses .orig for its own purposes)
5787 5898 a = repo.wjoin(f)
5788 5899 try:
5789 5900 util.copyfile(a, a + ".resolve")
5790 5901 except (IOError, OSError) as inst:
5791 5902 if inst.errno != errno.ENOENT:
5792 5903 raise
5793 5904
5794 5905 try:
5795 5906 # preresolve file
5796 5907 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5797 5908 'resolve')
5798 5909 complete, r = ms.preresolve(f, wctx)
5799 5910 if not complete:
5800 5911 tocomplete.append(f)
5801 5912 elif r:
5802 5913 ret = 1
5803 5914 finally:
5804 5915 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5805 5916 ms.commit()
5806 5917
5807 5918 # replace filemerge's .orig file with our resolve file, but only
5808 5919 # for merges that are complete
5809 5920 if complete:
5810 5921 try:
5811 5922 util.rename(a + ".resolve",
5812 5923 cmdutil.origpath(ui, repo, a))
5813 5924 except OSError as inst:
5814 5925 if inst.errno != errno.ENOENT:
5815 5926 raise
5816 5927
5817 5928 for f in tocomplete:
5818 5929 try:
5819 5930 # resolve file
5820 5931 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5821 5932 'resolve')
5822 5933 r = ms.resolve(f, wctx)
5823 5934 if r:
5824 5935 ret = 1
5825 5936 finally:
5826 5937 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5827 5938 ms.commit()
5828 5939
5829 5940 # replace filemerge's .orig file with our resolve file
5830 5941 a = repo.wjoin(f)
5831 5942 try:
5832 5943 util.rename(a + ".resolve", cmdutil.origpath(ui, repo, a))
5833 5944 except OSError as inst:
5834 5945 if inst.errno != errno.ENOENT:
5835 5946 raise
5836 5947
5837 5948 ms.commit()
5838 5949 ms.recordactions()
5839 5950
5840 5951 if not didwork and pats:
5841 5952 ui.warn(_("arguments do not match paths that need resolving\n"))
5842 5953 elif ms.mergedriver and ms.mdstate() != 's':
5843 5954 # run conclude step when either a driver-resolved file is requested
5844 5955 # or there are no driver-resolved files
5845 5956 # we can't use 'ret' to determine whether any files are unresolved
5846 5957 # because we might not have tried to resolve some
5847 5958 if ((runconclude or not list(ms.driverresolved()))
5848 5959 and not list(ms.unresolved())):
5849 5960 proceed = mergemod.driverconclude(repo, ms, wctx)
5850 5961 ms.commit()
5851 5962 if not proceed:
5852 5963 return 1
5853 5964
5854 5965 finally:
5855 5966 wlock.release()
5856 5967
5857 5968 # Nudge users into finishing an unfinished operation
5858 5969 unresolvedf = list(ms.unresolved())
5859 5970 driverresolvedf = list(ms.driverresolved())
5860 5971 if not unresolvedf and not driverresolvedf:
5861 5972 ui.status(_('(no more unresolved files)\n'))
5862 5973 elif not unresolvedf:
5863 5974 ui.status(_('(no more unresolved files -- '
5864 5975 'run "hg resolve --all" to conclude)\n'))
5865 5976
5866 5977 return ret
5867 5978
5868 5979 @command('revert',
5869 5980 [('a', 'all', None, _('revert all changes when no arguments given')),
5870 5981 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5871 5982 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5872 5983 ('C', 'no-backup', None, _('do not save backup copies of files')),
5873 5984 ('i', 'interactive', None,
5874 5985 _('interactively select the changes (EXPERIMENTAL)')),
5875 5986 ] + walkopts + dryrunopts,
5876 5987 _('[OPTION]... [-r REV] [NAME]...'))
5877 5988 def revert(ui, repo, *pats, **opts):
5878 5989 """restore files to their checkout state
5879 5990
5880 5991 .. note::
5881 5992
5882 5993 To check out earlier revisions, you should use :hg:`update REV`.
5883 5994 To cancel an uncommitted merge (and lose your changes),
5884 5995 use :hg:`update --clean .`.
5885 5996
5886 5997 With no revision specified, revert the specified files or directories
5887 5998 to the contents they had in the parent of the working directory.
5888 5999 This restores the contents of files to an unmodified
5889 6000 state and unschedules adds, removes, copies, and renames. If the
5890 6001 working directory has two parents, you must explicitly specify a
5891 6002 revision.
5892 6003
5893 6004 Using the -r/--rev or -d/--date options, revert the given files or
5894 6005 directories to their states as of a specific revision. Because
5895 6006 revert does not change the working directory parents, this will
5896 6007 cause these files to appear modified. This can be helpful to "back
5897 6008 out" some or all of an earlier change. See :hg:`backout` for a
5898 6009 related method.
5899 6010
5900 6011 Modified files are saved with a .orig suffix before reverting.
5901 6012 To disable these backups, use --no-backup.
5902 6013
5903 6014 See :hg:`help dates` for a list of formats valid for -d/--date.
5904 6015
5905 6016 See :hg:`help backout` for a way to reverse the effect of an
5906 6017 earlier changeset.
5907 6018
5908 6019 Returns 0 on success.
5909 6020 """
5910 6021
5911 6022 if opts.get("date"):
5912 6023 if opts.get("rev"):
5913 6024 raise error.Abort(_("you can't specify a revision and a date"))
5914 6025 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5915 6026
5916 6027 parent, p2 = repo.dirstate.parents()
5917 6028 if not opts.get('rev') and p2 != nullid:
5918 6029 # revert after merge is a trap for new users (issue2915)
5919 6030 raise error.Abort(_('uncommitted merge with no revision specified'),
5920 6031 hint=_('use "hg update" or see "hg help revert"'))
5921 6032
5922 6033 ctx = scmutil.revsingle(repo, opts.get('rev'))
5923 6034
5924 6035 if (not (pats or opts.get('include') or opts.get('exclude') or
5925 6036 opts.get('all') or opts.get('interactive'))):
5926 6037 msg = _("no files or directories specified")
5927 6038 if p2 != nullid:
5928 6039 hint = _("uncommitted merge, use --all to discard all changes,"
5929 6040 " or 'hg update -C .' to abort the merge")
5930 6041 raise error.Abort(msg, hint=hint)
5931 6042 dirty = any(repo.status())
5932 6043 node = ctx.node()
5933 6044 if node != parent:
5934 6045 if dirty:
5935 6046 hint = _("uncommitted changes, use --all to discard all"
5936 6047 " changes, or 'hg update %s' to update") % ctx.rev()
5937 6048 else:
5938 6049 hint = _("use --all to revert all files,"
5939 6050 " or 'hg update %s' to update") % ctx.rev()
5940 6051 elif dirty:
5941 6052 hint = _("uncommitted changes, use --all to discard all changes")
5942 6053 else:
5943 6054 hint = _("use --all to revert all files")
5944 6055 raise error.Abort(msg, hint=hint)
5945 6056
5946 6057 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5947 6058
5948 6059 @command('rollback', dryrunopts +
5949 6060 [('f', 'force', False, _('ignore safety measures'))])
5950 6061 def rollback(ui, repo, **opts):
5951 6062 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5952 6063
5953 6064 Please use :hg:`commit --amend` instead of rollback to correct
5954 6065 mistakes in the last commit.
5955 6066
5956 6067 This command should be used with care. There is only one level of
5957 6068 rollback, and there is no way to undo a rollback. It will also
5958 6069 restore the dirstate at the time of the last transaction, losing
5959 6070 any dirstate changes since that time. This command does not alter
5960 6071 the working directory.
5961 6072
5962 6073 Transactions are used to encapsulate the effects of all commands
5963 6074 that create new changesets or propagate existing changesets into a
5964 6075 repository.
5965 6076
5966 6077 .. container:: verbose
5967 6078
5968 6079 For example, the following commands are transactional, and their
5969 6080 effects can be rolled back:
5970 6081
5971 6082 - commit
5972 6083 - import
5973 6084 - pull
5974 6085 - push (with this repository as the destination)
5975 6086 - unbundle
5976 6087
5977 6088 To avoid permanent data loss, rollback will refuse to rollback a
5978 6089 commit transaction if it isn't checked out. Use --force to
5979 6090 override this protection.
5980 6091
5981 6092 This command is not intended for use on public repositories. Once
5982 6093 changes are visible for pull by other users, rolling a transaction
5983 6094 back locally is ineffective (someone else may already have pulled
5984 6095 the changes). Furthermore, a race is possible with readers of the
5985 6096 repository; for example an in-progress pull from the repository
5986 6097 may fail if a rollback is performed.
5987 6098
5988 6099 Returns 0 on success, 1 if no rollback data is available.
5989 6100 """
5990 6101 return repo.rollback(dryrun=opts.get('dry_run'),
5991 6102 force=opts.get('force'))
5992 6103
5993 6104 @command('root', [])
5994 6105 def root(ui, repo):
5995 6106 """print the root (top) of the current working directory
5996 6107
5997 6108 Print the root directory of the current repository.
5998 6109
5999 6110 Returns 0 on success.
6000 6111 """
6001 6112 ui.write(repo.root + "\n")
6002 6113
6003 6114 @command('^serve',
6004 6115 [('A', 'accesslog', '', _('name of access log file to write to'),
6005 6116 _('FILE')),
6006 6117 ('d', 'daemon', None, _('run server in background')),
6007 6118 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6008 6119 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6009 6120 # use string type, then we can check if something was passed
6010 6121 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6011 6122 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6012 6123 _('ADDR')),
6013 6124 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6014 6125 _('PREFIX')),
6015 6126 ('n', 'name', '',
6016 6127 _('name to show in web pages (default: working directory)'), _('NAME')),
6017 6128 ('', 'web-conf', '',
6018 6129 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6019 6130 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6020 6131 _('FILE')),
6021 6132 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6022 6133 ('', 'stdio', None, _('for remote clients')),
6023 6134 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6024 6135 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6025 6136 ('', 'style', '', _('template style to use'), _('STYLE')),
6026 6137 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6027 6138 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6028 6139 _('[OPTION]...'),
6029 6140 optionalrepo=True)
6030 6141 def serve(ui, repo, **opts):
6031 6142 """start stand-alone webserver
6032 6143
6033 6144 Start a local HTTP repository browser and pull server. You can use
6034 6145 this for ad-hoc sharing and browsing of repositories. It is
6035 6146 recommended to use a real web server to serve a repository for
6036 6147 longer periods of time.
6037 6148
6038 6149 Please note that the server does not implement access control.
6039 6150 This means that, by default, anybody can read from the server and
6040 6151 nobody can write to it by default. Set the ``web.allow_push``
6041 6152 option to ``*`` to allow everybody to push to the server. You
6042 6153 should use a real web server if you need to authenticate users.
6043 6154
6044 6155 By default, the server logs accesses to stdout and errors to
6045 6156 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6046 6157 files.
6047 6158
6048 6159 To have the server choose a free port number to listen on, specify
6049 6160 a port number of 0; in this case, the server will print the port
6050 6161 number it uses.
6051 6162
6052 6163 Returns 0 on success.
6053 6164 """
6054 6165
6055 6166 if opts["stdio"] and opts["cmdserver"]:
6056 6167 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6057 6168
6058 6169 if opts["stdio"]:
6059 6170 if repo is None:
6060 6171 raise error.RepoError(_("there is no Mercurial repository here"
6061 6172 " (.hg not found)"))
6062 6173 s = sshserver.sshserver(ui, repo)
6063 6174 s.serve_forever()
6064 6175
6065 6176 if opts["cmdserver"]:
6066 6177 import commandserver
6067 6178 service = commandserver.createservice(ui, repo, opts)
6068 6179 else:
6069 6180 service = hgweb.createservice(ui, repo, opts)
6070 6181 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6071 6182
6072 6183 @command('^status|st',
6073 6184 [('A', 'all', None, _('show status of all files')),
6074 6185 ('m', 'modified', None, _('show only modified files')),
6075 6186 ('a', 'added', None, _('show only added files')),
6076 6187 ('r', 'removed', None, _('show only removed files')),
6077 6188 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6078 6189 ('c', 'clean', None, _('show only files without changes')),
6079 6190 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6080 6191 ('i', 'ignored', None, _('show only ignored files')),
6081 6192 ('n', 'no-status', None, _('hide status prefix')),
6082 6193 ('C', 'copies', None, _('show source of copied files')),
6083 6194 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6084 6195 ('', 'rev', [], _('show difference from revision'), _('REV')),
6085 6196 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6086 6197 ] + walkopts + subrepoopts + formatteropts,
6087 6198 _('[OPTION]... [FILE]...'),
6088 6199 inferrepo=True)
6089 6200 def status(ui, repo, *pats, **opts):
6090 6201 """show changed files in the working directory
6091 6202
6092 6203 Show status of files in the repository. If names are given, only
6093 6204 files that match are shown. Files that are clean or ignored or
6094 6205 the source of a copy/move operation, are not listed unless
6095 6206 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6096 6207 Unless options described with "show only ..." are given, the
6097 6208 options -mardu are used.
6098 6209
6099 6210 Option -q/--quiet hides untracked (unknown and ignored) files
6100 6211 unless explicitly requested with -u/--unknown or -i/--ignored.
6101 6212
6102 6213 .. note::
6103 6214
6104 6215 status may appear to disagree with diff if permissions have
6105 6216 changed or a merge has occurred. The standard diff format does
6106 6217 not report permission changes and diff only reports changes
6107 6218 relative to one merge parent.
6108 6219
6109 6220 If one revision is given, it is used as the base revision.
6110 6221 If two revisions are given, the differences between them are
6111 6222 shown. The --change option can also be used as a shortcut to list
6112 6223 the changed files of a revision from its first parent.
6113 6224
6114 6225 The codes used to show the status of files are::
6115 6226
6116 6227 M = modified
6117 6228 A = added
6118 6229 R = removed
6119 6230 C = clean
6120 6231 ! = missing (deleted by non-hg command, but still tracked)
6121 6232 ? = not tracked
6122 6233 I = ignored
6123 6234 = origin of the previous file (with --copies)
6124 6235
6125 6236 .. container:: verbose
6126 6237
6127 6238 Examples:
6128 6239
6129 6240 - show changes in the working directory relative to a
6130 6241 changeset::
6131 6242
6132 6243 hg status --rev 9353
6133 6244
6134 6245 - show changes in the working directory relative to the
6135 6246 current directory (see :hg:`help patterns` for more information)::
6136 6247
6137 6248 hg status re:
6138 6249
6139 6250 - show all changes including copies in an existing changeset::
6140 6251
6141 6252 hg status --copies --change 9353
6142 6253
6143 6254 - get a NUL separated list of added files, suitable for xargs::
6144 6255
6145 6256 hg status -an0
6146 6257
6147 6258 Returns 0 on success.
6148 6259 """
6149 6260
6150 6261 revs = opts.get('rev')
6151 6262 change = opts.get('change')
6152 6263
6153 6264 if revs and change:
6154 6265 msg = _('cannot specify --rev and --change at the same time')
6155 6266 raise error.Abort(msg)
6156 6267 elif change:
6157 6268 node2 = scmutil.revsingle(repo, change, None).node()
6158 6269 node1 = repo[node2].p1().node()
6159 6270 else:
6160 6271 node1, node2 = scmutil.revpair(repo, revs)
6161 6272
6162 6273 if pats:
6163 6274 cwd = repo.getcwd()
6164 6275 else:
6165 6276 cwd = ''
6166 6277
6167 6278 if opts.get('print0'):
6168 6279 end = '\0'
6169 6280 else:
6170 6281 end = '\n'
6171 6282 copy = {}
6172 6283 states = 'modified added removed deleted unknown ignored clean'.split()
6173 6284 show = [k for k in states if opts.get(k)]
6174 6285 if opts.get('all'):
6175 6286 show += ui.quiet and (states[:4] + ['clean']) or states
6176 6287 if not show:
6177 6288 if ui.quiet:
6178 6289 show = states[:4]
6179 6290 else:
6180 6291 show = states[:5]
6181 6292
6182 6293 m = scmutil.match(repo[node2], pats, opts)
6183 6294 stat = repo.status(node1, node2, m,
6184 6295 'ignored' in show, 'clean' in show, 'unknown' in show,
6185 6296 opts.get('subrepos'))
6186 6297 changestates = zip(states, 'MAR!?IC', stat)
6187 6298
6188 6299 if (opts.get('all') or opts.get('copies')
6189 6300 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6190 6301 copy = copies.pathcopies(repo[node1], repo[node2], m)
6191 6302
6192 6303 fm = ui.formatter('status', opts)
6193 6304 fmt = '%s' + end
6194 6305 showchar = not opts.get('no_status')
6195 6306
6196 6307 for state, char, files in changestates:
6197 6308 if state in show:
6198 6309 label = 'status.' + state
6199 6310 for f in files:
6200 6311 fm.startitem()
6201 6312 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6202 6313 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6203 6314 if f in copy:
6204 6315 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6205 6316 label='status.copied')
6206 6317 fm.end()
6207 6318
6208 6319 @command('^summary|sum',
6209 6320 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6210 6321 def summary(ui, repo, **opts):
6211 6322 """summarize working directory state
6212 6323
6213 6324 This generates a brief summary of the working directory state,
6214 6325 including parents, branch, commit status, phase and available updates.
6215 6326
6216 6327 With the --remote option, this will check the default paths for
6217 6328 incoming and outgoing changes. This can be time-consuming.
6218 6329
6219 6330 Returns 0 on success.
6220 6331 """
6221 6332
6222 6333 ctx = repo[None]
6223 6334 parents = ctx.parents()
6224 6335 pnode = parents[0].node()
6225 6336 marks = []
6226 6337
6227 6338 for p in parents:
6228 6339 # label with log.changeset (instead of log.parent) since this
6229 6340 # shows a working directory parent *changeset*:
6230 6341 # i18n: column positioning for "hg summary"
6231 6342 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6232 6343 label='log.changeset changeset.%s' % p.phasestr())
6233 6344 ui.write(' '.join(p.tags()), label='log.tag')
6234 6345 if p.bookmarks():
6235 6346 marks.extend(p.bookmarks())
6236 6347 if p.rev() == -1:
6237 6348 if not len(repo):
6238 6349 ui.write(_(' (empty repository)'))
6239 6350 else:
6240 6351 ui.write(_(' (no revision checked out)'))
6241 6352 ui.write('\n')
6242 6353 if p.description():
6243 6354 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6244 6355 label='log.summary')
6245 6356
6246 6357 branch = ctx.branch()
6247 6358 bheads = repo.branchheads(branch)
6248 6359 # i18n: column positioning for "hg summary"
6249 6360 m = _('branch: %s\n') % branch
6250 6361 if branch != 'default':
6251 6362 ui.write(m, label='log.branch')
6252 6363 else:
6253 6364 ui.status(m, label='log.branch')
6254 6365
6255 6366 if marks:
6256 6367 active = repo._activebookmark
6257 6368 # i18n: column positioning for "hg summary"
6258 6369 ui.write(_('bookmarks:'), label='log.bookmark')
6259 6370 if active is not None:
6260 6371 if active in marks:
6261 6372 ui.write(' *' + active, label=activebookmarklabel)
6262 6373 marks.remove(active)
6263 6374 else:
6264 6375 ui.write(' [%s]' % active, label=activebookmarklabel)
6265 6376 for m in marks:
6266 6377 ui.write(' ' + m, label='log.bookmark')
6267 6378 ui.write('\n', label='log.bookmark')
6268 6379
6269 6380 status = repo.status(unknown=True)
6270 6381
6271 6382 c = repo.dirstate.copies()
6272 6383 copied, renamed = [], []
6273 6384 for d, s in c.iteritems():
6274 6385 if s in status.removed:
6275 6386 status.removed.remove(s)
6276 6387 renamed.append(d)
6277 6388 else:
6278 6389 copied.append(d)
6279 6390 if d in status.added:
6280 6391 status.added.remove(d)
6281 6392
6282 6393 try:
6283 6394 ms = mergemod.mergestate.read(repo)
6284 6395 except error.UnsupportedMergeRecords as e:
6285 6396 s = ' '.join(e.recordtypes)
6286 6397 ui.warn(
6287 6398 _('warning: merge state has unsupported record types: %s\n') % s)
6288 6399 unresolved = 0
6289 6400 else:
6290 6401 unresolved = [f for f in ms if ms[f] == 'u']
6291 6402
6292 6403 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6293 6404
6294 6405 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6295 6406 (ui.label(_('%d added'), 'status.added'), status.added),
6296 6407 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6297 6408 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6298 6409 (ui.label(_('%d copied'), 'status.copied'), copied),
6299 6410 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6300 6411 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6301 6412 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6302 6413 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6303 6414 t = []
6304 6415 for l, s in labels:
6305 6416 if s:
6306 6417 t.append(l % len(s))
6307 6418
6308 6419 t = ', '.join(t)
6309 6420 cleanworkdir = False
6310 6421
6311 6422 if repo.vfs.exists('graftstate'):
6312 6423 t += _(' (graft in progress)')
6313 6424 if repo.vfs.exists('updatestate'):
6314 6425 t += _(' (interrupted update)')
6315 6426 elif len(parents) > 1:
6316 6427 t += _(' (merge)')
6317 6428 elif branch != parents[0].branch():
6318 6429 t += _(' (new branch)')
6319 6430 elif (parents[0].closesbranch() and
6320 6431 pnode in repo.branchheads(branch, closed=True)):
6321 6432 t += _(' (head closed)')
6322 6433 elif not (status.modified or status.added or status.removed or renamed or
6323 6434 copied or subs):
6324 6435 t += _(' (clean)')
6325 6436 cleanworkdir = True
6326 6437 elif pnode not in bheads:
6327 6438 t += _(' (new branch head)')
6328 6439
6329 6440 if parents:
6330 6441 pendingphase = max(p.phase() for p in parents)
6331 6442 else:
6332 6443 pendingphase = phases.public
6333 6444
6334 6445 if pendingphase > phases.newcommitphase(ui):
6335 6446 t += ' (%s)' % phases.phasenames[pendingphase]
6336 6447
6337 6448 if cleanworkdir:
6338 6449 # i18n: column positioning for "hg summary"
6339 6450 ui.status(_('commit: %s\n') % t.strip())
6340 6451 else:
6341 6452 # i18n: column positioning for "hg summary"
6342 6453 ui.write(_('commit: %s\n') % t.strip())
6343 6454
6344 6455 # all ancestors of branch heads - all ancestors of parent = new csets
6345 6456 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6346 6457 bheads))
6347 6458
6348 6459 if new == 0:
6349 6460 # i18n: column positioning for "hg summary"
6350 6461 ui.status(_('update: (current)\n'))
6351 6462 elif pnode not in bheads:
6352 6463 # i18n: column positioning for "hg summary"
6353 6464 ui.write(_('update: %d new changesets (update)\n') % new)
6354 6465 else:
6355 6466 # i18n: column positioning for "hg summary"
6356 6467 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6357 6468 (new, len(bheads)))
6358 6469
6359 6470 t = []
6360 6471 draft = len(repo.revs('draft()'))
6361 6472 if draft:
6362 6473 t.append(_('%d draft') % draft)
6363 6474 secret = len(repo.revs('secret()'))
6364 6475 if secret:
6365 6476 t.append(_('%d secret') % secret)
6366 6477
6367 6478 if draft or secret:
6368 6479 ui.status(_('phases: %s\n') % ', '.join(t))
6369 6480
6370 6481 cmdutil.summaryhooks(ui, repo)
6371 6482
6372 6483 if opts.get('remote'):
6373 6484 needsincoming, needsoutgoing = True, True
6374 6485 else:
6375 6486 needsincoming, needsoutgoing = False, False
6376 6487 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6377 6488 if i:
6378 6489 needsincoming = True
6379 6490 if o:
6380 6491 needsoutgoing = True
6381 6492 if not needsincoming and not needsoutgoing:
6382 6493 return
6383 6494
6384 6495 def getincoming():
6385 6496 source, branches = hg.parseurl(ui.expandpath('default'))
6386 6497 sbranch = branches[0]
6387 6498 try:
6388 6499 other = hg.peer(repo, {}, source)
6389 6500 except error.RepoError:
6390 6501 if opts.get('remote'):
6391 6502 raise
6392 6503 return source, sbranch, None, None, None
6393 6504 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6394 6505 if revs:
6395 6506 revs = [other.lookup(rev) for rev in revs]
6396 6507 ui.debug('comparing with %s\n' % util.hidepassword(source))
6397 6508 repo.ui.pushbuffer()
6398 6509 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6399 6510 repo.ui.popbuffer()
6400 6511 return source, sbranch, other, commoninc, commoninc[1]
6401 6512
6402 6513 if needsincoming:
6403 6514 source, sbranch, sother, commoninc, incoming = getincoming()
6404 6515 else:
6405 6516 source = sbranch = sother = commoninc = incoming = None
6406 6517
6407 6518 def getoutgoing():
6408 6519 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6409 6520 dbranch = branches[0]
6410 6521 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6411 6522 if source != dest:
6412 6523 try:
6413 6524 dother = hg.peer(repo, {}, dest)
6414 6525 except error.RepoError:
6415 6526 if opts.get('remote'):
6416 6527 raise
6417 6528 return dest, dbranch, None, None
6418 6529 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6419 6530 elif sother is None:
6420 6531 # there is no explicit destination peer, but source one is invalid
6421 6532 return dest, dbranch, None, None
6422 6533 else:
6423 6534 dother = sother
6424 6535 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6425 6536 common = None
6426 6537 else:
6427 6538 common = commoninc
6428 6539 if revs:
6429 6540 revs = [repo.lookup(rev) for rev in revs]
6430 6541 repo.ui.pushbuffer()
6431 6542 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6432 6543 commoninc=common)
6433 6544 repo.ui.popbuffer()
6434 6545 return dest, dbranch, dother, outgoing
6435 6546
6436 6547 if needsoutgoing:
6437 6548 dest, dbranch, dother, outgoing = getoutgoing()
6438 6549 else:
6439 6550 dest = dbranch = dother = outgoing = None
6440 6551
6441 6552 if opts.get('remote'):
6442 6553 t = []
6443 6554 if incoming:
6444 6555 t.append(_('1 or more incoming'))
6445 6556 o = outgoing.missing
6446 6557 if o:
6447 6558 t.append(_('%d outgoing') % len(o))
6448 6559 other = dother or sother
6449 6560 if 'bookmarks' in other.listkeys('namespaces'):
6450 6561 counts = bookmarks.summary(repo, other)
6451 6562 if counts[0] > 0:
6452 6563 t.append(_('%d incoming bookmarks') % counts[0])
6453 6564 if counts[1] > 0:
6454 6565 t.append(_('%d outgoing bookmarks') % counts[1])
6455 6566
6456 6567 if t:
6457 6568 # i18n: column positioning for "hg summary"
6458 6569 ui.write(_('remote: %s\n') % (', '.join(t)))
6459 6570 else:
6460 6571 # i18n: column positioning for "hg summary"
6461 6572 ui.status(_('remote: (synced)\n'))
6462 6573
6463 6574 cmdutil.summaryremotehooks(ui, repo, opts,
6464 6575 ((source, sbranch, sother, commoninc),
6465 6576 (dest, dbranch, dother, outgoing)))
6466 6577
6467 6578 @command('tag',
6468 6579 [('f', 'force', None, _('force tag')),
6469 6580 ('l', 'local', None, _('make the tag local')),
6470 6581 ('r', 'rev', '', _('revision to tag'), _('REV')),
6471 6582 ('', 'remove', None, _('remove a tag')),
6472 6583 # -l/--local is already there, commitopts cannot be used
6473 6584 ('e', 'edit', None, _('invoke editor on commit messages')),
6474 6585 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6475 6586 ] + commitopts2,
6476 6587 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6477 6588 def tag(ui, repo, name1, *names, **opts):
6478 6589 """add one or more tags for the current or given revision
6479 6590
6480 6591 Name a particular revision using <name>.
6481 6592
6482 6593 Tags are used to name particular revisions of the repository and are
6483 6594 very useful to compare different revisions, to go back to significant
6484 6595 earlier versions or to mark branch points as releases, etc. Changing
6485 6596 an existing tag is normally disallowed; use -f/--force to override.
6486 6597
6487 6598 If no revision is given, the parent of the working directory is
6488 6599 used.
6489 6600
6490 6601 To facilitate version control, distribution, and merging of tags,
6491 6602 they are stored as a file named ".hgtags" which is managed similarly
6492 6603 to other project files and can be hand-edited if necessary. This
6493 6604 also means that tagging creates a new commit. The file
6494 6605 ".hg/localtags" is used for local tags (not shared among
6495 6606 repositories).
6496 6607
6497 6608 Tag commits are usually made at the head of a branch. If the parent
6498 6609 of the working directory is not a branch head, :hg:`tag` aborts; use
6499 6610 -f/--force to force the tag commit to be based on a non-head
6500 6611 changeset.
6501 6612
6502 6613 See :hg:`help dates` for a list of formats valid for -d/--date.
6503 6614
6504 6615 Since tag names have priority over branch names during revision
6505 6616 lookup, using an existing branch name as a tag name is discouraged.
6506 6617
6507 6618 Returns 0 on success.
6508 6619 """
6509 6620 wlock = lock = None
6510 6621 try:
6511 6622 wlock = repo.wlock()
6512 6623 lock = repo.lock()
6513 6624 rev_ = "."
6514 6625 names = [t.strip() for t in (name1,) + names]
6515 6626 if len(names) != len(set(names)):
6516 6627 raise error.Abort(_('tag names must be unique'))
6517 6628 for n in names:
6518 6629 scmutil.checknewlabel(repo, n, 'tag')
6519 6630 if not n:
6520 6631 raise error.Abort(_('tag names cannot consist entirely of '
6521 6632 'whitespace'))
6522 6633 if opts.get('rev') and opts.get('remove'):
6523 6634 raise error.Abort(_("--rev and --remove are incompatible"))
6524 6635 if opts.get('rev'):
6525 6636 rev_ = opts['rev']
6526 6637 message = opts.get('message')
6527 6638 if opts.get('remove'):
6528 6639 if opts.get('local'):
6529 6640 expectedtype = 'local'
6530 6641 else:
6531 6642 expectedtype = 'global'
6532 6643
6533 6644 for n in names:
6534 6645 if not repo.tagtype(n):
6535 6646 raise error.Abort(_("tag '%s' does not exist") % n)
6536 6647 if repo.tagtype(n) != expectedtype:
6537 6648 if expectedtype == 'global':
6538 6649 raise error.Abort(_("tag '%s' is not a global tag") % n)
6539 6650 else:
6540 6651 raise error.Abort(_("tag '%s' is not a local tag") % n)
6541 6652 rev_ = 'null'
6542 6653 if not message:
6543 6654 # we don't translate commit messages
6544 6655 message = 'Removed tag %s' % ', '.join(names)
6545 6656 elif not opts.get('force'):
6546 6657 for n in names:
6547 6658 if n in repo.tags():
6548 6659 raise error.Abort(_("tag '%s' already exists "
6549 6660 "(use -f to force)") % n)
6550 6661 if not opts.get('local'):
6551 6662 p1, p2 = repo.dirstate.parents()
6552 6663 if p2 != nullid:
6553 6664 raise error.Abort(_('uncommitted merge'))
6554 6665 bheads = repo.branchheads()
6555 6666 if not opts.get('force') and bheads and p1 not in bheads:
6556 6667 raise error.Abort(_('not at a branch head (use -f to force)'))
6557 6668 r = scmutil.revsingle(repo, rev_).node()
6558 6669
6559 6670 if not message:
6560 6671 # we don't translate commit messages
6561 6672 message = ('Added tag %s for changeset %s' %
6562 6673 (', '.join(names), short(r)))
6563 6674
6564 6675 date = opts.get('date')
6565 6676 if date:
6566 6677 date = util.parsedate(date)
6567 6678
6568 6679 if opts.get('remove'):
6569 6680 editform = 'tag.remove'
6570 6681 else:
6571 6682 editform = 'tag.add'
6572 6683 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6573 6684
6574 6685 # don't allow tagging the null rev
6575 6686 if (not opts.get('remove') and
6576 6687 scmutil.revsingle(repo, rev_).rev() == nullrev):
6577 6688 raise error.Abort(_("cannot tag null revision"))
6578 6689
6579 6690 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6580 6691 editor=editor)
6581 6692 finally:
6582 6693 release(lock, wlock)
6583 6694
6584 6695 @command('tags', formatteropts, '')
6585 6696 def tags(ui, repo, **opts):
6586 6697 """list repository tags
6587 6698
6588 6699 This lists both regular and local tags. When the -v/--verbose
6589 6700 switch is used, a third column "local" is printed for local tags.
6590 6701
6591 6702 Returns 0 on success.
6592 6703 """
6593 6704
6594 6705 fm = ui.formatter('tags', opts)
6595 6706 hexfunc = fm.hexfunc
6596 6707 tagtype = ""
6597 6708
6598 6709 for t, n in reversed(repo.tagslist()):
6599 6710 hn = hexfunc(n)
6600 6711 label = 'tags.normal'
6601 6712 tagtype = ''
6602 6713 if repo.tagtype(t) == 'local':
6603 6714 label = 'tags.local'
6604 6715 tagtype = 'local'
6605 6716
6606 6717 fm.startitem()
6607 6718 fm.write('tag', '%s', t, label=label)
6608 6719 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6609 6720 fm.condwrite(not ui.quiet, 'rev node', fmt,
6610 6721 repo.changelog.rev(n), hn, label=label)
6611 6722 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6612 6723 tagtype, label=label)
6613 6724 fm.plain('\n')
6614 6725 fm.end()
6615 6726
6616 6727 @command('tip',
6617 6728 [('p', 'patch', None, _('show patch')),
6618 6729 ('g', 'git', None, _('use git extended diff format')),
6619 6730 ] + templateopts,
6620 6731 _('[-p] [-g]'))
6621 6732 def tip(ui, repo, **opts):
6622 6733 """show the tip revision (DEPRECATED)
6623 6734
6624 6735 The tip revision (usually just called the tip) is the changeset
6625 6736 most recently added to the repository (and therefore the most
6626 6737 recently changed head).
6627 6738
6628 6739 If you have just made a commit, that commit will be the tip. If
6629 6740 you have just pulled changes from another repository, the tip of
6630 6741 that repository becomes the current tip. The "tip" tag is special
6631 6742 and cannot be renamed or assigned to a different changeset.
6632 6743
6633 6744 This command is deprecated, please use :hg:`heads` instead.
6634 6745
6635 6746 Returns 0 on success.
6636 6747 """
6637 6748 displayer = cmdutil.show_changeset(ui, repo, opts)
6638 6749 displayer.show(repo['tip'])
6639 6750 displayer.close()
6640 6751
6641 6752 @command('unbundle',
6642 6753 [('u', 'update', None,
6643 6754 _('update to new branch head if changesets were unbundled'))],
6644 6755 _('[-u] FILE...'))
6645 6756 def unbundle(ui, repo, fname1, *fnames, **opts):
6646 6757 """apply one or more changegroup files
6647 6758
6648 6759 Apply one or more compressed changegroup files generated by the
6649 6760 bundle command.
6650 6761
6651 6762 Returns 0 on success, 1 if an update has unresolved files.
6652 6763 """
6653 6764 fnames = (fname1,) + fnames
6654 6765
6655 6766 lock = repo.lock()
6656 6767 try:
6657 6768 for fname in fnames:
6658 6769 f = hg.openpath(ui, fname)
6659 6770 gen = exchange.readbundle(ui, f, fname)
6660 6771 if isinstance(gen, bundle2.unbundle20):
6661 6772 tr = repo.transaction('unbundle')
6662 6773 try:
6663 6774 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6664 6775 url='bundle:' + fname)
6665 6776 tr.close()
6666 6777 except error.BundleUnknownFeatureError as exc:
6667 6778 raise error.Abort(_('%s: unknown bundle feature, %s')
6668 6779 % (fname, exc),
6669 6780 hint=_("see https://mercurial-scm.org/"
6670 6781 "wiki/BundleFeature for more "
6671 6782 "information"))
6672 6783 finally:
6673 6784 if tr:
6674 6785 tr.release()
6675 6786 changes = [r.get('return', 0)
6676 6787 for r in op.records['changegroup']]
6677 6788 modheads = changegroup.combineresults(changes)
6678 6789 elif isinstance(gen, streamclone.streamcloneapplier):
6679 6790 raise error.Abort(
6680 6791 _('packed bundles cannot be applied with '
6681 6792 '"hg unbundle"'),
6682 6793 hint=_('use "hg debugapplystreamclonebundle"'))
6683 6794 else:
6684 6795 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6685 6796 finally:
6686 6797 lock.release()
6687 6798
6688 6799 return postincoming(ui, repo, modheads, opts.get('update'), None)
6689 6800
6690 6801 @command('^update|up|checkout|co',
6691 6802 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6692 6803 ('c', 'check', None,
6693 6804 _('update across branches if no uncommitted changes')),
6694 6805 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6695 6806 ('r', 'rev', '', _('revision'), _('REV'))
6696 6807 ] + mergetoolopts,
6697 6808 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6698 6809 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6699 6810 tool=None):
6700 6811 """update working directory (or switch revisions)
6701 6812
6702 6813 Update the repository's working directory to the specified
6703 6814 changeset. If no changeset is specified, update to the tip of the
6704 6815 current named branch and move the active bookmark (see :hg:`help
6705 6816 bookmarks`).
6706 6817
6707 6818 Update sets the working directory's parent revision to the specified
6708 6819 changeset (see :hg:`help parents`).
6709 6820
6710 6821 If the changeset is not a descendant or ancestor of the working
6711 6822 directory's parent, the update is aborted. With the -c/--check
6712 6823 option, the working directory is checked for uncommitted changes; if
6713 6824 none are found, the working directory is updated to the specified
6714 6825 changeset.
6715 6826
6716 6827 .. container:: verbose
6717 6828
6718 6829 The following rules apply when the working directory contains
6719 6830 uncommitted changes:
6720 6831
6721 6832 1. If neither -c/--check nor -C/--clean is specified, and if
6722 6833 the requested changeset is an ancestor or descendant of
6723 6834 the working directory's parent, the uncommitted changes
6724 6835 are merged into the requested changeset and the merged
6725 6836 result is left uncommitted. If the requested changeset is
6726 6837 not an ancestor or descendant (that is, it is on another
6727 6838 branch), the update is aborted and the uncommitted changes
6728 6839 are preserved.
6729 6840
6730 6841 2. With the -c/--check option, the update is aborted and the
6731 6842 uncommitted changes are preserved.
6732 6843
6733 6844 3. With the -C/--clean option, uncommitted changes are discarded and
6734 6845 the working directory is updated to the requested changeset.
6735 6846
6736 6847 To cancel an uncommitted merge (and lose your changes), use
6737 6848 :hg:`update --clean .`.
6738 6849
6739 6850 Use null as the changeset to remove the working directory (like
6740 6851 :hg:`clone -U`).
6741 6852
6742 6853 If you want to revert just one file to an older revision, use
6743 6854 :hg:`revert [-r REV] NAME`.
6744 6855
6745 6856 See :hg:`help dates` for a list of formats valid for -d/--date.
6746 6857
6747 6858 Returns 0 on success, 1 if there are unresolved files.
6748 6859 """
6749 6860 movemarkfrom = None
6750 6861 if rev and node:
6751 6862 raise error.Abort(_("please specify just one revision"))
6752 6863
6753 6864 if rev is None or rev == '':
6754 6865 rev = node
6755 6866
6756 6867 wlock = repo.wlock()
6757 6868 try:
6758 6869 cmdutil.clearunfinished(repo)
6759 6870
6760 6871 if date:
6761 6872 if rev is not None:
6762 6873 raise error.Abort(_("you can't specify a revision and a date"))
6763 6874 rev = cmdutil.finddate(ui, repo, date)
6764 6875
6765 6876 # if we defined a bookmark, we have to remember the original name
6766 6877 brev = rev
6767 6878 rev = scmutil.revsingle(repo, rev, rev).rev()
6768 6879
6769 6880 if check and clean:
6770 6881 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6771 6882 )
6772 6883
6773 6884 if check:
6774 6885 cmdutil.bailifchanged(repo, merge=False)
6775 6886 if rev is None:
6776 6887 updata = destutil.destupdate(repo, clean=clean, check=check)
6777 6888 rev, movemarkfrom, brev = updata
6778 6889
6779 6890 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6780 6891
6781 6892 if clean:
6782 6893 ret = hg.clean(repo, rev)
6783 6894 else:
6784 6895 ret = hg.update(repo, rev)
6785 6896
6786 6897 if not ret and movemarkfrom:
6787 6898 if movemarkfrom == repo['.'].node():
6788 6899 pass # no-op update
6789 6900 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6790 6901 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6791 6902 else:
6792 6903 # this can happen with a non-linear update
6793 6904 ui.status(_("(leaving bookmark %s)\n") %
6794 6905 repo._activebookmark)
6795 6906 bookmarks.deactivate(repo)
6796 6907 elif brev in repo._bookmarks:
6797 6908 bookmarks.activate(repo, brev)
6798 6909 ui.status(_("(activating bookmark %s)\n") % brev)
6799 6910 elif brev:
6800 6911 if repo._activebookmark:
6801 6912 ui.status(_("(leaving bookmark %s)\n") %
6802 6913 repo._activebookmark)
6803 6914 bookmarks.deactivate(repo)
6804 6915 finally:
6805 6916 wlock.release()
6806 6917
6807 6918 return ret
6808 6919
6809 6920 @command('verify', [])
6810 6921 def verify(ui, repo):
6811 6922 """verify the integrity of the repository
6812 6923
6813 6924 Verify the integrity of the current repository.
6814 6925
6815 6926 This will perform an extensive check of the repository's
6816 6927 integrity, validating the hashes and checksums of each entry in
6817 6928 the changelog, manifest, and tracked files, as well as the
6818 6929 integrity of their crosslinks and indices.
6819 6930
6820 6931 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6821 6932 for more information about recovery from corruption of the
6822 6933 repository.
6823 6934
6824 6935 Returns 0 on success, 1 if errors are encountered.
6825 6936 """
6826 6937 return hg.verify(repo)
6827 6938
6828 6939 @command('version', [], norepo=True)
6829 6940 def version_(ui):
6830 6941 """output version and copyright information"""
6831 6942 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6832 6943 % util.version())
6833 6944 ui.status(_(
6834 6945 "(see https://mercurial-scm.org for more information)\n"
6835 6946 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6836 6947 "This is free software; see the source for copying conditions. "
6837 6948 "There is NO\nwarranty; "
6838 6949 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6839 6950 ))
6840 6951
6841 6952 ui.note(_("\nEnabled extensions:\n\n"))
6842 6953 if ui.verbose:
6843 6954 # format names and versions into columns
6844 6955 names = []
6845 6956 vers = []
6846 6957 for name, module in extensions.extensions():
6847 6958 names.append(name)
6848 6959 vers.append(extensions.moduleversion(module))
6849 6960 if names:
6850 6961 maxnamelen = max(len(n) for n in names)
6851 6962 for i, name in enumerate(names):
6852 6963 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,348 +1,350 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcheckstate
76 76 debugcommands
77 77 debugcomplete
78 78 debugconfig
79 79 debugcreatestreamclonebundle
80 80 debugdag
81 81 debugdata
82 82 debugdate
83 debugdeltachain
83 84 debugdirstate
84 85 debugdiscovery
85 86 debugextensions
86 87 debugfileset
87 88 debugfsinfo
88 89 debuggetbundle
89 90 debugignore
90 91 debugindex
91 92 debugindexdot
92 93 debuginstall
93 94 debugknown
94 95 debuglabelcomplete
95 96 debuglocks
96 97 debugmergestate
97 98 debugnamecomplete
98 99 debugobsolete
99 100 debugpathcomplete
100 101 debugpushkey
101 102 debugpvec
102 103 debugrebuilddirstate
103 104 debugrebuildfncache
104 105 debugrename
105 106 debugrevlog
106 107 debugrevspec
107 108 debugsetparents
108 109 debugsub
109 110 debugsuccessorssets
110 111 debugwalk
111 112 debugwireargs
112 113
113 114 Do not show the alias of a debug command if there are other candidates
114 115 (this should hide rawcommit)
115 116 $ hg debugcomplete r
116 117 recover
117 118 remove
118 119 rename
119 120 resolve
120 121 revert
121 122 rollback
122 123 root
123 124 Show the alias of a debug command if there are no other candidates
124 125 $ hg debugcomplete rawc
125 126
126 127
127 128 Show the global options
128 129 $ hg debugcomplete --options | sort
129 130 --config
130 131 --cwd
131 132 --debug
132 133 --debugger
133 134 --encoding
134 135 --encodingmode
135 136 --help
136 137 --hidden
137 138 --noninteractive
138 139 --profile
139 140 --quiet
140 141 --repository
141 142 --time
142 143 --traceback
143 144 --verbose
144 145 --version
145 146 -R
146 147 -h
147 148 -q
148 149 -v
149 150 -y
150 151
151 152 Show the options for the "serve" command
152 153 $ hg debugcomplete --options serve | sort
153 154 --accesslog
154 155 --address
155 156 --certificate
156 157 --cmdserver
157 158 --config
158 159 --cwd
159 160 --daemon
160 161 --daemon-pipefds
161 162 --debug
162 163 --debugger
163 164 --encoding
164 165 --encodingmode
165 166 --errorlog
166 167 --help
167 168 --hidden
168 169 --ipv6
169 170 --name
170 171 --noninteractive
171 172 --pid-file
172 173 --port
173 174 --prefix
174 175 --profile
175 176 --quiet
176 177 --repository
177 178 --stdio
178 179 --style
179 180 --templates
180 181 --time
181 182 --traceback
182 183 --verbose
183 184 --version
184 185 --web-conf
185 186 -6
186 187 -A
187 188 -E
188 189 -R
189 190 -a
190 191 -d
191 192 -h
192 193 -n
193 194 -p
194 195 -q
195 196 -t
196 197 -v
197 198 -y
198 199
199 200 Show an error if we use --options with an ambiguous abbreviation
200 201 $ hg debugcomplete --options s
201 202 hg: command 's' is ambiguous:
202 203 serve showconfig status summary
203 204 [255]
204 205
205 206 Show all commands + options
206 207 $ hg debugcommands
207 208 add: include, exclude, subrepos, dry-run
208 209 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
209 210 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
210 211 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
211 212 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
212 213 export: output, switch-parent, rev, text, git, nodates
213 214 forget: include, exclude
214 215 init: ssh, remotecmd, insecure
215 216 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
216 217 merge: force, rev, preview, tool
217 218 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
218 219 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
219 220 remove: after, force, subrepos, include, exclude
220 221 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
221 222 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
222 223 summary: remote
223 224 update: clean, check, date, rev, tool
224 225 addremove: similarity, subrepos, include, exclude, dry-run
225 226 archive: no-decode, prefix, rev, type, subrepos, include, exclude
226 227 backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
227 228 bisect: reset, good, bad, skip, extend, command, noupdate
228 229 bookmarks: force, rev, delete, rename, inactive, template
229 230 branch: force, clean
230 231 branches: active, closed, template
231 232 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
232 233 cat: output, rev, decode, include, exclude
233 234 config: untrusted, edit, local, global
234 235 copy: after, force, include, exclude, dry-run
235 236 debugancestor:
236 237 debugapplystreamclonebundle:
237 238 debugbuilddag: mergeable-file, overwritten-file, new-file
238 239 debugbundle: all
239 240 debugcheckstate:
240 241 debugcommands:
241 242 debugcomplete: options
242 243 debugcreatestreamclonebundle:
243 244 debugdag: tags, branches, dots, spaces
244 245 debugdata: changelog, manifest, dir
245 246 debugdate: extended
247 debugdeltachain: changelog, manifest, dir, template
246 248 debugdirstate: nodates, datesort
247 249 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
248 250 debugextensions: template
249 251 debugfileset: rev
250 252 debugfsinfo:
251 253 debuggetbundle: head, common, type
252 254 debugignore:
253 255 debugindex: changelog, manifest, dir, format
254 256 debugindexdot: changelog, manifest, dir
255 257 debuginstall:
256 258 debugknown:
257 259 debuglabelcomplete:
258 260 debuglocks: force-lock, force-wlock
259 261 debugmergestate:
260 262 debugnamecomplete:
261 263 debugobsolete: flags, record-parents, rev, date, user
262 264 debugpathcomplete: full, normal, added, removed
263 265 debugpushkey:
264 266 debugpvec:
265 267 debugrebuilddirstate: rev, minimal
266 268 debugrebuildfncache:
267 269 debugrename: rev
268 270 debugrevlog: changelog, manifest, dir, dump
269 271 debugrevspec: optimize
270 272 debugsetparents:
271 273 debugsub: rev
272 274 debugsuccessorssets:
273 275 debugwalk: include, exclude
274 276 debugwireargs: three, four, five, ssh, remotecmd, insecure
275 277 files: rev, print0, include, exclude, template, subrepos
276 278 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
277 279 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
278 280 heads: rev, topo, active, closed, style, template
279 281 help: extension, command, keyword
280 282 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
281 283 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
282 284 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
283 285 locate: rev, print0, fullpath, include, exclude
284 286 manifest: rev, all, template
285 287 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
286 288 parents: rev, style, template
287 289 paths:
288 290 phase: public, draft, secret, force, rev
289 291 recover:
290 292 rename: after, force, include, exclude, dry-run
291 293 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
292 294 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
293 295 rollback: dry-run, force
294 296 root:
295 297 tag: force, local, rev, remove, edit, message, date, user
296 298 tags: template
297 299 tip: patch, git, style, template
298 300 unbundle: update
299 301 verify:
300 302 version:
301 303
302 304 $ hg init a
303 305 $ cd a
304 306 $ echo fee > fee
305 307 $ hg ci -q -Amfee
306 308 $ hg tag fee
307 309 $ mkdir fie
308 310 $ echo dead > fie/dead
309 311 $ echo live > fie/live
310 312 $ hg bookmark fo
311 313 $ hg branch -q fie
312 314 $ hg ci -q -Amfie
313 315 $ echo fo > fo
314 316 $ hg branch -qf default
315 317 $ hg ci -q -Amfo
316 318 $ echo Fum > Fum
317 319 $ hg ci -q -AmFum
318 320 $ hg bookmark Fum
319 321
320 322 Test debugpathcomplete
321 323
322 324 $ hg debugpathcomplete f
323 325 fee
324 326 fie
325 327 fo
326 328 $ hg debugpathcomplete -f f
327 329 fee
328 330 fie/dead
329 331 fie/live
330 332 fo
331 333
332 334 $ hg rm Fum
333 335 $ hg debugpathcomplete -r F
334 336 Fum
335 337
336 338 Test debugnamecomplete
337 339
338 340 $ hg debugnamecomplete
339 341 Fum
340 342 default
341 343 fee
342 344 fie
343 345 fo
344 346 tip
345 347 $ hg debugnamecomplete f
346 348 fee
347 349 fie
348 350 fo
@@ -1,102 +1,128 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [format]
3 3 > usegeneraldelta=yes
4 4 > EOF
5 5
6 6 $ hg init debugrevlog
7 7 $ cd debugrevlog
8 8 $ echo a > a
9 9 $ hg ci -Am adda
10 10 adding a
11 11 $ hg debugrevlog -m
12 12 format : 1
13 13 flags : inline, generaldelta
14 14
15 15 revisions : 1
16 16 merges : 0 ( 0.00%)
17 17 normal : 1 (100.00%)
18 18 revisions : 1
19 19 full : 1 (100.00%)
20 20 deltas : 0 ( 0.00%)
21 21 revision size : 44
22 22 full : 44 (100.00%)
23 23 deltas : 0 ( 0.00%)
24 24
25 25 avg chain length : 0
26 26 max chain length : 0
27 27 compression ratio : 0
28 28
29 29 uncompressed data size (min/max/avg) : 43 / 43 / 43
30 30 full revision size (min/max/avg) : 44 / 44 / 44
31 31 delta size (min/max/avg) : 0 / 0 / 0
32 32
33 33 Test debugindex, with and without the --debug flag
34 34 $ hg debugindex a
35 35 rev offset length ..... linkrev nodeid p1 p2 (re)
36 36 0 0 3 .... 0 b789fdd96dc2 000000000000 000000000000 (re)
37 37 $ hg --debug debugindex a
38 38 rev offset length ..... linkrev nodeid p1 p2 (re)
39 39 0 0 3 .... 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 (re)
40 40 $ hg debugindex -f 1 a
41 41 rev flag offset length size ..... link p1 p2 nodeid (re)
42 42 0 0000 0 3 2 .... 0 -1 -1 b789fdd96dc2 (re)
43 43 $ hg --debug debugindex -f 1 a
44 44 rev flag offset length size ..... link p1 p2 nodeid (re)
45 45 0 0000 0 3 2 .... 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (re)
46 46
47 debugdelta chain basic output
48
49 $ hg debugdeltachain -m
50 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
51 0 1 1 -1 base 44 43 44 1.02326 44 0 0.00000
52
53 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
54 0 1 1
55
56 $ hg debugdeltachain -m -Tjson
57 [
58 {
59 "chainid": 1,
60 "chainlen": 1,
61 "chainratio": 1.02325581395,
62 "chainsize": 44,
63 "compsize": 44,
64 "deltatype": "base",
65 "extradist": 0,
66 "extraratio": 0.0,
67 "lindist": 44,
68 "prevrev": -1,
69 "rev": 0,
70 "uncompsize": 43
71 }
72 ]
47 73
48 74 Test max chain len
49 75 $ cat >> $HGRCPATH << EOF
50 76 > [format]
51 77 > maxchainlen=4
52 78 > EOF
53 79
54 80 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
55 81 $ hg ci -m a
56 82 $ printf "b\n" >> a
57 83 $ hg ci -m a
58 84 $ printf "c\n" >> a
59 85 $ hg ci -m a
60 86 $ printf "d\n" >> a
61 87 $ hg ci -m a
62 88 $ printf "e\n" >> a
63 89 $ hg ci -m a
64 90 $ printf "f\n" >> a
65 91 $ hg ci -m a
66 92 $ printf 'g\n' >> a
67 93 $ hg ci -m a
68 94 $ printf 'h\n' >> a
69 95 $ hg ci -m a
70 96 $ hg debugrevlog -d a
71 97 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
72 98 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
73 99 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
74 100 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
75 101 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
76 102 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
77 103 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
78 104 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
79 105 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
80 106 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
81 107 $ cd ..
82 108
83 109 Test internal debugstacktrace command
84 110
85 111 $ cat > debugstacktrace.py << EOF
86 112 > from mercurial.util import debugstacktrace, dst, sys
87 113 > def f():
88 114 > dst('hello world')
89 115 > def g():
90 116 > f()
91 117 > debugstacktrace(skip=-5, f=sys.stdout)
92 118 > g()
93 119 > EOF
94 120 $ python debugstacktrace.py
95 121 hello world at:
96 122 debugstacktrace.py:7 in * (glob)
97 123 debugstacktrace.py:5 in g
98 124 debugstacktrace.py:3 in f
99 125 stacktrace at:
100 126 debugstacktrace.py:7 *in * (glob)
101 127 debugstacktrace.py:6 *in g (glob)
102 128 */util.py:* in debugstacktrace (glob)
@@ -1,2413 +1,2415 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use "hg help" for the full list of commands or "hg -v" for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks create a new bookmark or list existing bookmarks
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 files list tracked files
70 70 forget forget the specified files on the next commit
71 71 graft copy changes from other branches onto the current branch
72 72 grep search for a pattern in specified files and revisions
73 73 heads show branch heads
74 74 help show help for a given topic or a help overview
75 75 identify identify the working directory or specified revision
76 76 import import an ordered set of patches
77 77 incoming show new changesets found in source
78 78 init create a new repository in the given directory
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge another revision into working directory
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 diffs Diff Formats
108 108 environment Environment Variables
109 109 extensions Using Additional Features
110 110 filesets Specifying File Sets
111 111 glossary Glossary
112 112 hgignore Syntax for Mercurial Ignore Files
113 113 hgweb Configuring hgweb
114 114 merge-tools Merge Tools
115 115 multirevs Specifying Multiple Revisions
116 116 patterns File Name Patterns
117 117 phases Working with Phases
118 118 revisions Specifying Single Revisions
119 119 revsets Specifying Revision Sets
120 120 scripting Using Mercurial from scripts and automation
121 121 subrepos Subrepositories
122 122 templating Template Usage
123 123 urls URL Paths
124 124
125 125 (use "hg help -v" to show built-in aliases and global options)
126 126
127 127 $ hg -q help
128 128 add add the specified files on the next commit
129 129 addremove add all new files, delete all missing files
130 130 annotate show changeset information by line for each file
131 131 archive create an unversioned archive of a repository revision
132 132 backout reverse effect of earlier changeset
133 133 bisect subdivision search of changesets
134 134 bookmarks create a new bookmark or list existing bookmarks
135 135 branch set or show the current branch name
136 136 branches list repository named branches
137 137 bundle create a changegroup file
138 138 cat output the current or given revision of files
139 139 clone make a copy of an existing repository
140 140 commit commit the specified files or all outstanding changes
141 141 config show combined config settings from all hgrc files
142 142 copy mark files as copied for the next commit
143 143 diff diff repository (or selected files)
144 144 export dump the header and diffs for one or more changesets
145 145 files list tracked files
146 146 forget forget the specified files on the next commit
147 147 graft copy changes from other branches onto the current branch
148 148 grep search for a pattern in specified files and revisions
149 149 heads show branch heads
150 150 help show help for a given topic or a help overview
151 151 identify identify the working directory or specified revision
152 152 import import an ordered set of patches
153 153 incoming show new changesets found in source
154 154 init create a new repository in the given directory
155 155 log show revision history of entire repository or files
156 156 manifest output the current or given revision of the project manifest
157 157 merge merge another revision into working directory
158 158 outgoing show changesets not found in the destination
159 159 paths show aliases for remote repositories
160 160 phase set or show the current phase name
161 161 pull pull changes from the specified source
162 162 push push changes to the specified destination
163 163 recover roll back an interrupted transaction
164 164 remove remove the specified files on the next commit
165 165 rename rename files; equivalent of copy + remove
166 166 resolve redo merges or set/view the merge status of files
167 167 revert restore files to their checkout state
168 168 root print the root (top) of the current working directory
169 169 serve start stand-alone webserver
170 170 status show changed files in the working directory
171 171 summary summarize working directory state
172 172 tag add one or more tags for the current or given revision
173 173 tags list repository tags
174 174 unbundle apply one or more changegroup files
175 175 update update working directory (or switch revisions)
176 176 verify verify the integrity of the repository
177 177 version output version and copyright information
178 178
179 179 additional help topics:
180 180
181 181 config Configuration Files
182 182 dates Date Formats
183 183 diffs Diff Formats
184 184 environment Environment Variables
185 185 extensions Using Additional Features
186 186 filesets Specifying File Sets
187 187 glossary Glossary
188 188 hgignore Syntax for Mercurial Ignore Files
189 189 hgweb Configuring hgweb
190 190 merge-tools Merge Tools
191 191 multirevs Specifying Multiple Revisions
192 192 patterns File Name Patterns
193 193 phases Working with Phases
194 194 revisions Specifying Single Revisions
195 195 revsets Specifying Revision Sets
196 196 scripting Using Mercurial from scripts and automation
197 197 subrepos Subrepositories
198 198 templating Template Usage
199 199 urls URL Paths
200 200
201 201 Test extension help:
202 202 $ hg help extensions --config extensions.rebase= --config extensions.children=
203 203 Using Additional Features
204 204 """""""""""""""""""""""""
205 205
206 206 Mercurial has the ability to add new features through the use of
207 207 extensions. Extensions may add new commands, add options to existing
208 208 commands, change the default behavior of commands, or implement hooks.
209 209
210 210 To enable the "foo" extension, either shipped with Mercurial or in the
211 211 Python search path, create an entry for it in your configuration file,
212 212 like this:
213 213
214 214 [extensions]
215 215 foo =
216 216
217 217 You may also specify the full path to an extension:
218 218
219 219 [extensions]
220 220 myfeature = ~/.hgext/myfeature.py
221 221
222 222 See "hg help config" for more information on configuration files.
223 223
224 224 Extensions are not loaded by default for a variety of reasons: they can
225 225 increase startup overhead; they may be meant for advanced usage only; they
226 226 may provide potentially dangerous abilities (such as letting you destroy
227 227 or modify history); they might not be ready for prime time; or they may
228 228 alter some usual behaviors of stock Mercurial. It is thus up to the user
229 229 to activate extensions as needed.
230 230
231 231 To explicitly disable an extension enabled in a configuration file of
232 232 broader scope, prepend its path with !:
233 233
234 234 [extensions]
235 235 # disabling extension bar residing in /path/to/extension/bar.py
236 236 bar = !/path/to/extension/bar.py
237 237 # ditto, but no path was supplied for extension baz
238 238 baz = !
239 239
240 240 enabled extensions:
241 241
242 242 children command to display child changesets (DEPRECATED)
243 243 rebase command to move sets of revisions to a different ancestor
244 244
245 245 disabled extensions:
246 246
247 247 acl hooks for controlling repository access
248 248 blackbox log repository events to a blackbox for debugging
249 249 bugzilla hooks for integrating with the Bugzilla bug tracker
250 250 censor erase file content at a given revision
251 251 churn command to display statistics about repository history
252 252 clonebundles advertise pre-generated bundles to seed clones
253 253 (experimental)
254 254 color colorize output from some commands
255 255 convert import revisions from foreign VCS repositories into
256 256 Mercurial
257 257 eol automatically manage newlines in repository files
258 258 extdiff command to allow external programs to compare revisions
259 259 factotum http authentication with factotum
260 260 gpg commands to sign and verify changesets
261 261 hgcia hooks for integrating with the CIA.vc notification service
262 262 hgk browse the repository in a graphical way
263 263 highlight syntax highlighting for hgweb (requires Pygments)
264 264 histedit interactive history editing
265 265 keyword expand keywords in tracked files
266 266 largefiles track large binary files
267 267 mq manage a stack of patches
268 268 notify hooks for sending email push notifications
269 269 pager browse command output with an external pager
270 270 patchbomb command to send changesets as (a series of) patch emails
271 271 purge command to delete untracked files from the working
272 272 directory
273 273 record commands to interactively select changes for
274 274 commit/qrefresh
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.
349 349
350 350 Returns 0 if all files are successfully added.
351 351
352 352 options ([+] can be repeated):
353 353
354 354 -I --include PATTERN [+] include names matching the given patterns
355 355 -X --exclude PATTERN [+] exclude names matching the given patterns
356 356 -S --subrepos recurse into subrepositories
357 357 -n --dry-run do not perform actions, just print output
358 358
359 359 (some details hidden, use --verbose to show complete help)
360 360
361 361 Verbose help for add
362 362
363 363 $ hg add -hv
364 364 hg add [OPTION]... [FILE]...
365 365
366 366 add the specified files on the next commit
367 367
368 368 Schedule files to be version controlled and added to the repository.
369 369
370 370 The files will be added to the repository at the next commit. To undo an
371 371 add before that, see "hg forget".
372 372
373 373 If no names are given, add all files to the repository.
374 374
375 375 Examples:
376 376
377 377 - New (unknown) files are added automatically by "hg add":
378 378
379 379 $ ls
380 380 foo.c
381 381 $ hg status
382 382 ? foo.c
383 383 $ hg add
384 384 adding foo.c
385 385 $ hg status
386 386 A foo.c
387 387
388 388 - Specific files to be added can be specified:
389 389
390 390 $ ls
391 391 bar.c foo.c
392 392 $ hg status
393 393 ? bar.c
394 394 ? foo.c
395 395 $ hg add bar.c
396 396 $ hg status
397 397 A bar.c
398 398 ? foo.c
399 399
400 400 Returns 0 if all files are successfully added.
401 401
402 402 options ([+] can be repeated):
403 403
404 404 -I --include PATTERN [+] include names matching the given patterns
405 405 -X --exclude PATTERN [+] exclude names matching the given patterns
406 406 -S --subrepos recurse into subrepositories
407 407 -n --dry-run do not perform actions, just print output
408 408
409 409 global options ([+] can be repeated):
410 410
411 411 -R --repository REPO repository root directory or name of overlay bundle
412 412 file
413 413 --cwd DIR change working directory
414 414 -y --noninteractive do not prompt, automatically pick the first choice for
415 415 all prompts
416 416 -q --quiet suppress output
417 417 -v --verbose enable additional output
418 418 --config CONFIG [+] set/override config option (use 'section.name=value')
419 419 --debug enable debugging output
420 420 --debugger start debugger
421 421 --encoding ENCODE set the charset encoding (default: ascii)
422 422 --encodingmode MODE set the charset encoding mode (default: strict)
423 423 --traceback always print a traceback on exception
424 424 --time time how long the command takes
425 425 --profile print command execution profile
426 426 --version output version information and exit
427 427 -h --help display help and exit
428 428 --hidden consider hidden changesets
429 429
430 430 Test help option with version option
431 431
432 432 $ hg add -h --version
433 433 Mercurial Distributed SCM (version *) (glob)
434 434 (see https://mercurial-scm.org for more information)
435 435
436 436 Copyright (C) 2005-2015 Matt Mackall and others
437 437 This is free software; see the source for copying conditions. There is NO
438 438 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
439 439
440 440 $ hg add --skjdfks
441 441 hg add: option --skjdfks not recognized
442 442 hg add [OPTION]... [FILE]...
443 443
444 444 add the specified files on the next commit
445 445
446 446 options ([+] can be repeated):
447 447
448 448 -I --include PATTERN [+] include names matching the given patterns
449 449 -X --exclude PATTERN [+] exclude names matching the given patterns
450 450 -S --subrepos recurse into subrepositories
451 451 -n --dry-run do not perform actions, just print output
452 452
453 453 (use "hg add -h" to show more help)
454 454 [255]
455 455
456 456 Test ambiguous command help
457 457
458 458 $ hg help ad
459 459 list of commands:
460 460
461 461 add add the specified files on the next commit
462 462 addremove add all new files, delete all missing files
463 463
464 464 (use "hg help -v ad" to show built-in aliases and global options)
465 465
466 466 Test command without options
467 467
468 468 $ hg help verify
469 469 hg verify
470 470
471 471 verify the integrity of the repository
472 472
473 473 Verify the integrity of the current repository.
474 474
475 475 This will perform an extensive check of the repository's integrity,
476 476 validating the hashes and checksums of each entry in the changelog,
477 477 manifest, and tracked files, as well as the integrity of their crosslinks
478 478 and indices.
479 479
480 480 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
481 481 information about recovery from corruption of the repository.
482 482
483 483 Returns 0 on success, 1 if errors are encountered.
484 484
485 485 (some details hidden, use --verbose to show complete help)
486 486
487 487 $ hg help diff
488 488 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
489 489
490 490 diff repository (or selected files)
491 491
492 492 Show differences between revisions for the specified files.
493 493
494 494 Differences between files are shown using the unified diff format.
495 495
496 496 Note:
497 497 diff may generate unexpected results for merges, as it will default to
498 498 comparing against the working directory's first parent changeset if no
499 499 revisions are specified.
500 500
501 501 When two revision arguments are given, then changes are shown between
502 502 those revisions. If only one revision is specified then that revision is
503 503 compared to the working directory, and, when no revisions are specified,
504 504 the working directory files are compared to its parent.
505 505
506 506 Alternatively you can specify -c/--change with a revision to see the
507 507 changes in that changeset relative to its first parent.
508 508
509 509 Without the -a/--text option, diff will avoid generating diffs of files it
510 510 detects as binary. With -a, diff will generate a diff anyway, probably
511 511 with undesirable results.
512 512
513 513 Use the -g/--git option to generate diffs in the git extended diff format.
514 514 For more information, read "hg help diffs".
515 515
516 516 Returns 0 on success.
517 517
518 518 options ([+] can be repeated):
519 519
520 520 -r --rev REV [+] revision
521 521 -c --change REV change made by revision
522 522 -a --text treat all files as text
523 523 -g --git use git extended diff format
524 524 --nodates omit dates from diff headers
525 525 --noprefix omit a/ and b/ prefixes from filenames
526 526 -p --show-function show which function each change is in
527 527 --reverse produce a diff that undoes the changes
528 528 -w --ignore-all-space ignore white space when comparing lines
529 529 -b --ignore-space-change ignore changes in the amount of white space
530 530 -B --ignore-blank-lines ignore changes whose lines are all blank
531 531 -U --unified NUM number of lines of context to show
532 532 --stat output diffstat-style summary of changes
533 533 --root DIR produce diffs relative to subdirectory
534 534 -I --include PATTERN [+] include names matching the given patterns
535 535 -X --exclude PATTERN [+] exclude names matching the given patterns
536 536 -S --subrepos recurse into subrepositories
537 537
538 538 (some details hidden, use --verbose to show complete help)
539 539
540 540 $ hg help status
541 541 hg status [OPTION]... [FILE]...
542 542
543 543 aliases: st
544 544
545 545 show changed files in the working directory
546 546
547 547 Show status of files in the repository. If names are given, only files
548 548 that match are shown. Files that are clean or ignored or the source of a
549 549 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
550 550 -C/--copies or -A/--all are given. Unless options described with "show
551 551 only ..." are given, the options -mardu are used.
552 552
553 553 Option -q/--quiet hides untracked (unknown and ignored) files unless
554 554 explicitly requested with -u/--unknown or -i/--ignored.
555 555
556 556 Note:
557 557 status may appear to disagree with diff if permissions have changed or
558 558 a merge has occurred. The standard diff format does not report
559 559 permission changes and diff only reports changes relative to one merge
560 560 parent.
561 561
562 562 If one revision is given, it is used as the base revision. If two
563 563 revisions are given, the differences between them are shown. The --change
564 564 option can also be used as a shortcut to list the changed files of a
565 565 revision from its first parent.
566 566
567 567 The codes used to show the status of files are:
568 568
569 569 M = modified
570 570 A = added
571 571 R = removed
572 572 C = clean
573 573 ! = missing (deleted by non-hg command, but still tracked)
574 574 ? = not tracked
575 575 I = ignored
576 576 = origin of the previous file (with --copies)
577 577
578 578 Returns 0 on success.
579 579
580 580 options ([+] can be repeated):
581 581
582 582 -A --all show status of all files
583 583 -m --modified show only modified files
584 584 -a --added show only added files
585 585 -r --removed show only removed files
586 586 -d --deleted show only deleted (but tracked) files
587 587 -c --clean show only files without changes
588 588 -u --unknown show only unknown (not tracked) files
589 589 -i --ignored show only ignored files
590 590 -n --no-status hide status prefix
591 591 -C --copies show source of copied files
592 592 -0 --print0 end filenames with NUL, for use with xargs
593 593 --rev REV [+] show difference from revision
594 594 --change REV list the changed files of a revision
595 595 -I --include PATTERN [+] include names matching the given patterns
596 596 -X --exclude PATTERN [+] exclude names matching the given patterns
597 597 -S --subrepos recurse into subrepositories
598 598
599 599 (some details hidden, use --verbose to show complete help)
600 600
601 601 $ hg -q help status
602 602 hg status [OPTION]... [FILE]...
603 603
604 604 show changed files in the working directory
605 605
606 606 $ hg help foo
607 607 abort: no such help topic: foo
608 608 (try "hg help --keyword foo")
609 609 [255]
610 610
611 611 $ hg skjdfks
612 612 hg: unknown command 'skjdfks'
613 613 Mercurial Distributed SCM
614 614
615 615 basic commands:
616 616
617 617 add add the specified files on the next commit
618 618 annotate show changeset information by line for each file
619 619 clone make a copy of an existing repository
620 620 commit commit the specified files or all outstanding changes
621 621 diff diff repository (or selected files)
622 622 export dump the header and diffs for one or more changesets
623 623 forget forget the specified files on the next commit
624 624 init create a new repository in the given directory
625 625 log show revision history of entire repository or files
626 626 merge merge another revision into working directory
627 627 pull pull changes from the specified source
628 628 push push changes to the specified destination
629 629 remove remove the specified files on the next commit
630 630 serve start stand-alone webserver
631 631 status show changed files in the working directory
632 632 summary summarize working directory state
633 633 update update working directory (or switch revisions)
634 634
635 635 (use "hg help" for the full list of commands or "hg -v" for details)
636 636 [255]
637 637
638 638
639 639 Make sure that we don't run afoul of the help system thinking that
640 640 this is a section and erroring out weirdly.
641 641
642 642 $ hg .log
643 643 hg: unknown command '.log'
644 644 (did you mean one of log?)
645 645 [255]
646 646
647 647 $ hg log.
648 648 hg: unknown command 'log.'
649 649 (did you mean one of log?)
650 650 [255]
651 651 $ hg pu.lh
652 652 hg: unknown command 'pu.lh'
653 653 (did you mean one of pull, push?)
654 654 [255]
655 655
656 656 $ cat > helpext.py <<EOF
657 657 > import os
658 658 > from mercurial import cmdutil, commands
659 659 >
660 660 > cmdtable = {}
661 661 > command = cmdutil.command(cmdtable)
662 662 >
663 663 > @command('nohelp',
664 664 > [('', 'longdesc', 3, 'x'*90),
665 665 > ('n', '', None, 'normal desc'),
666 666 > ('', 'newline', '', 'line1\nline2')],
667 667 > 'hg nohelp',
668 668 > norepo=True)
669 669 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
670 670 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
671 671 > def nohelp(ui, *args, **kwargs):
672 672 > pass
673 673 >
674 674 > EOF
675 675 $ echo '[extensions]' >> $HGRCPATH
676 676 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
677 677
678 678 Test command with no help text
679 679
680 680 $ hg help nohelp
681 681 hg nohelp
682 682
683 683 (no help text available)
684 684
685 685 options:
686 686
687 687 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
688 688 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
689 689 -n -- normal desc
690 690 --newline VALUE line1 line2
691 691
692 692 (some details hidden, use --verbose to show complete help)
693 693
694 694 $ hg help -k nohelp
695 695 Commands:
696 696
697 697 nohelp hg nohelp
698 698
699 699 Extension Commands:
700 700
701 701 nohelp (no help text available)
702 702
703 703 Test that default list of commands omits extension commands
704 704
705 705 $ hg help
706 706 Mercurial Distributed SCM
707 707
708 708 list of commands:
709 709
710 710 add add the specified files on the next commit
711 711 addremove add all new files, delete all missing files
712 712 annotate show changeset information by line for each file
713 713 archive create an unversioned archive of a repository revision
714 714 backout reverse effect of earlier changeset
715 715 bisect subdivision search of changesets
716 716 bookmarks create a new bookmark or list existing bookmarks
717 717 branch set or show the current branch name
718 718 branches list repository named branches
719 719 bundle create a changegroup file
720 720 cat output the current or given revision of files
721 721 clone make a copy of an existing repository
722 722 commit commit the specified files or all outstanding changes
723 723 config show combined config settings from all hgrc files
724 724 copy mark files as copied for the next commit
725 725 diff diff repository (or selected files)
726 726 export dump the header and diffs for one or more changesets
727 727 files list tracked files
728 728 forget forget the specified files on the next commit
729 729 graft copy changes from other branches onto the current branch
730 730 grep search for a pattern in specified files and revisions
731 731 heads show branch heads
732 732 help show help for a given topic or a help overview
733 733 identify identify the working directory or specified revision
734 734 import import an ordered set of patches
735 735 incoming show new changesets found in source
736 736 init create a new repository in the given directory
737 737 log show revision history of entire repository or files
738 738 manifest output the current or given revision of the project manifest
739 739 merge merge another revision into working directory
740 740 outgoing show changesets not found in the destination
741 741 paths show aliases for remote repositories
742 742 phase set or show the current phase name
743 743 pull pull changes from the specified source
744 744 push push changes to the specified destination
745 745 recover roll back an interrupted transaction
746 746 remove remove the specified files on the next commit
747 747 rename rename files; equivalent of copy + remove
748 748 resolve redo merges or set/view the merge status of files
749 749 revert restore files to their checkout state
750 750 root print the root (top) of the current working directory
751 751 serve start stand-alone webserver
752 752 status show changed files in the working directory
753 753 summary summarize working directory state
754 754 tag add one or more tags for the current or given revision
755 755 tags list repository tags
756 756 unbundle apply one or more changegroup files
757 757 update update working directory (or switch revisions)
758 758 verify verify the integrity of the repository
759 759 version output version and copyright information
760 760
761 761 enabled extensions:
762 762
763 763 helpext (no help text available)
764 764
765 765 additional help topics:
766 766
767 767 config Configuration Files
768 768 dates Date Formats
769 769 diffs Diff Formats
770 770 environment Environment Variables
771 771 extensions Using Additional Features
772 772 filesets Specifying File Sets
773 773 glossary Glossary
774 774 hgignore Syntax for Mercurial Ignore Files
775 775 hgweb Configuring hgweb
776 776 merge-tools Merge Tools
777 777 multirevs Specifying Multiple Revisions
778 778 patterns File Name Patterns
779 779 phases Working with Phases
780 780 revisions Specifying Single Revisions
781 781 revsets Specifying Revision Sets
782 782 scripting Using Mercurial from scripts and automation
783 783 subrepos Subrepositories
784 784 templating Template Usage
785 785 urls URL Paths
786 786
787 787 (use "hg help -v" to show built-in aliases and global options)
788 788
789 789
790 790 Test list of internal help commands
791 791
792 792 $ hg help debug
793 793 debug commands (internal and unsupported):
794 794
795 795 debugancestor
796 796 find the ancestor revision of two revisions in a given index
797 797 debugapplystreamclonebundle
798 798 apply a stream clone bundle file
799 799 debugbuilddag
800 800 builds a repo with a given DAG from scratch in the current
801 801 empty repo
802 802 debugbundle lists the contents of a bundle
803 803 debugcheckstate
804 804 validate the correctness of the current dirstate
805 805 debugcommands
806 806 list all available commands and options
807 807 debugcomplete
808 808 returns the completion list associated with the given command
809 809 debugcreatestreamclonebundle
810 810 create a stream clone bundle file
811 811 debugdag format the changelog or an index DAG as a concise textual
812 812 description
813 813 debugdata dump the contents of a data file revision
814 814 debugdate parse and display a date
815 debugdeltachain
816 dump information about delta chains in a revlog
815 817 debugdirstate
816 818 show the contents of the current dirstate
817 819 debugdiscovery
818 820 runs the changeset discovery protocol in isolation
819 821 debugextensions
820 822 show information about active extensions
821 823 debugfileset parse and apply a fileset specification
822 824 debugfsinfo show information detected about current filesystem
823 825 debuggetbundle
824 826 retrieves a bundle from a repo
825 827 debugignore display the combined ignore pattern
826 828 debugindex dump the contents of an index file
827 829 debugindexdot
828 830 dump an index DAG as a graphviz dot file
829 831 debuginstall test Mercurial installation
830 832 debugknown test whether node ids are known to a repo
831 833 debuglocks show or modify state of locks
832 834 debugmergestate
833 835 print merge state
834 836 debugnamecomplete
835 837 complete "names" - tags, open branch names, bookmark names
836 838 debugobsolete
837 839 create arbitrary obsolete marker
838 840 debugoptDEP (no help text available)
839 841 debugoptEXP (no help text available)
840 842 debugpathcomplete
841 843 complete part or all of a tracked path
842 844 debugpushkey access the pushkey key/value protocol
843 845 debugpvec (no help text available)
844 846 debugrebuilddirstate
845 847 rebuild the dirstate as it would look like for the given
846 848 revision
847 849 debugrebuildfncache
848 850 rebuild the fncache file
849 851 debugrename dump rename information
850 852 debugrevlog show data and statistics about a revlog
851 853 debugrevspec parse and apply a revision specification
852 854 debugsetparents
853 855 manually set the parents of the current working directory
854 856 debugsub (no help text available)
855 857 debugsuccessorssets
856 858 show set of successors for revision
857 859 debugwalk show how files match on given patterns
858 860 debugwireargs
859 861 (no help text available)
860 862
861 863 (use "hg help -v debug" to show built-in aliases and global options)
862 864
863 865
864 866 Test list of commands with command with no help text
865 867
866 868 $ hg help helpext
867 869 helpext extension - no help text available
868 870
869 871 list of commands:
870 872
871 873 nohelp (no help text available)
872 874
873 875 (use "hg help -v helpext" to show built-in aliases and global options)
874 876
875 877
876 878 test deprecated and experimental options are hidden in command help
877 879 $ hg help debugoptDEP
878 880 hg debugoptDEP
879 881
880 882 (no help text available)
881 883
882 884 options:
883 885
884 886 (some details hidden, use --verbose to show complete help)
885 887
886 888 $ hg help debugoptEXP
887 889 hg debugoptEXP
888 890
889 891 (no help text available)
890 892
891 893 options:
892 894
893 895 (some details hidden, use --verbose to show complete help)
894 896
895 897 test deprecated and experimental options is shown with -v
896 898 $ hg help -v debugoptDEP | grep dopt
897 899 --dopt option is (DEPRECATED)
898 900 $ hg help -v debugoptEXP | grep eopt
899 901 --eopt option is (EXPERIMENTAL)
900 902
901 903 #if gettext
902 904 test deprecated option is hidden with translation with untranslated description
903 905 (use many globy for not failing on changed transaction)
904 906 $ LANGUAGE=sv hg help debugoptDEP
905 907 hg debugoptDEP
906 908
907 909 (*) (glob)
908 910
909 911 options:
910 912
911 913 (some details hidden, use --verbose to show complete help)
912 914 #endif
913 915
914 916 Test commands that collide with topics (issue4240)
915 917
916 918 $ hg config -hq
917 919 hg config [-u] [NAME]...
918 920
919 921 show combined config settings from all hgrc files
920 922 $ hg showconfig -hq
921 923 hg config [-u] [NAME]...
922 924
923 925 show combined config settings from all hgrc files
924 926
925 927 Test a help topic
926 928
927 929 $ hg help revs
928 930 Specifying Single Revisions
929 931 """""""""""""""""""""""""""
930 932
931 933 Mercurial supports several ways to specify individual revisions.
932 934
933 935 A plain integer is treated as a revision number. Negative integers are
934 936 treated as sequential offsets from the tip, with -1 denoting the tip, -2
935 937 denoting the revision prior to the tip, and so forth.
936 938
937 939 A 40-digit hexadecimal string is treated as a unique revision identifier.
938 940
939 941 A hexadecimal string less than 40 characters long is treated as a unique
940 942 revision identifier and is referred to as a short-form identifier. A
941 943 short-form identifier is only valid if it is the prefix of exactly one
942 944 full-length identifier.
943 945
944 946 Any other string is treated as a bookmark, tag, or branch name. A bookmark
945 947 is a movable pointer to a revision. A tag is a permanent name associated
946 948 with a revision. A branch name denotes the tipmost open branch head of
947 949 that branch - or if they are all closed, the tipmost closed head of the
948 950 branch. Bookmark, tag, and branch names must not contain the ":"
949 951 character.
950 952
951 953 The reserved name "tip" always identifies the most recent revision.
952 954
953 955 The reserved name "null" indicates the null revision. This is the revision
954 956 of an empty repository, and the parent of revision 0.
955 957
956 958 The reserved name "." indicates the working directory parent. If no
957 959 working directory is checked out, it is equivalent to null. If an
958 960 uncommitted merge is in progress, "." is the revision of the first parent.
959 961
960 962 Test repeated config section name
961 963
962 964 $ hg help config.host
963 965 "http_proxy.host"
964 966 Host name and (optional) port of the proxy server, for example
965 967 "myproxy:8000".
966 968
967 969 "smtp.host"
968 970 Host name of mail server, e.g. "mail.example.com".
969 971
970 972 Unrelated trailing paragraphs shouldn't be included
971 973
972 974 $ hg help config.extramsg | grep '^$'
973 975
974 976
975 977 Test capitalized section name
976 978
977 979 $ hg help scripting.HGPLAIN > /dev/null
978 980
979 981 Help subsection:
980 982
981 983 $ hg help config.charsets |grep "Email example:" > /dev/null
982 984 [1]
983 985
984 986 Show nested definitions
985 987 ("profiling.type"[break]"ls"[break]"stat"[break])
986 988
987 989 $ hg help config.type | egrep '^$'|wc -l
988 990 \s*3 (re)
989 991
990 992 Last item in help config.*:
991 993
992 994 $ hg help config.`hg help config|grep '^ "'| \
993 995 > tail -1|sed 's![ "]*!!g'`| \
994 996 > grep "hg help -c config" > /dev/null
995 997 [1]
996 998
997 999 note to use help -c for general hg help config:
998 1000
999 1001 $ hg help config |grep "hg help -c config" > /dev/null
1000 1002
1001 1003 Test templating help
1002 1004
1003 1005 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1004 1006 desc String. The text of the changeset description.
1005 1007 diffstat String. Statistics of changes with the following format:
1006 1008 firstline Any text. Returns the first line of text.
1007 1009 nonempty Any text. Returns '(none)' if the string is empty.
1008 1010
1009 1011 Test deprecated items
1010 1012
1011 1013 $ hg help -v templating | grep currentbookmark
1012 1014 currentbookmark
1013 1015 $ hg help templating | (grep currentbookmark || true)
1014 1016
1015 1017 Test help hooks
1016 1018
1017 1019 $ cat > helphook1.py <<EOF
1018 1020 > from mercurial import help
1019 1021 >
1020 1022 > def rewrite(ui, topic, doc):
1021 1023 > return doc + '\nhelphook1\n'
1022 1024 >
1023 1025 > def extsetup(ui):
1024 1026 > help.addtopichook('revsets', rewrite)
1025 1027 > EOF
1026 1028 $ cat > helphook2.py <<EOF
1027 1029 > from mercurial import help
1028 1030 >
1029 1031 > def rewrite(ui, topic, doc):
1030 1032 > return doc + '\nhelphook2\n'
1031 1033 >
1032 1034 > def extsetup(ui):
1033 1035 > help.addtopichook('revsets', rewrite)
1034 1036 > EOF
1035 1037 $ echo '[extensions]' >> $HGRCPATH
1036 1038 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1037 1039 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1038 1040 $ hg help revsets | grep helphook
1039 1041 helphook1
1040 1042 helphook2
1041 1043
1042 1044 Test -e / -c / -k combinations
1043 1045
1044 1046 $ hg help -c schemes
1045 1047 abort: no such help topic: schemes
1046 1048 (try "hg help --keyword schemes")
1047 1049 [255]
1048 1050 $ hg help -e schemes |head -1
1049 1051 schemes extension - extend schemes with shortcuts to repository swarms
1050 1052 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1051 1053 Commands:
1052 1054 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1053 1055 Extensions:
1054 1056 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1055 1057 Extensions:
1056 1058 Commands:
1057 1059 $ hg help -c commit > /dev/null
1058 1060 $ hg help -e -c commit > /dev/null
1059 1061 $ hg help -e commit > /dev/null
1060 1062 abort: no such help topic: commit
1061 1063 (try "hg help --keyword commit")
1062 1064 [255]
1063 1065
1064 1066 Test keyword search help
1065 1067
1066 1068 $ cat > prefixedname.py <<EOF
1067 1069 > '''matched against word "clone"
1068 1070 > '''
1069 1071 > EOF
1070 1072 $ echo '[extensions]' >> $HGRCPATH
1071 1073 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1072 1074 $ hg help -k clone
1073 1075 Topics:
1074 1076
1075 1077 config Configuration Files
1076 1078 extensions Using Additional Features
1077 1079 glossary Glossary
1078 1080 phases Working with Phases
1079 1081 subrepos Subrepositories
1080 1082 urls URL Paths
1081 1083
1082 1084 Commands:
1083 1085
1084 1086 bookmarks create a new bookmark or list existing bookmarks
1085 1087 clone make a copy of an existing repository
1086 1088 debugapplystreamclonebundle apply a stream clone bundle file
1087 1089 debugcreatestreamclonebundle create a stream clone bundle file
1088 1090 paths show aliases for remote repositories
1089 1091 update update working directory (or switch revisions)
1090 1092
1091 1093 Extensions:
1092 1094
1093 1095 clonebundles advertise pre-generated bundles to seed clones (experimental)
1094 1096 prefixedname matched against word "clone"
1095 1097 relink recreates hardlinks between repository clones
1096 1098
1097 1099 Extension Commands:
1098 1100
1099 1101 qclone clone main and patch repository at same time
1100 1102
1101 1103 Test unfound topic
1102 1104
1103 1105 $ hg help nonexistingtopicthatwillneverexisteverever
1104 1106 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1105 1107 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1106 1108 [255]
1107 1109
1108 1110 Test unfound keyword
1109 1111
1110 1112 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1111 1113 abort: no matches
1112 1114 (try "hg help" for a list of topics)
1113 1115 [255]
1114 1116
1115 1117 Test omit indicating for help
1116 1118
1117 1119 $ cat > addverboseitems.py <<EOF
1118 1120 > '''extension to test omit indicating.
1119 1121 >
1120 1122 > This paragraph is never omitted (for extension)
1121 1123 >
1122 1124 > .. container:: verbose
1123 1125 >
1124 1126 > This paragraph is omitted,
1125 1127 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1126 1128 >
1127 1129 > This paragraph is never omitted, too (for extension)
1128 1130 > '''
1129 1131 >
1130 1132 > from mercurial import help, commands
1131 1133 > testtopic = """This paragraph is never omitted (for topic).
1132 1134 >
1133 1135 > .. container:: verbose
1134 1136 >
1135 1137 > This paragraph is omitted,
1136 1138 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1137 1139 >
1138 1140 > This paragraph is never omitted, too (for topic)
1139 1141 > """
1140 1142 > def extsetup(ui):
1141 1143 > help.helptable.append((["topic-containing-verbose"],
1142 1144 > "This is the topic to test omit indicating.",
1143 1145 > lambda ui: testtopic))
1144 1146 > EOF
1145 1147 $ echo '[extensions]' >> $HGRCPATH
1146 1148 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1147 1149 $ hg help addverboseitems
1148 1150 addverboseitems extension - extension to test omit indicating.
1149 1151
1150 1152 This paragraph is never omitted (for extension)
1151 1153
1152 1154 This paragraph is never omitted, too (for extension)
1153 1155
1154 1156 (some details hidden, use --verbose to show complete help)
1155 1157
1156 1158 no commands defined
1157 1159 $ hg help -v addverboseitems
1158 1160 addverboseitems extension - extension to test omit indicating.
1159 1161
1160 1162 This paragraph is never omitted (for extension)
1161 1163
1162 1164 This paragraph is omitted, if "hg help" is invoked without "-v" (for
1163 1165 extension)
1164 1166
1165 1167 This paragraph is never omitted, too (for extension)
1166 1168
1167 1169 no commands defined
1168 1170 $ hg help topic-containing-verbose
1169 1171 This is the topic to test omit indicating.
1170 1172 """"""""""""""""""""""""""""""""""""""""""
1171 1173
1172 1174 This paragraph is never omitted (for topic).
1173 1175
1174 1176 This paragraph is never omitted, too (for topic)
1175 1177
1176 1178 (some details hidden, use --verbose to show complete help)
1177 1179 $ hg help -v topic-containing-verbose
1178 1180 This is the topic to test omit indicating.
1179 1181 """"""""""""""""""""""""""""""""""""""""""
1180 1182
1181 1183 This paragraph is never omitted (for topic).
1182 1184
1183 1185 This paragraph is omitted, if "hg help" is invoked without "-v" (for
1184 1186 topic)
1185 1187
1186 1188 This paragraph is never omitted, too (for topic)
1187 1189
1188 1190 Test section lookup
1189 1191
1190 1192 $ hg help revset.merge
1191 1193 "merge()"
1192 1194 Changeset is a merge changeset.
1193 1195
1194 1196 $ hg help glossary.dag
1195 1197 DAG
1196 1198 The repository of changesets of a distributed version control system
1197 1199 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1198 1200 of nodes and edges, where nodes correspond to changesets and edges
1199 1201 imply a parent -> child relation. This graph can be visualized by
1200 1202 graphical tools such as "hg log --graph". In Mercurial, the DAG is
1201 1203 limited by the requirement for children to have at most two parents.
1202 1204
1203 1205
1204 1206 $ hg help hgrc.paths
1205 1207 "paths"
1206 1208 -------
1207 1209
1208 1210 Assigns symbolic names to repositories. The left side is the symbolic
1209 1211 name, and the right gives the directory or URL that is the location of the
1210 1212 repository. Default paths can be declared by setting the following
1211 1213 entries.
1212 1214
1213 1215 "default"
1214 1216 Directory or URL to use when pulling if no source is specified.
1215 1217 (default: repository from which the current repository was cloned)
1216 1218
1217 1219 "default-push"
1218 1220 Optional. Directory or URL to use when pushing if no destination is
1219 1221 specified.
1220 1222
1221 1223 Custom paths can be defined by assigning the path to a name that later can
1222 1224 be used from the command line. Example:
1223 1225
1224 1226 [paths]
1225 1227 my_path = http://example.com/path
1226 1228
1227 1229 To push to the path defined in "my_path" run the command:
1228 1230
1229 1231 hg push my_path
1230 1232
1231 1233 $ hg help glossary.mcguffin
1232 1234 abort: help section not found
1233 1235 [255]
1234 1236
1235 1237 $ hg help glossary.mc.guffin
1236 1238 abort: help section not found
1237 1239 [255]
1238 1240
1239 1241 $ hg help template.files
1240 1242 files List of strings. All files modified, added, or removed by
1241 1243 this changeset.
1242 1244
1243 1245 Test dynamic list of merge tools only shows up once
1244 1246 $ hg help merge-tools
1245 1247 Merge Tools
1246 1248 """""""""""
1247 1249
1248 1250 To merge files Mercurial uses merge tools.
1249 1251
1250 1252 A merge tool combines two different versions of a file into a merged file.
1251 1253 Merge tools are given the two files and the greatest common ancestor of
1252 1254 the two file versions, so they can determine the changes made on both
1253 1255 branches.
1254 1256
1255 1257 Merge tools are used both for "hg resolve", "hg merge", "hg update", "hg
1256 1258 backout" and in several extensions.
1257 1259
1258 1260 Usually, the merge tool tries to automatically reconcile the files by
1259 1261 combining all non-overlapping changes that occurred separately in the two
1260 1262 different evolutions of the same initial base file. Furthermore, some
1261 1263 interactive merge programs make it easier to manually resolve conflicting
1262 1264 merges, either in a graphical way, or by inserting some conflict markers.
1263 1265 Mercurial does not include any interactive merge programs but relies on
1264 1266 external tools for that.
1265 1267
1266 1268 Available merge tools
1267 1269 =====================
1268 1270
1269 1271 External merge tools and their properties are configured in the merge-
1270 1272 tools configuration section - see hgrc(5) - but they can often just be
1271 1273 named by their executable.
1272 1274
1273 1275 A merge tool is generally usable if its executable can be found on the
1274 1276 system and if it can handle the merge. The executable is found if it is an
1275 1277 absolute or relative executable path or the name of an application in the
1276 1278 executable search path. The tool is assumed to be able to handle the merge
1277 1279 if it can handle symlinks if the file is a symlink, if it can handle
1278 1280 binary files if the file is binary, and if a GUI is available if the tool
1279 1281 requires a GUI.
1280 1282
1281 1283 There are some internal merge tools which can be used. The internal merge
1282 1284 tools are:
1283 1285
1284 1286 ":dump"
1285 1287 Creates three versions of the files to merge, containing the contents of
1286 1288 local, other and base. These files can then be used to perform a merge
1287 1289 manually. If the file to be merged is named "a.txt", these files will
1288 1290 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1289 1291 they will be placed in the same directory as "a.txt".
1290 1292
1291 1293 ":fail"
1292 1294 Rather than attempting to merge files that were modified on both
1293 1295 branches, it marks them as unresolved. The resolve command must be used
1294 1296 to resolve these conflicts.
1295 1297
1296 1298 ":local"
1297 1299 Uses the local version of files as the merged version.
1298 1300
1299 1301 ":merge"
1300 1302 Uses the internal non-interactive simple merge algorithm for merging
1301 1303 files. It will fail if there are any conflicts and leave markers in the
1302 1304 partially merged file. Markers will have two sections, one for each side
1303 1305 of merge.
1304 1306
1305 1307 ":merge-local"
1306 1308 Like :merge, but resolve all conflicts non-interactively in favor of the
1307 1309 local changes.
1308 1310
1309 1311 ":merge-other"
1310 1312 Like :merge, but resolve all conflicts non-interactively in favor of the
1311 1313 other changes.
1312 1314
1313 1315 ":merge3"
1314 1316 Uses the internal non-interactive simple merge algorithm for merging
1315 1317 files. It will fail if there are any conflicts and leave markers in the
1316 1318 partially merged file. Marker will have three sections, one from each
1317 1319 side of the merge and one for the base content.
1318 1320
1319 1321 ":other"
1320 1322 Uses the other version of files as the merged version.
1321 1323
1322 1324 ":prompt"
1323 1325 Asks the user which of the local or the other version to keep as the
1324 1326 merged version.
1325 1327
1326 1328 ":tagmerge"
1327 1329 Uses the internal tag merge algorithm (experimental).
1328 1330
1329 1331 ":union"
1330 1332 Uses the internal non-interactive simple merge algorithm for merging
1331 1333 files. It will use both left and right sides for conflict regions. No
1332 1334 markers are inserted.
1333 1335
1334 1336 Internal tools are always available and do not require a GUI but will by
1335 1337 default not handle symlinks or binary files.
1336 1338
1337 1339 Choosing a merge tool
1338 1340 =====================
1339 1341
1340 1342 Mercurial uses these rules when deciding which merge tool to use:
1341 1343
1342 1344 1. If a tool has been specified with the --tool option to merge or
1343 1345 resolve, it is used. If it is the name of a tool in the merge-tools
1344 1346 configuration, its configuration is used. Otherwise the specified tool
1345 1347 must be executable by the shell.
1346 1348 2. If the "HGMERGE" environment variable is present, its value is used and
1347 1349 must be executable by the shell.
1348 1350 3. If the filename of the file to be merged matches any of the patterns in
1349 1351 the merge-patterns configuration section, the first usable merge tool
1350 1352 corresponding to a matching pattern is used. Here, binary capabilities
1351 1353 of the merge tool are not considered.
1352 1354 4. If ui.merge is set it will be considered next. If the value is not the
1353 1355 name of a configured tool, the specified value is used and must be
1354 1356 executable by the shell. Otherwise the named tool is used if it is
1355 1357 usable.
1356 1358 5. If any usable merge tools are present in the merge-tools configuration
1357 1359 section, the one with the highest priority is used.
1358 1360 6. If a program named "hgmerge" can be found on the system, it is used -
1359 1361 but it will by default not be used for symlinks and binary files.
1360 1362 7. If the file to be merged is not binary and is not a symlink, then
1361 1363 internal ":merge" is used.
1362 1364 8. The merge of the file fails and must be resolved before commit.
1363 1365
1364 1366 Note:
1365 1367 After selecting a merge program, Mercurial will by default attempt to
1366 1368 merge the files using a simple merge algorithm first. Only if it
1367 1369 doesn't succeed because of conflicting changes Mercurial will actually
1368 1370 execute the merge program. Whether to use the simple merge algorithm
1369 1371 first can be controlled by the premerge setting of the merge tool.
1370 1372 Premerge is enabled by default unless the file is binary or a symlink.
1371 1373
1372 1374 See the merge-tools and ui sections of hgrc(5) for details on the
1373 1375 configuration of merge tools.
1374 1376
1375 1377 Test usage of section marks in help documents
1376 1378
1377 1379 $ cd "$TESTDIR"/../doc
1378 1380 $ python check-seclevel.py
1379 1381 $ cd $TESTTMP
1380 1382
1381 1383 #if serve
1382 1384
1383 1385 Test the help pages in hgweb.
1384 1386
1385 1387 Dish up an empty repo; serve it cold.
1386 1388
1387 1389 $ hg init "$TESTTMP/test"
1388 1390 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1389 1391 $ cat hg.pid >> $DAEMON_PIDS
1390 1392
1391 1393 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1392 1394 200 Script output follows
1393 1395
1394 1396 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1395 1397 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1396 1398 <head>
1397 1399 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1398 1400 <meta name="robots" content="index, nofollow" />
1399 1401 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1400 1402 <script type="text/javascript" src="/static/mercurial.js"></script>
1401 1403
1402 1404 <title>Help: Index</title>
1403 1405 </head>
1404 1406 <body>
1405 1407
1406 1408 <div class="container">
1407 1409 <div class="menu">
1408 1410 <div class="logo">
1409 1411 <a href="https://mercurial-scm.org/">
1410 1412 <img src="/static/hglogo.png" alt="mercurial" /></a>
1411 1413 </div>
1412 1414 <ul>
1413 1415 <li><a href="/shortlog">log</a></li>
1414 1416 <li><a href="/graph">graph</a></li>
1415 1417 <li><a href="/tags">tags</a></li>
1416 1418 <li><a href="/bookmarks">bookmarks</a></li>
1417 1419 <li><a href="/branches">branches</a></li>
1418 1420 </ul>
1419 1421 <ul>
1420 1422 <li class="active">help</li>
1421 1423 </ul>
1422 1424 </div>
1423 1425
1424 1426 <div class="main">
1425 1427 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1426 1428 <form class="search" action="/log">
1427 1429
1428 1430 <p><input name="rev" id="search1" type="text" size="30" /></p>
1429 1431 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1430 1432 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1431 1433 </form>
1432 1434 <table class="bigtable">
1433 1435 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1434 1436
1435 1437 <tr><td>
1436 1438 <a href="/help/config">
1437 1439 config
1438 1440 </a>
1439 1441 </td><td>
1440 1442 Configuration Files
1441 1443 </td></tr>
1442 1444 <tr><td>
1443 1445 <a href="/help/dates">
1444 1446 dates
1445 1447 </a>
1446 1448 </td><td>
1447 1449 Date Formats
1448 1450 </td></tr>
1449 1451 <tr><td>
1450 1452 <a href="/help/diffs">
1451 1453 diffs
1452 1454 </a>
1453 1455 </td><td>
1454 1456 Diff Formats
1455 1457 </td></tr>
1456 1458 <tr><td>
1457 1459 <a href="/help/environment">
1458 1460 environment
1459 1461 </a>
1460 1462 </td><td>
1461 1463 Environment Variables
1462 1464 </td></tr>
1463 1465 <tr><td>
1464 1466 <a href="/help/extensions">
1465 1467 extensions
1466 1468 </a>
1467 1469 </td><td>
1468 1470 Using Additional Features
1469 1471 </td></tr>
1470 1472 <tr><td>
1471 1473 <a href="/help/filesets">
1472 1474 filesets
1473 1475 </a>
1474 1476 </td><td>
1475 1477 Specifying File Sets
1476 1478 </td></tr>
1477 1479 <tr><td>
1478 1480 <a href="/help/glossary">
1479 1481 glossary
1480 1482 </a>
1481 1483 </td><td>
1482 1484 Glossary
1483 1485 </td></tr>
1484 1486 <tr><td>
1485 1487 <a href="/help/hgignore">
1486 1488 hgignore
1487 1489 </a>
1488 1490 </td><td>
1489 1491 Syntax for Mercurial Ignore Files
1490 1492 </td></tr>
1491 1493 <tr><td>
1492 1494 <a href="/help/hgweb">
1493 1495 hgweb
1494 1496 </a>
1495 1497 </td><td>
1496 1498 Configuring hgweb
1497 1499 </td></tr>
1498 1500 <tr><td>
1499 1501 <a href="/help/merge-tools">
1500 1502 merge-tools
1501 1503 </a>
1502 1504 </td><td>
1503 1505 Merge Tools
1504 1506 </td></tr>
1505 1507 <tr><td>
1506 1508 <a href="/help/multirevs">
1507 1509 multirevs
1508 1510 </a>
1509 1511 </td><td>
1510 1512 Specifying Multiple Revisions
1511 1513 </td></tr>
1512 1514 <tr><td>
1513 1515 <a href="/help/patterns">
1514 1516 patterns
1515 1517 </a>
1516 1518 </td><td>
1517 1519 File Name Patterns
1518 1520 </td></tr>
1519 1521 <tr><td>
1520 1522 <a href="/help/phases">
1521 1523 phases
1522 1524 </a>
1523 1525 </td><td>
1524 1526 Working with Phases
1525 1527 </td></tr>
1526 1528 <tr><td>
1527 1529 <a href="/help/revisions">
1528 1530 revisions
1529 1531 </a>
1530 1532 </td><td>
1531 1533 Specifying Single Revisions
1532 1534 </td></tr>
1533 1535 <tr><td>
1534 1536 <a href="/help/revsets">
1535 1537 revsets
1536 1538 </a>
1537 1539 </td><td>
1538 1540 Specifying Revision Sets
1539 1541 </td></tr>
1540 1542 <tr><td>
1541 1543 <a href="/help/scripting">
1542 1544 scripting
1543 1545 </a>
1544 1546 </td><td>
1545 1547 Using Mercurial from scripts and automation
1546 1548 </td></tr>
1547 1549 <tr><td>
1548 1550 <a href="/help/subrepos">
1549 1551 subrepos
1550 1552 </a>
1551 1553 </td><td>
1552 1554 Subrepositories
1553 1555 </td></tr>
1554 1556 <tr><td>
1555 1557 <a href="/help/templating">
1556 1558 templating
1557 1559 </a>
1558 1560 </td><td>
1559 1561 Template Usage
1560 1562 </td></tr>
1561 1563 <tr><td>
1562 1564 <a href="/help/urls">
1563 1565 urls
1564 1566 </a>
1565 1567 </td><td>
1566 1568 URL Paths
1567 1569 </td></tr>
1568 1570 <tr><td>
1569 1571 <a href="/help/topic-containing-verbose">
1570 1572 topic-containing-verbose
1571 1573 </a>
1572 1574 </td><td>
1573 1575 This is the topic to test omit indicating.
1574 1576 </td></tr>
1575 1577
1576 1578 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1577 1579
1578 1580 <tr><td>
1579 1581 <a href="/help/add">
1580 1582 add
1581 1583 </a>
1582 1584 </td><td>
1583 1585 add the specified files on the next commit
1584 1586 </td></tr>
1585 1587 <tr><td>
1586 1588 <a href="/help/annotate">
1587 1589 annotate
1588 1590 </a>
1589 1591 </td><td>
1590 1592 show changeset information by line for each file
1591 1593 </td></tr>
1592 1594 <tr><td>
1593 1595 <a href="/help/clone">
1594 1596 clone
1595 1597 </a>
1596 1598 </td><td>
1597 1599 make a copy of an existing repository
1598 1600 </td></tr>
1599 1601 <tr><td>
1600 1602 <a href="/help/commit">
1601 1603 commit
1602 1604 </a>
1603 1605 </td><td>
1604 1606 commit the specified files or all outstanding changes
1605 1607 </td></tr>
1606 1608 <tr><td>
1607 1609 <a href="/help/diff">
1608 1610 diff
1609 1611 </a>
1610 1612 </td><td>
1611 1613 diff repository (or selected files)
1612 1614 </td></tr>
1613 1615 <tr><td>
1614 1616 <a href="/help/export">
1615 1617 export
1616 1618 </a>
1617 1619 </td><td>
1618 1620 dump the header and diffs for one or more changesets
1619 1621 </td></tr>
1620 1622 <tr><td>
1621 1623 <a href="/help/forget">
1622 1624 forget
1623 1625 </a>
1624 1626 </td><td>
1625 1627 forget the specified files on the next commit
1626 1628 </td></tr>
1627 1629 <tr><td>
1628 1630 <a href="/help/init">
1629 1631 init
1630 1632 </a>
1631 1633 </td><td>
1632 1634 create a new repository in the given directory
1633 1635 </td></tr>
1634 1636 <tr><td>
1635 1637 <a href="/help/log">
1636 1638 log
1637 1639 </a>
1638 1640 </td><td>
1639 1641 show revision history of entire repository or files
1640 1642 </td></tr>
1641 1643 <tr><td>
1642 1644 <a href="/help/merge">
1643 1645 merge
1644 1646 </a>
1645 1647 </td><td>
1646 1648 merge another revision into working directory
1647 1649 </td></tr>
1648 1650 <tr><td>
1649 1651 <a href="/help/pull">
1650 1652 pull
1651 1653 </a>
1652 1654 </td><td>
1653 1655 pull changes from the specified source
1654 1656 </td></tr>
1655 1657 <tr><td>
1656 1658 <a href="/help/push">
1657 1659 push
1658 1660 </a>
1659 1661 </td><td>
1660 1662 push changes to the specified destination
1661 1663 </td></tr>
1662 1664 <tr><td>
1663 1665 <a href="/help/remove">
1664 1666 remove
1665 1667 </a>
1666 1668 </td><td>
1667 1669 remove the specified files on the next commit
1668 1670 </td></tr>
1669 1671 <tr><td>
1670 1672 <a href="/help/serve">
1671 1673 serve
1672 1674 </a>
1673 1675 </td><td>
1674 1676 start stand-alone webserver
1675 1677 </td></tr>
1676 1678 <tr><td>
1677 1679 <a href="/help/status">
1678 1680 status
1679 1681 </a>
1680 1682 </td><td>
1681 1683 show changed files in the working directory
1682 1684 </td></tr>
1683 1685 <tr><td>
1684 1686 <a href="/help/summary">
1685 1687 summary
1686 1688 </a>
1687 1689 </td><td>
1688 1690 summarize working directory state
1689 1691 </td></tr>
1690 1692 <tr><td>
1691 1693 <a href="/help/update">
1692 1694 update
1693 1695 </a>
1694 1696 </td><td>
1695 1697 update working directory (or switch revisions)
1696 1698 </td></tr>
1697 1699
1698 1700 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
1699 1701
1700 1702 <tr><td>
1701 1703 <a href="/help/addremove">
1702 1704 addremove
1703 1705 </a>
1704 1706 </td><td>
1705 1707 add all new files, delete all missing files
1706 1708 </td></tr>
1707 1709 <tr><td>
1708 1710 <a href="/help/archive">
1709 1711 archive
1710 1712 </a>
1711 1713 </td><td>
1712 1714 create an unversioned archive of a repository revision
1713 1715 </td></tr>
1714 1716 <tr><td>
1715 1717 <a href="/help/backout">
1716 1718 backout
1717 1719 </a>
1718 1720 </td><td>
1719 1721 reverse effect of earlier changeset
1720 1722 </td></tr>
1721 1723 <tr><td>
1722 1724 <a href="/help/bisect">
1723 1725 bisect
1724 1726 </a>
1725 1727 </td><td>
1726 1728 subdivision search of changesets
1727 1729 </td></tr>
1728 1730 <tr><td>
1729 1731 <a href="/help/bookmarks">
1730 1732 bookmarks
1731 1733 </a>
1732 1734 </td><td>
1733 1735 create a new bookmark or list existing bookmarks
1734 1736 </td></tr>
1735 1737 <tr><td>
1736 1738 <a href="/help/branch">
1737 1739 branch
1738 1740 </a>
1739 1741 </td><td>
1740 1742 set or show the current branch name
1741 1743 </td></tr>
1742 1744 <tr><td>
1743 1745 <a href="/help/branches">
1744 1746 branches
1745 1747 </a>
1746 1748 </td><td>
1747 1749 list repository named branches
1748 1750 </td></tr>
1749 1751 <tr><td>
1750 1752 <a href="/help/bundle">
1751 1753 bundle
1752 1754 </a>
1753 1755 </td><td>
1754 1756 create a changegroup file
1755 1757 </td></tr>
1756 1758 <tr><td>
1757 1759 <a href="/help/cat">
1758 1760 cat
1759 1761 </a>
1760 1762 </td><td>
1761 1763 output the current or given revision of files
1762 1764 </td></tr>
1763 1765 <tr><td>
1764 1766 <a href="/help/config">
1765 1767 config
1766 1768 </a>
1767 1769 </td><td>
1768 1770 show combined config settings from all hgrc files
1769 1771 </td></tr>
1770 1772 <tr><td>
1771 1773 <a href="/help/copy">
1772 1774 copy
1773 1775 </a>
1774 1776 </td><td>
1775 1777 mark files as copied for the next commit
1776 1778 </td></tr>
1777 1779 <tr><td>
1778 1780 <a href="/help/files">
1779 1781 files
1780 1782 </a>
1781 1783 </td><td>
1782 1784 list tracked files
1783 1785 </td></tr>
1784 1786 <tr><td>
1785 1787 <a href="/help/graft">
1786 1788 graft
1787 1789 </a>
1788 1790 </td><td>
1789 1791 copy changes from other branches onto the current branch
1790 1792 </td></tr>
1791 1793 <tr><td>
1792 1794 <a href="/help/grep">
1793 1795 grep
1794 1796 </a>
1795 1797 </td><td>
1796 1798 search for a pattern in specified files and revisions
1797 1799 </td></tr>
1798 1800 <tr><td>
1799 1801 <a href="/help/heads">
1800 1802 heads
1801 1803 </a>
1802 1804 </td><td>
1803 1805 show branch heads
1804 1806 </td></tr>
1805 1807 <tr><td>
1806 1808 <a href="/help/help">
1807 1809 help
1808 1810 </a>
1809 1811 </td><td>
1810 1812 show help for a given topic or a help overview
1811 1813 </td></tr>
1812 1814 <tr><td>
1813 1815 <a href="/help/identify">
1814 1816 identify
1815 1817 </a>
1816 1818 </td><td>
1817 1819 identify the working directory or specified revision
1818 1820 </td></tr>
1819 1821 <tr><td>
1820 1822 <a href="/help/import">
1821 1823 import
1822 1824 </a>
1823 1825 </td><td>
1824 1826 import an ordered set of patches
1825 1827 </td></tr>
1826 1828 <tr><td>
1827 1829 <a href="/help/incoming">
1828 1830 incoming
1829 1831 </a>
1830 1832 </td><td>
1831 1833 show new changesets found in source
1832 1834 </td></tr>
1833 1835 <tr><td>
1834 1836 <a href="/help/manifest">
1835 1837 manifest
1836 1838 </a>
1837 1839 </td><td>
1838 1840 output the current or given revision of the project manifest
1839 1841 </td></tr>
1840 1842 <tr><td>
1841 1843 <a href="/help/nohelp">
1842 1844 nohelp
1843 1845 </a>
1844 1846 </td><td>
1845 1847 (no help text available)
1846 1848 </td></tr>
1847 1849 <tr><td>
1848 1850 <a href="/help/outgoing">
1849 1851 outgoing
1850 1852 </a>
1851 1853 </td><td>
1852 1854 show changesets not found in the destination
1853 1855 </td></tr>
1854 1856 <tr><td>
1855 1857 <a href="/help/paths">
1856 1858 paths
1857 1859 </a>
1858 1860 </td><td>
1859 1861 show aliases for remote repositories
1860 1862 </td></tr>
1861 1863 <tr><td>
1862 1864 <a href="/help/phase">
1863 1865 phase
1864 1866 </a>
1865 1867 </td><td>
1866 1868 set or show the current phase name
1867 1869 </td></tr>
1868 1870 <tr><td>
1869 1871 <a href="/help/recover">
1870 1872 recover
1871 1873 </a>
1872 1874 </td><td>
1873 1875 roll back an interrupted transaction
1874 1876 </td></tr>
1875 1877 <tr><td>
1876 1878 <a href="/help/rename">
1877 1879 rename
1878 1880 </a>
1879 1881 </td><td>
1880 1882 rename files; equivalent of copy + remove
1881 1883 </td></tr>
1882 1884 <tr><td>
1883 1885 <a href="/help/resolve">
1884 1886 resolve
1885 1887 </a>
1886 1888 </td><td>
1887 1889 redo merges or set/view the merge status of files
1888 1890 </td></tr>
1889 1891 <tr><td>
1890 1892 <a href="/help/revert">
1891 1893 revert
1892 1894 </a>
1893 1895 </td><td>
1894 1896 restore files to their checkout state
1895 1897 </td></tr>
1896 1898 <tr><td>
1897 1899 <a href="/help/root">
1898 1900 root
1899 1901 </a>
1900 1902 </td><td>
1901 1903 print the root (top) of the current working directory
1902 1904 </td></tr>
1903 1905 <tr><td>
1904 1906 <a href="/help/tag">
1905 1907 tag
1906 1908 </a>
1907 1909 </td><td>
1908 1910 add one or more tags for the current or given revision
1909 1911 </td></tr>
1910 1912 <tr><td>
1911 1913 <a href="/help/tags">
1912 1914 tags
1913 1915 </a>
1914 1916 </td><td>
1915 1917 list repository tags
1916 1918 </td></tr>
1917 1919 <tr><td>
1918 1920 <a href="/help/unbundle">
1919 1921 unbundle
1920 1922 </a>
1921 1923 </td><td>
1922 1924 apply one or more changegroup files
1923 1925 </td></tr>
1924 1926 <tr><td>
1925 1927 <a href="/help/verify">
1926 1928 verify
1927 1929 </a>
1928 1930 </td><td>
1929 1931 verify the integrity of the repository
1930 1932 </td></tr>
1931 1933 <tr><td>
1932 1934 <a href="/help/version">
1933 1935 version
1934 1936 </a>
1935 1937 </td><td>
1936 1938 output version and copyright information
1937 1939 </td></tr>
1938 1940 </table>
1939 1941 </div>
1940 1942 </div>
1941 1943
1942 1944 <script type="text/javascript">process_dates()</script>
1943 1945
1944 1946
1945 1947 </body>
1946 1948 </html>
1947 1949
1948 1950
1949 1951 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
1950 1952 200 Script output follows
1951 1953
1952 1954 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1953 1955 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1954 1956 <head>
1955 1957 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1956 1958 <meta name="robots" content="index, nofollow" />
1957 1959 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1958 1960 <script type="text/javascript" src="/static/mercurial.js"></script>
1959 1961
1960 1962 <title>Help: add</title>
1961 1963 </head>
1962 1964 <body>
1963 1965
1964 1966 <div class="container">
1965 1967 <div class="menu">
1966 1968 <div class="logo">
1967 1969 <a href="https://mercurial-scm.org/">
1968 1970 <img src="/static/hglogo.png" alt="mercurial" /></a>
1969 1971 </div>
1970 1972 <ul>
1971 1973 <li><a href="/shortlog">log</a></li>
1972 1974 <li><a href="/graph">graph</a></li>
1973 1975 <li><a href="/tags">tags</a></li>
1974 1976 <li><a href="/bookmarks">bookmarks</a></li>
1975 1977 <li><a href="/branches">branches</a></li>
1976 1978 </ul>
1977 1979 <ul>
1978 1980 <li class="active"><a href="/help">help</a></li>
1979 1981 </ul>
1980 1982 </div>
1981 1983
1982 1984 <div class="main">
1983 1985 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1984 1986 <h3>Help: add</h3>
1985 1987
1986 1988 <form class="search" action="/log">
1987 1989
1988 1990 <p><input name="rev" id="search1" type="text" size="30" /></p>
1989 1991 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1990 1992 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1991 1993 </form>
1992 1994 <div id="doc">
1993 1995 <p>
1994 1996 hg add [OPTION]... [FILE]...
1995 1997 </p>
1996 1998 <p>
1997 1999 add the specified files on the next commit
1998 2000 </p>
1999 2001 <p>
2000 2002 Schedule files to be version controlled and added to the
2001 2003 repository.
2002 2004 </p>
2003 2005 <p>
2004 2006 The files will be added to the repository at the next commit. To
2005 2007 undo an add before that, see &quot;hg forget&quot;.
2006 2008 </p>
2007 2009 <p>
2008 2010 If no names are given, add all files to the repository.
2009 2011 </p>
2010 2012 <p>
2011 2013 Examples:
2012 2014 </p>
2013 2015 <ul>
2014 2016 <li> New (unknown) files are added automatically by &quot;hg add&quot;:
2015 2017 <pre>
2016 2018 \$ ls (re)
2017 2019 foo.c
2018 2020 \$ hg status (re)
2019 2021 ? foo.c
2020 2022 \$ hg add (re)
2021 2023 adding foo.c
2022 2024 \$ hg status (re)
2023 2025 A foo.c
2024 2026 </pre>
2025 2027 <li> Specific files to be added can be specified:
2026 2028 <pre>
2027 2029 \$ ls (re)
2028 2030 bar.c foo.c
2029 2031 \$ hg status (re)
2030 2032 ? bar.c
2031 2033 ? foo.c
2032 2034 \$ hg add bar.c (re)
2033 2035 \$ hg status (re)
2034 2036 A bar.c
2035 2037 ? foo.c
2036 2038 </pre>
2037 2039 </ul>
2038 2040 <p>
2039 2041 Returns 0 if all files are successfully added.
2040 2042 </p>
2041 2043 <p>
2042 2044 options ([+] can be repeated):
2043 2045 </p>
2044 2046 <table>
2045 2047 <tr><td>-I</td>
2046 2048 <td>--include PATTERN [+]</td>
2047 2049 <td>include names matching the given patterns</td></tr>
2048 2050 <tr><td>-X</td>
2049 2051 <td>--exclude PATTERN [+]</td>
2050 2052 <td>exclude names matching the given patterns</td></tr>
2051 2053 <tr><td>-S</td>
2052 2054 <td>--subrepos</td>
2053 2055 <td>recurse into subrepositories</td></tr>
2054 2056 <tr><td>-n</td>
2055 2057 <td>--dry-run</td>
2056 2058 <td>do not perform actions, just print output</td></tr>
2057 2059 </table>
2058 2060 <p>
2059 2061 global options ([+] can be repeated):
2060 2062 </p>
2061 2063 <table>
2062 2064 <tr><td>-R</td>
2063 2065 <td>--repository REPO</td>
2064 2066 <td>repository root directory or name of overlay bundle file</td></tr>
2065 2067 <tr><td></td>
2066 2068 <td>--cwd DIR</td>
2067 2069 <td>change working directory</td></tr>
2068 2070 <tr><td>-y</td>
2069 2071 <td>--noninteractive</td>
2070 2072 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2071 2073 <tr><td>-q</td>
2072 2074 <td>--quiet</td>
2073 2075 <td>suppress output</td></tr>
2074 2076 <tr><td>-v</td>
2075 2077 <td>--verbose</td>
2076 2078 <td>enable additional output</td></tr>
2077 2079 <tr><td></td>
2078 2080 <td>--config CONFIG [+]</td>
2079 2081 <td>set/override config option (use 'section.name=value')</td></tr>
2080 2082 <tr><td></td>
2081 2083 <td>--debug</td>
2082 2084 <td>enable debugging output</td></tr>
2083 2085 <tr><td></td>
2084 2086 <td>--debugger</td>
2085 2087 <td>start debugger</td></tr>
2086 2088 <tr><td></td>
2087 2089 <td>--encoding ENCODE</td>
2088 2090 <td>set the charset encoding (default: ascii)</td></tr>
2089 2091 <tr><td></td>
2090 2092 <td>--encodingmode MODE</td>
2091 2093 <td>set the charset encoding mode (default: strict)</td></tr>
2092 2094 <tr><td></td>
2093 2095 <td>--traceback</td>
2094 2096 <td>always print a traceback on exception</td></tr>
2095 2097 <tr><td></td>
2096 2098 <td>--time</td>
2097 2099 <td>time how long the command takes</td></tr>
2098 2100 <tr><td></td>
2099 2101 <td>--profile</td>
2100 2102 <td>print command execution profile</td></tr>
2101 2103 <tr><td></td>
2102 2104 <td>--version</td>
2103 2105 <td>output version information and exit</td></tr>
2104 2106 <tr><td>-h</td>
2105 2107 <td>--help</td>
2106 2108 <td>display help and exit</td></tr>
2107 2109 <tr><td></td>
2108 2110 <td>--hidden</td>
2109 2111 <td>consider hidden changesets</td></tr>
2110 2112 </table>
2111 2113
2112 2114 </div>
2113 2115 </div>
2114 2116 </div>
2115 2117
2116 2118 <script type="text/javascript">process_dates()</script>
2117 2119
2118 2120
2119 2121 </body>
2120 2122 </html>
2121 2123
2122 2124
2123 2125 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2124 2126 200 Script output follows
2125 2127
2126 2128 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2127 2129 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2128 2130 <head>
2129 2131 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2130 2132 <meta name="robots" content="index, nofollow" />
2131 2133 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2132 2134 <script type="text/javascript" src="/static/mercurial.js"></script>
2133 2135
2134 2136 <title>Help: remove</title>
2135 2137 </head>
2136 2138 <body>
2137 2139
2138 2140 <div class="container">
2139 2141 <div class="menu">
2140 2142 <div class="logo">
2141 2143 <a href="https://mercurial-scm.org/">
2142 2144 <img src="/static/hglogo.png" alt="mercurial" /></a>
2143 2145 </div>
2144 2146 <ul>
2145 2147 <li><a href="/shortlog">log</a></li>
2146 2148 <li><a href="/graph">graph</a></li>
2147 2149 <li><a href="/tags">tags</a></li>
2148 2150 <li><a href="/bookmarks">bookmarks</a></li>
2149 2151 <li><a href="/branches">branches</a></li>
2150 2152 </ul>
2151 2153 <ul>
2152 2154 <li class="active"><a href="/help">help</a></li>
2153 2155 </ul>
2154 2156 </div>
2155 2157
2156 2158 <div class="main">
2157 2159 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2158 2160 <h3>Help: remove</h3>
2159 2161
2160 2162 <form class="search" action="/log">
2161 2163
2162 2164 <p><input name="rev" id="search1" type="text" size="30" /></p>
2163 2165 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2164 2166 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2165 2167 </form>
2166 2168 <div id="doc">
2167 2169 <p>
2168 2170 hg remove [OPTION]... FILE...
2169 2171 </p>
2170 2172 <p>
2171 2173 aliases: rm
2172 2174 </p>
2173 2175 <p>
2174 2176 remove the specified files on the next commit
2175 2177 </p>
2176 2178 <p>
2177 2179 Schedule the indicated files for removal from the current branch.
2178 2180 </p>
2179 2181 <p>
2180 2182 This command schedules the files to be removed at the next commit.
2181 2183 To undo a remove before that, see &quot;hg revert&quot;. To undo added
2182 2184 files, see &quot;hg forget&quot;.
2183 2185 </p>
2184 2186 <p>
2185 2187 -A/--after can be used to remove only files that have already
2186 2188 been deleted, -f/--force can be used to force deletion, and -Af
2187 2189 can be used to remove files from the next revision without
2188 2190 deleting them from the working directory.
2189 2191 </p>
2190 2192 <p>
2191 2193 The following table details the behavior of remove for different
2192 2194 file states (columns) and option combinations (rows). The file
2193 2195 states are Added [A], Clean [C], Modified [M] and Missing [!]
2194 2196 (as reported by &quot;hg status&quot;). The actions are Warn, Remove
2195 2197 (from branch) and Delete (from disk):
2196 2198 </p>
2197 2199 <table>
2198 2200 <tr><td>opt/state</td>
2199 2201 <td>A</td>
2200 2202 <td>C</td>
2201 2203 <td>M</td>
2202 2204 <td>!</td></tr>
2203 2205 <tr><td>none</td>
2204 2206 <td>W</td>
2205 2207 <td>RD</td>
2206 2208 <td>W</td>
2207 2209 <td>R</td></tr>
2208 2210 <tr><td>-f</td>
2209 2211 <td>R</td>
2210 2212 <td>RD</td>
2211 2213 <td>RD</td>
2212 2214 <td>R</td></tr>
2213 2215 <tr><td>-A</td>
2214 2216 <td>W</td>
2215 2217 <td>W</td>
2216 2218 <td>W</td>
2217 2219 <td>R</td></tr>
2218 2220 <tr><td>-Af</td>
2219 2221 <td>R</td>
2220 2222 <td>R</td>
2221 2223 <td>R</td>
2222 2224 <td>R</td></tr>
2223 2225 </table>
2224 2226 <p>
2225 2227 Note that remove never deletes files in Added [A] state from the
2226 2228 working directory, not even if option --force is specified.
2227 2229 </p>
2228 2230 <p>
2229 2231 Returns 0 on success, 1 if any warnings encountered.
2230 2232 </p>
2231 2233 <p>
2232 2234 options ([+] can be repeated):
2233 2235 </p>
2234 2236 <table>
2235 2237 <tr><td>-A</td>
2236 2238 <td>--after</td>
2237 2239 <td>record delete for missing files</td></tr>
2238 2240 <tr><td>-f</td>
2239 2241 <td>--force</td>
2240 2242 <td>remove (and delete) file even if added or modified</td></tr>
2241 2243 <tr><td>-S</td>
2242 2244 <td>--subrepos</td>
2243 2245 <td>recurse into subrepositories</td></tr>
2244 2246 <tr><td>-I</td>
2245 2247 <td>--include PATTERN [+]</td>
2246 2248 <td>include names matching the given patterns</td></tr>
2247 2249 <tr><td>-X</td>
2248 2250 <td>--exclude PATTERN [+]</td>
2249 2251 <td>exclude names matching the given patterns</td></tr>
2250 2252 </table>
2251 2253 <p>
2252 2254 global options ([+] can be repeated):
2253 2255 </p>
2254 2256 <table>
2255 2257 <tr><td>-R</td>
2256 2258 <td>--repository REPO</td>
2257 2259 <td>repository root directory or name of overlay bundle file</td></tr>
2258 2260 <tr><td></td>
2259 2261 <td>--cwd DIR</td>
2260 2262 <td>change working directory</td></tr>
2261 2263 <tr><td>-y</td>
2262 2264 <td>--noninteractive</td>
2263 2265 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2264 2266 <tr><td>-q</td>
2265 2267 <td>--quiet</td>
2266 2268 <td>suppress output</td></tr>
2267 2269 <tr><td>-v</td>
2268 2270 <td>--verbose</td>
2269 2271 <td>enable additional output</td></tr>
2270 2272 <tr><td></td>
2271 2273 <td>--config CONFIG [+]</td>
2272 2274 <td>set/override config option (use 'section.name=value')</td></tr>
2273 2275 <tr><td></td>
2274 2276 <td>--debug</td>
2275 2277 <td>enable debugging output</td></tr>
2276 2278 <tr><td></td>
2277 2279 <td>--debugger</td>
2278 2280 <td>start debugger</td></tr>
2279 2281 <tr><td></td>
2280 2282 <td>--encoding ENCODE</td>
2281 2283 <td>set the charset encoding (default: ascii)</td></tr>
2282 2284 <tr><td></td>
2283 2285 <td>--encodingmode MODE</td>
2284 2286 <td>set the charset encoding mode (default: strict)</td></tr>
2285 2287 <tr><td></td>
2286 2288 <td>--traceback</td>
2287 2289 <td>always print a traceback on exception</td></tr>
2288 2290 <tr><td></td>
2289 2291 <td>--time</td>
2290 2292 <td>time how long the command takes</td></tr>
2291 2293 <tr><td></td>
2292 2294 <td>--profile</td>
2293 2295 <td>print command execution profile</td></tr>
2294 2296 <tr><td></td>
2295 2297 <td>--version</td>
2296 2298 <td>output version information and exit</td></tr>
2297 2299 <tr><td>-h</td>
2298 2300 <td>--help</td>
2299 2301 <td>display help and exit</td></tr>
2300 2302 <tr><td></td>
2301 2303 <td>--hidden</td>
2302 2304 <td>consider hidden changesets</td></tr>
2303 2305 </table>
2304 2306
2305 2307 </div>
2306 2308 </div>
2307 2309 </div>
2308 2310
2309 2311 <script type="text/javascript">process_dates()</script>
2310 2312
2311 2313
2312 2314 </body>
2313 2315 </html>
2314 2316
2315 2317
2316 2318 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2317 2319 200 Script output follows
2318 2320
2319 2321 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2320 2322 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2321 2323 <head>
2322 2324 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2323 2325 <meta name="robots" content="index, nofollow" />
2324 2326 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2325 2327 <script type="text/javascript" src="/static/mercurial.js"></script>
2326 2328
2327 2329 <title>Help: revisions</title>
2328 2330 </head>
2329 2331 <body>
2330 2332
2331 2333 <div class="container">
2332 2334 <div class="menu">
2333 2335 <div class="logo">
2334 2336 <a href="https://mercurial-scm.org/">
2335 2337 <img src="/static/hglogo.png" alt="mercurial" /></a>
2336 2338 </div>
2337 2339 <ul>
2338 2340 <li><a href="/shortlog">log</a></li>
2339 2341 <li><a href="/graph">graph</a></li>
2340 2342 <li><a href="/tags">tags</a></li>
2341 2343 <li><a href="/bookmarks">bookmarks</a></li>
2342 2344 <li><a href="/branches">branches</a></li>
2343 2345 </ul>
2344 2346 <ul>
2345 2347 <li class="active"><a href="/help">help</a></li>
2346 2348 </ul>
2347 2349 </div>
2348 2350
2349 2351 <div class="main">
2350 2352 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2351 2353 <h3>Help: revisions</h3>
2352 2354
2353 2355 <form class="search" action="/log">
2354 2356
2355 2357 <p><input name="rev" id="search1" type="text" size="30" /></p>
2356 2358 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2357 2359 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2358 2360 </form>
2359 2361 <div id="doc">
2360 2362 <h1>Specifying Single Revisions</h1>
2361 2363 <p>
2362 2364 Mercurial supports several ways to specify individual revisions.
2363 2365 </p>
2364 2366 <p>
2365 2367 A plain integer is treated as a revision number. Negative integers are
2366 2368 treated as sequential offsets from the tip, with -1 denoting the tip,
2367 2369 -2 denoting the revision prior to the tip, and so forth.
2368 2370 </p>
2369 2371 <p>
2370 2372 A 40-digit hexadecimal string is treated as a unique revision
2371 2373 identifier.
2372 2374 </p>
2373 2375 <p>
2374 2376 A hexadecimal string less than 40 characters long is treated as a
2375 2377 unique revision identifier and is referred to as a short-form
2376 2378 identifier. A short-form identifier is only valid if it is the prefix
2377 2379 of exactly one full-length identifier.
2378 2380 </p>
2379 2381 <p>
2380 2382 Any other string is treated as a bookmark, tag, or branch name. A
2381 2383 bookmark is a movable pointer to a revision. A tag is a permanent name
2382 2384 associated with a revision. A branch name denotes the tipmost open branch head
2383 2385 of that branch - or if they are all closed, the tipmost closed head of the
2384 2386 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2385 2387 </p>
2386 2388 <p>
2387 2389 The reserved name &quot;tip&quot; always identifies the most recent revision.
2388 2390 </p>
2389 2391 <p>
2390 2392 The reserved name &quot;null&quot; indicates the null revision. This is the
2391 2393 revision of an empty repository, and the parent of revision 0.
2392 2394 </p>
2393 2395 <p>
2394 2396 The reserved name &quot;.&quot; indicates the working directory parent. If no
2395 2397 working directory is checked out, it is equivalent to null. If an
2396 2398 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2397 2399 parent.
2398 2400 </p>
2399 2401
2400 2402 </div>
2401 2403 </div>
2402 2404 </div>
2403 2405
2404 2406 <script type="text/javascript">process_dates()</script>
2405 2407
2406 2408
2407 2409 </body>
2408 2410 </html>
2409 2411
2410 2412
2411 2413 $ killdaemons.py
2412 2414
2413 2415 #endif
General Comments 0
You need to be logged in to leave comments. Login now